Procházet zdrojové kódy

Added 0*a -> 0 rule.

Taddeus Kroes před 14 roky
rodič
revize
1a74b48d73
3 změnil soubory, kde provedl 53 přidání a 4 odebrání
  1. 3 2
      src/rules/__init__.py
  2. 46 0
      src/rules/numerics.py
  3. 4 2
      tests/test_leiden_oefenopgave.py

+ 3 - 2
src/rules/__init__.py

@@ -6,7 +6,8 @@ from .powers import match_add_exponents, match_subtract_exponents, \
         match_multiply_exponents, match_duplicate_exponent, \
         match_remove_negative_exponent, match_exponent_to_root, \
         match_extend_exponent
-from .numerics import match_divide_numerics, match_multiply_numerics
+from .numerics import match_divide_numerics, match_multiply_numerics, \
+        match_multiply_zero
 from .fractions import match_constant_division, match_add_constant_fractions, \
         match_expand_and_add_fractions
 from .negation import match_negate_group, match_negated_division
@@ -15,7 +16,7 @@ RULES = {
         OP_ADD: [match_add_constant_fractions, match_combine_polynomes, \
                  match_combine_groups],
         OP_MUL: [match_multiply_numerics, match_expand, match_add_exponents, \
-                 match_expand_and_add_fractions],
+                 match_expand_and_add_fractions, match_multiply_zero],
         OP_DIV: [match_subtract_exponents, match_divide_numerics, \
                  match_constant_division, match_negated_division],
         OP_POW: [match_multiply_exponents, match_duplicate_exponent, \

+ 46 - 0
src/rules/numerics.py

@@ -106,6 +106,52 @@ def divide_numerics(root, args):
     return Leaf(n / d)
 
 
+def match_multiply_zero(node):
+    """
+    a * 0    ->  0
+    0 * a    ->  0
+    -0 * a   ->  -0
+    0 * -a   ->  -0
+    -0 * -a  ->  0
+    """
+    assert node.is_op(OP_MUL)
+
+    left, right = node
+    is_zero = lambda n: n.is_leaf() and n.value == 0
+
+    if is_zero(left):
+        negated = right.is_op(OP_NEG)
+    elif is_zero(right):
+        negated = left.is_op(OP_NEG)
+    elif left.is_op(OP_NEG) and is_zero(left[0]):
+        negated = not right.is_op(OP_NEG)
+    elif right.is_op(OP_NEG) and is_zero(right[0]):
+        negated = not left.is_op(OP_NEG)
+    else:
+        return []
+
+    return [P(node, multiply_zero, (negated,))]
+
+
+def multiply_zero(root, args):
+    """
+    a * 0  ->  0
+    0 * a  ->  0
+    -0 * a   ->  -0
+    0 * -a   ->  -0
+    -0 * -a  ->  0
+    """
+    negated = args[0]
+
+    if negated:
+        return -Leaf(0)
+    else:
+        return Leaf(0)
+
+
+MESSAGES[multiply_zero] = _('Multiplication with zero yields zero.')
+
+
 def match_multiply_numerics(node):
     """
     3 * 2      ->  6

+ 4 - 2
tests/test_leiden_oefenopgave.py

@@ -102,8 +102,10 @@ class TestLeidenOefenopgave(TestCase):
                             '-20x + 16 * x ^ 2 - 25 + 5 * 4x',
                             '-20x + 16 * x ^ 2 - 25 + 20x',
                             '(-20 + 20)x + 16 * x ^ 2 - 25',
-                            '0x + 16 * x ^ 2 - 25',])
-                            # FIXME: '16x^2 - 25'])
+                            '0x + 16 * x ^ 2 - 25',
+                            '0 + 16 * x ^ 2 - 25',
+                            '-25 + 16 * x ^ 2'])
+                            # FIXME: '16 * x ^ 2 - 25'])
 
     def test_2(self):
         pass