| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- from ..node import Scope, nary_node, OP_ADD, OP_MUL, OP_DIV
- from ..possibilities import Possibility as P, MESSAGES
- from ..translate import _
- def match_negated_factor(node):
- """
- This rule assures that negations in the scope of a multiplication are
- brought `outside', to the multiplication itself.
- Example:
- a * -b -> -(ab)
- """
- assert node.is_op(OP_MUL)
- p = []
- scope = Scope(node)
- for factor in scope:
- if factor.negated:
- p.append(P(node, negated_factor, (scope, factor)))
- return p
- def negated_factor(root, args):
- """
- a * -b -> -(ab)
- """
- scope, factor = args
- scope.replace(factor, +factor)
- return -scope.as_nary_node()
- def match_negate_polynome(node):
- """
- --a -> a
- -(a + b) -> -a - b
- """
- #assert node.negated
- p = []
- if node.negated == 2:
- # --a
- p.append(P(node, double_negation, ()))
- if node.is_op(OP_ADD):
- # -(a + b) -> -a - b
- p.append(P(node, negate_polynome, ()))
- return p
- def double_negation(root, args):
- """
- --a -> a
- """
- return root.reduce_negation(2)
- MESSAGES[double_negation] = _('Remove double negation in {1}.')
- def negate_polynome(root, args):
- """
- -(a + b) -> -a - b
- """
- scope = Scope(root)
- # Negate each group
- for i, n in enumerate(scope):
- scope[i] = -n
- return +scope.as_nary_node()
- MESSAGES[negate_polynome] = _('Apply negation to the polynome {1}.')
- #def negate_group(root, args):
- # """
- # -(a * -3c) -> a * 3c
- # -(a * ... * -b) -> ab
- # """
- # node, scope = args
- #
- # for i, n in enumerate(scope):
- # if n.negated:
- # scope[i] = n.reduce_negation()
- #
- # return nary_node('*', scope).reduce_negation()
- #
- #
- #MESSAGES[negate_polynome] = _('Apply negation to the subexpression {1[0]}.')
- def match_negated_division(node):
- """
- -a / -b -> a / b
- """
- assert node.is_op(OP_DIV)
- a, b = node
- if a.negated and b.negated:
- return [P(node, double_negated_division, ())]
- elif a.negated:
- return [P(node, single_negated_division, (+a, b))]
- elif b.negated:
- return [P(node, single_negated_division, (a, +b))]
- return []
- def single_negated_division(root, args):
- """
- -a / b -> -(a / b)
- a / -b -> -(a / b)
- """
- a, b = args
- # FIXME: "-a/b" results in "-(a/b)", which will cause a loop.
- return -(a / b)
- MESSAGES[single_negated_division] = \
- _('Bring negation outside of the division: -({1} / {2}).')
- def double_negated_division(root, args):
- """
- -a / -b -> a / b
- """
- a, b = root
- return +a / +b
- MESSAGES[double_negated_division] = \
- _('Eliminate top and bottom negation in {1}.')
- # TODO: negated multiplication: -a * -b = ab
|