diff --git a/mapytex/calculus/core/compute/add.py b/mapytex/calculus/core/compute/add.py index b566140..691d16a 100644 --- a/mapytex/calculus/core/compute/add.py +++ b/mapytex/calculus/core/compute/add.py @@ -10,13 +10,14 @@ Adding MO """ +from functools import wraps from multipledispatch import Dispatcher from ..tree import Tree from ..MO.mo import MO, MOnumber from ..MO.fraction import MOFraction from .exceptions import AddError from .arithmetic import lcm -from .type_filter import args_are +from .filters import special_case add_doc = """ Adding MOs @@ -25,9 +26,36 @@ add_doc = """ Adding MOs :return: Tree or MO """ + add = Dispatcher("add", doc=add_doc) +def add_filter(left, right): + """ Automatic add on MO + + :param left: MO + :param right: MO + :returns: MO if it is a special case, nothing other wise + + >>> a = MOnumber(0) + >>> b = MOFraction(1, 2) + >>> add(a, b) + + >>> add(b, a) + + """ + try: + if left == 0: + return right + except TypeError: + pass + try: + if right == 0: + return left + except TypeError: + pass + @add.register(MOnumber, MOnumber) +@special_case(add_filter) def monumber_monumber(left, right): """ Simply add MO value @@ -40,6 +68,7 @@ def monumber_monumber(left, right): return MO.factory(left.value + right.value) @add.register(MOnumber, MOFraction) +@special_case(add_filter) def monumber_mofraction(left, right): """ Return a tree with the MOnumber transformed into a MOFraction @@ -58,6 +87,7 @@ def monumber_mofraction(left, right): return Tree("+", left_fraction, right) @add.register(MOFraction, MOnumber) +@special_case(add_filter) def mofraction_monumber(left, right): """ Return a tree with the MOnumber transformed into a MOFraction @@ -76,6 +106,7 @@ def mofraction_monumber(left, right): return Tree("+", left, right_fraction) @add.register(MOFraction, MOFraction) +@special_case(add_filter) def mofraction_mofraction(left, right): """ 3 differents cases: diff --git a/mapytex/calculus/core/compute/divide.py b/mapytex/calculus/core/compute/divide.py index 025083f..ec9afb7 100644 --- a/mapytex/calculus/core/compute/divide.py +++ b/mapytex/calculus/core/compute/divide.py @@ -15,7 +15,7 @@ from ..tree import Tree from ..MO.mo import MO, MOnumber from ..MO.fraction import MOFraction from .exceptions import DivideError -from .type_filter import args_are +from .filters import special_case divide_doc = """ Dividing MOs @@ -27,7 +27,42 @@ divide_doc = """ Dividing MOs divide = Dispatcher("divide", doc=divide_doc) +def divide_filter(left, right): + """ Automatic divide on MO + + >>> a = MOnumber(4) + >>> b = MOnumber(1) + >>> divide(a, b) + + >>> a = MOnumber(0) + >>> b = MOnumber(1) + >>> divide(a, b) + + >>> a = MOnumber(4) + >>> b = MOnumber(0) + >>> divide(a, b) + Traceback (most recent call last): + ... + mapytex.calculus.core.compute.exceptions.DivideError: Division by zero + """ + try: + if left == 0: + return left + except TypeError: + pass + try: + if right == 1: + return left + except TypeError: + pass + try: + if right == 0: + raise DivideError("Division by zero") + except TypeError: + pass + @divide.register(MOnumber, MOnumber) +@special_case(divide_filter) def monumber_monumber(left, right): """ Divide 2 monumbers and return a MOFraction @@ -39,6 +74,7 @@ def monumber_monumber(left, right): return MOFraction(left, right) @divide.register(MOnumber, MOFraction) +@special_case(divide_filter) def monumber_mofraction(left, right): """ Divide a monumber and a mofraction by inverting MOFraction @@ -63,6 +99,7 @@ def monumber_mofraction(left, right): return Tree("*", left, right.inverse()) @divide.register(MOFraction, MOnumber) +@special_case(divide_filter) def mofraction_monumber(left, right): """ Divide a monumber and a mofraction by inverting MOnumber @@ -82,6 +119,7 @@ def mofraction_monumber(left, right): return Tree("*", left, right_fraction) @divide.register(MOFraction, MOFraction) +@special_case(divide_filter) def mofraction_mofraction(left, right): """ Divide two mofractions by inverting right MOFraction @@ -99,37 +137,6 @@ def mofraction_mofraction(left, right): """ return Tree("*", left, right.inverse()) -#def divide(left, right): -# """ Perform the addition of left and right -# -# :param left: left MO -# :param right: right MO -# :returns: Tree or MO -# -# >>> a = MOnumber(4) -# >>> b = MOnumber(6) -# >>> divide(a, b) -# -# >>> b = MOnumber(0) -# >>> divide(a, b) -# Traceback (most recent call last): -# ... -# mapytex.calculus.core.compute.exceptions.DivideError: Division by zero -# -# """ -# try: -# right.value -# except AttributeError: -# pass -# else: -# if right.value == 0: -# raise DivideError("Division by zero") -# -# if right.value == 1: -# return left -# -# return MULFUNCTIONS[(type(left), type(right))](left, right) - # ----------------------------- # Reglages pour 'vim' # vim:set autoindent expandtab tabstop=4 shiftwidth=4: diff --git a/mapytex/calculus/core/compute/type_filter.py b/mapytex/calculus/core/compute/filters.py similarity index 76% rename from mapytex/calculus/core/compute/type_filter.py rename to mapytex/calculus/core/compute/filters.py index 64e5417..fd4a2c8 100644 --- a/mapytex/calculus/core/compute/type_filter.py +++ b/mapytex/calculus/core/compute/filters.py @@ -36,7 +36,22 @@ def args_are(left_type, right_type): return filtered_func return type_filter +def special_case(filter): + """ Decorate operation to filter special cases before call the function + :param filter: (MO, MO) -> MO or Tree + :returns: decorator + + """ + def decorator(func): + @wraps(func) + def _func(left, right): + ans = filter(left, right) + if ans is None: + return func(left, right) + return ans + return _func + return decorator # ----------------------------- # Reglages pour 'vim' diff --git a/mapytex/calculus/core/compute/multiply.py b/mapytex/calculus/core/compute/multiply.py index 079b07d..86612d9 100644 --- a/mapytex/calculus/core/compute/multiply.py +++ b/mapytex/calculus/core/compute/multiply.py @@ -16,7 +16,7 @@ from ..MO.mo import MO, MOnumber, MOstr from ..MO.fraction import MOFraction from ..MO.monomial import MOMonomial from .exceptions import MultiplyError -from .type_filter import args_are +from .filters import special_case multiply_doc = """ Multiply MOs @@ -28,7 +28,48 @@ multiply_doc = """ Multiply MOs multiply = Dispatcher("multiply", doc=multiply_doc) +def multiply_filter(left, right): + """ Automatic multiply on MO + + :param left: MO + :param right: MO + :returns: MO if it is a special case, nothing other wise + + >>> a = MOnumber(1) + >>> b = MOFraction(1, 2) + >>> multiply(a, b) + + >>> multiply(b, a) + + >>> a = MOnumber(0) + >>> b = MOFraction(1, 2) + >>> multiply(a, b) + + """ + try: + if left == 0: + return left + except TypeError: + pass + try: + if right == 0: + return right + except TypeError: + pass + + try: + if left == 1: + return right + except TypeError: + pass + try: + if right == 1: + return left + except TypeError: + pass + @multiply.register(MOnumber, MOnumber) +@special_case(multiply_filter) def monumber_monumber(left, right): """ Simply multiply values @@ -41,6 +82,7 @@ def monumber_monumber(left, right): return MO.factory(left.value * right.value) @multiply.register(MOnumber, MOFraction) +@special_case(multiply_filter) def monumber_mofraction(left, right): """ Return division Tree with on the numertor MOnumber times numerator of MOFraction @@ -67,6 +109,7 @@ def monumber_mofraction(left, right): return Tree("/", num, right._denominator) @multiply.register(MOFraction, MOnumber) +@special_case(multiply_filter) def mofraction_monumber(left, right): """ Return division Tree with on the numertor MOnumber times numerator of MOFraction @@ -83,6 +126,7 @@ def mofraction_monumber(left, right): return Tree("/", num, left._denominator) @multiply.register(MOFraction, MOFraction) +@special_case(multiply_filter) def mofraction_mofraction(left, right): """ Multiply two mofractions (numertors together and denominators together) @@ -102,6 +146,7 @@ def mofraction_mofraction(left, right): return Tree("/", num, denom) @multiply.register((MOnumber, MOFraction), MOstr) +@special_case(multiply_filter) def moscalar_mostr(left, right): """ Multiply a scalar with a letter to create a MOMonomial @@ -116,6 +161,7 @@ def moscalar_mostr(left, right): return MOMonomial(left, right) @multiply.register(MOstr, (MOnumber, MOFraction)) +@special_case(multiply_filter) def mostr_moscalar(left, right): """ Multiply a scalar with a letter to create a MOMonomial @@ -130,6 +176,7 @@ def mostr_moscalar(left, right): return MOMonomial(right, left) @multiply.register((MOnumber, MOFraction), MOMonomial) +@special_case(multiply_filter) def moscalar_monomonial(left, right): """ Multiply a scalar with a monomial