Quellcode durchsuchen

Moved all spreaded node creation functions to src/node.py.

Taddeus Kroes vor 14 Jahren
Ursprung
Commit
d3a8ad0aaf

+ 73 - 0
src/node.py

@@ -606,3 +606,76 @@ def negate(node, n=1):
     new_node.negated = n
 
     return new_node
+
+
+def infinity():
+    """
+    Return an infinity leaf node.
+    """
+    return ExpressionLeaf(INFINITY)
+
+
+def absolute(exp):
+    """
+    Put an 'absolute value' operator on top of the given expression.
+    """
+    return ExpressionNode(OP_ABS, exp)
+
+
+def sin(*args):
+    """
+    Create a sinus function node.
+    """
+    return ExpressionNode(OP_SIN, *args)
+
+
+def cos(*args):
+    """
+    Create a cosinus function node.
+    """
+    return ExpressionNode(OP_COS, *args)
+
+
+def tan(*args):
+    """
+    Create a tangens function node.
+    """
+    return ExpressionNode(OP_TAN, *args)
+
+
+def log(exponent, base=10):
+    """
+    Create a logarithm function node (default base is 10).
+    """
+    if not isinstance(base, ExpressionLeaf):
+        base = ExpressionLeaf(base)
+
+    return ExpressionNode(OP_LOG, exponent, base)
+
+
+def ln(exponent):
+    """
+    Create a natural logarithm node.
+    """
+    return log(exponent, base=E)
+
+
+def der(f, x=None):
+    """
+    Create a derivative node.
+    """
+    return ExpressionNode(OP_DER, f, x) if x else ExpressionNode(OP_DER, f)
+
+
+def integral(*args):
+    """
+    Create an integral node.
+    """
+    return ExpressionNode(OP_INT, *args)
+
+
+def indef(*args):
+    """
+    Create an indefinite integral node.
+    """
+    return ExpressionNode(OP_INT_INDEF, *args)

+ 2 - 8
src/rules/derivatives.py

@@ -1,16 +1,10 @@
 from .utils import find_variables, first_sorted_variable
-from .logarithmic import ln
-from .goniometry import sin, cos
-from ..node import ExpressionNode as N, ExpressionLeaf as L, Scope, OP_DER, \
-        OP_MUL, OP_LOG, OP_SIN, OP_COS, OP_TAN, OP_ADD, OP_DIV, E
+from ..node import ExpressionLeaf as L, Scope, OP_DER, OP_MUL, OP_LOG, \
+        OP_SIN, OP_COS, OP_TAN, OP_ADD, OP_DIV, E, sin, cos, der, ln
 from ..possibilities import Possibility as P, MESSAGES
 from ..translate import _
 
 
-def der(f, x=None):
-    return N(OP_DER, f, x) if x else N(OP_DER, f)
-
-
 def second_arg(node):
     """
     Get the second child of a node if it exists, None otherwise.

+ 3 - 15
src/rules/goniometry.py

@@ -1,21 +1,9 @@
 from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_ADD, OP_MUL, \
-        OP_DIV, OP_SIN, OP_COS, OP_TAN, OP_SQRT, PI, TYPE_OPERATOR
+        OP_DIV, OP_SIN, OP_COS, OP_TAN, OP_SQRT, PI, TYPE_OPERATOR, sin, cos
 from ..possibilities import Possibility as P, MESSAGES
 from ..translate import _
 
 
-def sin(*args):
-    return N(OP_SIN, *args)
-
-
-def cos(*args):
-    return N(OP_COS, *args)
-
-
-def tan(*args):
-    return N(OP_TAN, *args)
-
-
 def match_add_quadrants(node):
     """
     sin(t) ^ 2 + cos(t) ^ 2  ->  1
@@ -26,9 +14,9 @@ def match_add_quadrants(node):
     sin_q, cos_q = node
 
     if sin_q.is_power(2) and cos_q.is_power(2):
-        sin, cos = sin_q[0], cos_q[0]
+        sinus, cosinus = sin_q[0], cos_q[0]
 
-        if sin.is_op(OP_SIN) and cos.is_op(OP_COS):
+        if sinus.is_op(OP_SIN) and cosinus.is_op(OP_COS):
             p.append(P(node, add_quadrants, ()))
 
     return p

+ 3 - 19
src/rules/integrals.py

@@ -1,26 +1,10 @@
-from .utils import find_variables, replace_variable, find_variable, absolute
-from .logarithmic import ln
-from .goniometry import sin, cos
-from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_INT, \
-        OP_INT_INDEF, OP_MUL, OP_DIV, OP_LOG, OP_SIN, OP_COS, Scope
+from .utils import find_variables, replace_variable, find_variable
+from ..node import ExpressionLeaf as L, OP_INT, OP_INT_INDEF, OP_MUL, OP_DIV, \
+        OP_LOG, OP_SIN, OP_COS, Scope, sin, cos, ln, integral, indef, absolute
 from ..possibilities import Possibility as P, MESSAGES
 from ..translate import _
 
 
-def integral(*args):
-    """
-    Create an integral node.
-    """
-    return N(OP_INT, *args)
-
-
-def indef(*args):
-    """
-    Create an indefinite integral node.
-    """
-    return N(OP_INT_INDEF, *args)
-
-
 def choose_constant(integral):
     """
     Choose a constant to be added to the antiderivative.

+ 2 - 13
src/rules/logarithmic.py

@@ -1,23 +1,12 @@
 from itertools import combinations, product
 
 from .utils import find_variables, partition
-from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_LOG, E, \
-        OP_ADD, OP_MUL, OP_POW, Scope
+from ..node import ExpressionLeaf as L, OP_LOG, OP_ADD, OP_MUL, OP_POW, \
+        Scope, log
 from ..possibilities import Possibility as P, MESSAGES
 from ..translate import _
 
 
-def log(exponent, base=10):
-    if not isinstance(base, L):
-        base = L(base)
-
-    return N(OP_LOG, exponent, base)
-
-
-def ln(exponent):
-    return log(exponent, base=E)
-
-
 def match_constant_logarithm(node):
     """
     log_1(a)   ->  # raise ValueError for base 1

+ 1 - 16
src/rules/utils.py

@@ -1,5 +1,4 @@
-from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_MUL, OP_DIV, \
-        INFINITY, OP_ABS
+from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_MUL, OP_DIV
 
 
 def greatest_common_divisor(a, b):
@@ -126,17 +125,3 @@ def replace_variable(f, x, replacement):
     children = map(lambda c: replace_variable(c, x, replacement), f)
 
     return N(f.op, *children)
-
-
-def infinity():
-    """
-    Return an infinity leaf node.
-    """
-    return L(INFINITY)
-
-
-def absolute(exp):
-    """
-    Put an 'absolute value' operator on top of the given expression.
-    """
-    return N(OP_ABS, exp)

+ 43 - 1
tests/test_node.py

@@ -1,5 +1,6 @@
 from src.node import ExpressionNode as N, ExpressionLeaf as L, Scope, \
-        nary_node, get_scope, OP_ADD
+        nary_node, get_scope, OP_ADD, infinity, absolute, sin, cos, tan, log, \
+        ln, der, integral, indef
 from tests.rulestestcase import RulesTestCase, tree
 
 
@@ -249,3 +250,44 @@ class TestNode(RulesTestCase):
     def test_construct_function_absolute_child(self):
         self.assertEqual(str(tree('ln(|x|)')), 'ln|x|')
         self.assertEqual(str(tree('sin(|x|)')), 'sin|x|')
+
+    def test_infinity(self):
+        self.assertEqual(infinity(), tree('oo'))
+
+    def test_absolute(self):
+        self.assertEqual(absolute(tree('x2')), tree('|x2|'))
+
+    def test_sin(self):
+        self.assertEqual(sin(tree('x')), tree('sin(x)'))
+
+    def test_cos(self):
+        self.assertEqual(cos(tree('x')), tree('cos(x)'))
+
+    def test_tan(self):
+        self.assertEqual(tan(tree('x')), tree('tan(x)'))
+
+    def test_log(self):
+        x = tree('x')
+        self.assertEqual(log(x, 'e'), tree('ln x'))
+        self.assertEqual(log(x, 2), tree('log_2 x'))
+        self.assertEqual(log(x), tree('log x'))
+        self.assertEqual(log(x, 10), tree('log x'))
+
+    def test_ln(self):
+        self.assertEqual(ln(tree('x')), tree('ln x'))
+
+    def test_der(self):
+        x2, x, y = tree('x ^ 2, x, y')
+        self.assertEqual(der(x2), tree('[x ^ 2]\''))
+        self.assertEqual(der(x2, x), tree('d/dx x ^ 2'))
+        self.assertEqual(der(x2, y), tree('d/dy x ^ 2'))
+
+    def test_integral(self):
+        x2, x, y, a, b = tree('x ^ 2, x, y, a, b')
+        self.assertEqual(integral(x2, x), tree('int x2 dx'))
+        self.assertEqual(integral(x2, x, a, b), tree('int_a^b x2 dx'))
+        self.assertEqual(integral(x2, y, a, b), tree('int_a^b x2 dy'))
+
+    def test_indef(self):
+        x2, a, b, expect = tree('x ^ 2, a, b, [x ^ 2]_a^b')
+        self.assertEqual(indef(x2, a, b), expect)

+ 1 - 6
tests/test_parser.py

@@ -3,14 +3,9 @@ import unittest
 
 from src.parser import Parser
 from src.node import ExpressionNode as Node, ExpressionLeaf as Leaf, \
-        SPECIAL_TOKENS
+        SPECIAL_TOKENS, sin, cos, der, log, ln, integral, indef, absolute
 from tests.parser import ParserWrapper, run_expressions, line, graph
 from tests.rulestestcase import tree
-from src.rules.goniometry import sin, cos
-from src.rules.derivatives import der
-from src.rules.logarithmic import log, ln
-from src.rules.integrals import integral, indef
-from src.rules.utils import absolute
 
 
 class TestParser(unittest.TestCase):

+ 1 - 3
tests/test_rules_derivatives.py

@@ -6,9 +6,7 @@ from src.rules.derivatives import der, get_derivation_variable, \
         logarithmic, match_goniometric, sinus, cosinus, tangens, \
         match_sum_product_rule, sum_rule, product_rule, match_quotient_rule, \
         quotient_rule, power_rule
-from src.rules.logarithmic import ln
-from src.rules.goniometry import sin, cos
-from src.node import Scope
+from src.node import Scope, sin, cos, ln
 from src.possibilities import Possibility as P
 from tests.rulestestcase import RulesTestCase, tree
 

+ 4 - 5
tests/test_rules_goniometry.py

@@ -1,9 +1,8 @@
 # vim: set fileencoding=utf-8 :
-from src.rules.goniometry import sin, cos, tan, match_add_quadrants, \
-        add_quadrants, match_negated_parameter, negated_sinus_parameter, \
-        negated_cosinus_parameter, match_standard_radian, standard_radian, \
-        is_pi_frac
-from src.node import PI, OP_SIN, OP_COS, OP_TAN
+from src.rules.goniometry import match_add_quadrants, add_quadrants, \
+        match_negated_parameter, negated_sinus_parameter, is_pi_frac, \
+        negated_cosinus_parameter, match_standard_radian, standard_radian
+from src.node import PI, OP_SIN, OP_COS, OP_TAN, sin, cos, tan
 from src.possibilities import Possibility as P
 from tests.rulestestcase import RulesTestCase, tree
 from src.rules import goniometry

+ 0 - 2
tests/test_rules_integrals.py

@@ -6,8 +6,6 @@ from src.rules.integrals import indef, choose_constant, solve_integral, \
         match_division_integral, division_integral, extend_division_integral, \
         match_function_integral, logarithm_integral, sinus_integral, \
         cosinus_integral
-from src.rules.logarithmic import ln
-from src.rules.goniometry import sin, cos
 from src.node import Scope
 from src.possibilities import Possibility as P
 from tests.rulestestcase import RulesTestCase, tree

+ 1 - 1
tests/test_rules_logarithmic.py

@@ -1,4 +1,4 @@
-from src.rules.logarithmic import log, ln, match_constant_logarithm, \
+from src.rules.logarithmic import log, match_constant_logarithm, \
         base_equals_raised, logarithm_of_one, divide_same_base, \
         match_add_logarithms, add_logarithms, expand_negations, \
         subtract_logarithms, match_raised_base, raised_base, \

+ 1 - 5
tests/test_rules_utils.py

@@ -1,7 +1,6 @@
 from src.rules import utils
 from src.rules.utils import least_common_multiple, is_fraction, partition, \
-        find_variables, first_sorted_variable, find_variable, \
-        replace_variable, infinity
+        find_variables, first_sorted_variable, find_variable, replace_variable
 from tests.rulestestcase import tree, RulesTestCase
 
 
@@ -28,9 +27,6 @@ class TestRulesUtils(RulesTestCase):
         self.assertEqual(partition(lambda x: x & 1, range(6)),
                          ([1, 3, 5], [0, 2, 4]))
 
-    def test_infinity(self):
-        self.assertEqual(infinity(), tree('oo'))
-
     def test_find_variables(self):
         x, l2, add, mul0, mul1 = tree('x, 2, x + 2, 2x, xy')
         self.assertSetEqual(find_variables(x), set(['x']))