Commit f45d2751 authored by Taddeus Kroes's avatar Taddeus Kroes

Added rule that removed fractions from denominators.

parent e12f71ea
...@@ -11,7 +11,7 @@ from .numerics import match_add_numerics, match_divide_numerics, \ ...@@ -11,7 +11,7 @@ from .numerics import match_add_numerics, match_divide_numerics, \
match_multiply_numerics, match_multiply_zero, match_raise_numerics match_multiply_numerics, match_multiply_zero, match_raise_numerics
from .fractions import match_constant_division, match_add_fractions, \ from .fractions import match_constant_division, match_add_fractions, \
match_multiply_fractions, match_divide_fractions, \ match_multiply_fractions, match_divide_fractions, \
match_extract_fraction_terms match_extract_fraction_terms, match_division_in_denominator
from .negation import match_negated_factor, match_negate_polynome, \ from .negation import match_negated_factor, match_negate_polynome, \
match_negated_division match_negated_division
from .sort import match_sort_multiplicants from .sort import match_sort_multiplicants
...@@ -43,7 +43,8 @@ RULES = { ...@@ -43,7 +43,8 @@ RULES = {
match_factor_in_multiplicant], match_factor_in_multiplicant],
OP_DIV: [match_subtract_exponents, match_divide_numerics, OP_DIV: [match_subtract_exponents, match_divide_numerics,
match_constant_division, match_divide_fractions, match_constant_division, match_divide_fractions,
match_negated_division, match_extract_fraction_terms], match_negated_division, match_extract_fraction_terms,
match_division_in_denominator],
OP_POW: [match_multiply_exponents, match_duplicate_exponent, OP_POW: [match_multiply_exponents, match_duplicate_exponent,
match_raised_fraction, match_remove_negative_exponent, match_raised_fraction, match_remove_negative_exponent,
match_exponent_to_root, match_extend_exponent, match_exponent_to_root, match_extend_exponent,
......
...@@ -268,7 +268,7 @@ def divide_fraction(root, args): ...@@ -268,7 +268,7 @@ def divide_fraction(root, args):
""" """
(a, b), c = root (a, b), c = root
return (a / (b * c)).negate(root.negated) return negate(a / (b * c), root.negated)
MESSAGES[divide_fraction] = _('Move {3} to denominator of fraction {1} / {2}.') MESSAGES[divide_fraction] = _('Move {3} to denominator of fraction {1} / {2}.')
...@@ -281,7 +281,7 @@ def divide_by_fraction(root, args): ...@@ -281,7 +281,7 @@ def divide_by_fraction(root, args):
a, bc = root a, bc = root
b, c = bc b, c = bc
return (a * c / b).negate(root.negated + bc.negated) return negate(a * c / b, root.negated + bc.negated)
MESSAGES[divide_by_fraction] = \ MESSAGES[divide_by_fraction] = \
...@@ -370,7 +370,7 @@ def extract_nominator_term(root, args): ...@@ -370,7 +370,7 @@ def extract_nominator_term(root, args):
""" """
a, c = args a, c = args
return a / root[1] * c return negate(a / root[1] * c, root.negated)
MESSAGES[extract_nominator_term] = \ MESSAGES[extract_nominator_term] = \
...@@ -385,9 +385,39 @@ def extract_fraction_terms(root, args): ...@@ -385,9 +385,39 @@ def extract_fraction_terms(root, args):
a ^ b * c / (a ^ d * e) -> a ^ b / a ^ d * (c / e) a ^ b * c / (a ^ d * e) -> a ^ b / a ^ d * (c / e)
""" """
n_scope, d_scope, n, d = args n_scope, d_scope, n, d = args
div = n / d * (remove_from_mult_scope(n_scope, n) \
/ remove_from_mult_scope(d_scope, d))
return n / d * (remove_from_mult_scope(n_scope, n) \ return negate(div, root.negated)
/ remove_from_mult_scope(d_scope, d))
MESSAGES[extract_fraction_terms] = _('Extract {3} / {4} from fraction {0}.') MESSAGES[extract_fraction_terms] = _('Extract {3} / {4} from fraction {0}.')
def match_division_in_denominator(node):
"""
a / (b / c + d) -> (ca) / (c(b / c + d))
"""
assert node.is_op(OP_DIV)
denom = node[1]
if not denom.is_op(OP_ADD):
return []
return [P(node, multiply_with_term, (n[1],))
for n in Scope(denom) if n.is_op(OP_DIV)]
def multiply_with_term(root, args):
"""
a / (b / c + d) -> (ca) / (c(b / c + d))
"""
c = args[0]
nom, denom = root
return negate(c * nom / (c * denom), root.negated)
MESSAGES[multiply_with_term] = \
_('Multiply nominator and denominator of {0} with {1}.')
...@@ -3,7 +3,8 @@ from src.rules.fractions import match_constant_division, division_by_one, \ ...@@ -3,7 +3,8 @@ from src.rules.fractions import match_constant_division, division_by_one, \
equalize_denominators, add_nominators, match_multiply_fractions, \ equalize_denominators, add_nominators, match_multiply_fractions, \
multiply_fractions, multiply_with_fraction, match_divide_fractions, \ multiply_fractions, multiply_with_fraction, match_divide_fractions, \
divide_fraction, divide_by_fraction, match_extract_fraction_terms, \ divide_fraction, divide_by_fraction, match_extract_fraction_terms, \
constant_to_fraction, extract_nominator_term, extract_fraction_terms constant_to_fraction, extract_nominator_term, extract_fraction_terms, \
match_division_in_denominator, multiply_with_term
from src.node import ExpressionNode as N, Scope, OP_MUL from src.node import ExpressionNode as N, Scope, OP_MUL
from src.possibilities import Possibility as P from src.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree from tests.rulestestcase import RulesTestCase, tree
...@@ -284,3 +285,35 @@ class TestRulesFractions(RulesTestCase): ...@@ -284,3 +285,35 @@ class TestRulesFractions(RulesTestCase):
'a * 4 / 5', 'a * 4 / 5',
# FIXME: '4 / 5 * a', # FIXME: '4 / 5 * a',
]) ])
def test_match_division_in_denominator(self):
a, ((b, c), d) = root = tree('a / (b / c + d)')
self.assertEqualPos(match_division_in_denominator(root),
[P(root, multiply_with_term, (c,))])
a, ((d, (b, c)), e) = root = tree('a / (d + b / c + e)')
self.assertEqualPos(match_division_in_denominator(root),
[P(root, multiply_with_term, (c,))])
def test_multiply_with_term_chain(self):
self.assertRewrite([
'1 / (1 / b - 1 / a)',
'(b * 1) / (b(1 / b - 1 / a))',
'b / (b(1 / b - 1 / a))',
'b / (b * 1 / b + b(-1 / a))',
'b / ((b * 1) / b + b(-1 / a))',
'b / (b / b + b(-1 / a))',
'b / (1 + b(-1 / a))',
'b / (1 - b * 1 / a)',
'b / (1 - (b * 1) / a)',
'b / (1 - b / a)',
'(ab) / (a(1 - b / a))',
'(ab) / (a * 1 + a(-b / a))',
'(ab) / (a + a(-b / a))',
'(ab) / (a - ab / a)',
'(ab) / (a - (ab) / a)',
'(ab) / (a - a / a * b / 1)',
'(ab) / (a - 1b / 1)',
'(ab) / (a - 1b)',
'(ab) / (a - b)',
])
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment