#! /usr/bin/env python # -*- coding: utf-8 -*- # vim:fenc=utf-8 # # Copyright © 2017 lafrite # # Distributed under terms of the MIT license. """ Multiply MO """ from multipledispatch import Dispatcher from ..tree import Tree from ..MO.mo import MO, MOnumber, MOstr from ..MO.fraction import MOFraction from ..MO.monomial import MOstrPower, MOMonomial from .exceptions import MultiplyError from .filters import special_case multiply_doc = """ Multiply MOs :param left: left MO :param right: right MO :returns: Tree or MO """ 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 >>> a = MOnumber(4) >>> b = MOnumber(6) >>> multiply(a, b) """ 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 >>> a = MOnumber(4) >>> b = MOFraction(6, 5) >>> print(multiply(a, b)) / > * | > 4 | > 6 > 5 >>> b = MOFraction(6, 5, True) >>> print(multiply(a, b)) / > * | > 4 | > - | | > None | | > 6 > 5 """ num = Tree("*", left, right.numerator) 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 >>> a = MOFraction(6, 5) >>> b = MOnumber(4) >>> print(multiply(a, b)) / > * | > 6 | > 4 > 5 """ num = Tree("*", left.numerator, 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) >>> a = MOFraction(1, 5) >>> b = MOFraction(4, 5) >>> print(multiply(a, b)) / > * | > 1 | > 4 > * | > 5 | > 5 """ num = Tree("*", left.numerator, right.numerator) denom = Tree("*", left.denominator, right.denominator) 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 >>> a = MOnumber(2) >>> b = MOstr('x') >>> multiply(a, b) >>> a = MOFraction(1, 5) >>> multiply(a, b) """ 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 >>> a = MOstr('x') >>> b = MOnumber(2) >>> multiply(a, b) >>> b = MOFraction(1, 5) >>> multiply(a, b) """ return MOMonomial(right, left) @multiply.register((MOnumber, MOFraction), MOstrPower) @special_case(multiply_filter) def moscalar_mostrpower(left, right): """ Multiply a scalar with a MOstrPower >>> a = MOnumber(4) >>> x = MOstrPower('x', 4) >>> print(multiply(a, x)) * > 4 > ^ | > x | > 4 """ return MOMonomial(left, right) @multiply.register(MOstrPower, (MOnumber, MOFraction)) @special_case(multiply_filter) def mostrpower_moscalar(left, right): """ Multiply a MOstrPower with a scalar >>> a = MOnumber(4) >>> x = MOstrPower('x', 4) >>> print(multiply(x, a)) * > 4 > ^ | > x | > 4 """ return MOMonomial(right, left) @multiply.register((MOnumber, MOFraction), MOMonomial) @special_case(multiply_filter) def moscalar_monomonial(left, right): """ Multiply a scalar with a monomial >>> a = MOnumber(4) >>> x = MOstrPower('x', 4) >>> b = MOMonomial(5, x) >>> print(multiply(a, b)) * > * | > 4 | > 5 > ^ | > x | > 4 """ coefficient = Tree('*', left, right.coefficient) return Tree('*', coefficient, right.strpower) @multiply.register(MOMonomial, (MOnumber, MOFraction)) @special_case(multiply_filter) def monomonial_moscalar(left, right): """ Multiply a momonial with a scalar >>> x = MOstrPower('x', 4) >>> a = MOMonomial(5, x) >>> b = MOnumber(4) >>> print(multiply(a, b)) * > * | > 4 | > 5 > ^ | > x | > 4 """ coefficient = Tree('*', right, left.coefficient) return Tree('*', coefficient, left.strpower) @multiply.register(MOstr, MOstrPower) @special_case(multiply_filter) def mostr_mostrpower(left, right): """ Multiply a MOstr and a MOstrPower >>> a = MOstr('x') >>> b = MOstrPower('x', 4) >>> multiply(a, b) >>> a = MOstr('x') >>> b = MOstrPower('y', 4) >>> multiply(a, b) Traceback (most recent call last): ... mapytex.calculus.core.compute.exceptions.MultiplyError: Can't multiply MOstr and MOstrPower if they don'thave same variable (got x and y) """ if left.variable != right.variable: raise MultiplyError("Can't multiply MOstr and MOstrPower if they don't" f"have same variable (got {left.variable} and {right.variable})") return MOstrPower(left.variable, right.power+1) # ----------------------------- # Reglages pour 'vim' # vim:set autoindent expandtab tabstop=4 shiftwidth=4: # cursor: 16 del