diff --git a/mathics/builtin/numbers/hyperbolic.py b/mathics/builtin/numbers/hyperbolic.py index b29443207..225b98f0b 100644 --- a/mathics/builtin/numbers/hyperbolic.py +++ b/mathics/builtin/numbers/hyperbolic.py @@ -275,6 +275,7 @@ class ComplexExpand(SympyFunction): sympy_name = "expand" def eval(self, expr, evaluation: Evaluation): + "ComplexExpand[expr_]" return eval_ComplexExpand(expr, ListExpression()) def eval_with_complex_vars(self, expr, vars, evaluation: Evaluation): diff --git a/mathics/eval/hyperbolic.py b/mathics/eval/hyperbolic.py index 51cd6e441..0a76d18b8 100644 --- a/mathics/eval/hyperbolic.py +++ b/mathics/eval/hyperbolic.py @@ -1,10 +1,19 @@ """ Mathics3 builtins from mathics.core.numbers.hyperbolic """ +from sympy import Symbol as SympySymbol + from mathics.core.convert.sympy import from_sympy def eval_ComplexExpand(expr, vars): sympy_expr = expr.to_sympy() - # Turn Re[x] -> x and remove Im[x] for all variables X that are not in vars. + sympy_vars = {v.to_sympy() for v in vars.elements} + # All vars are assumed to be real + replaces = [ + (fs, SympySymbol(fs.name, real=True)) + for fs in sympy_expr.free_symbols + if fs not in sympy_vars + ] + sympy_expr = sympy_expr.subs(replaces) return from_sympy(sympy_expr.expand(complex=True)) diff --git a/test/builtin/numbers/test_hyperbolic.py b/test/builtin/numbers/test_hyperbolic.py index 78e4288a4..762cab81f 100644 --- a/test/builtin/numbers/test_hyperbolic.py +++ b/test/builtin/numbers/test_hyperbolic.py @@ -23,3 +23,14 @@ def test_gudermannian(): ("Gudermannian[z]", "2 ArcTan[Tanh[z / 2]]"), ): check_evaluation(str_expr, str_expected) + + +def test_complexexpand(): + for str_expr, str_expected in ( + ("ComplexExpand[Sin[x + I y]]", "Cosh[y]*Sin[x] + I*Cos[x]*Sinh[y]"), + ( + "ComplexExpand[3^(I x)]", + "3 ^ (-Im[x]) Re[3 ^ (I Re[x])] + I Im[3 ^ (I Re[x])] 3 ^ (-Im[x])", + ), + ): + check_evaluation(str_expr, str_expected)