diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_complex.py b/graalpython/com.oracle.graal.python.test/src/tests/test_complex.py index 9eb43d378b..e1b6ea9ec9 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_complex.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_complex.py @@ -39,6 +39,7 @@ import sys import unittest from math import atan2 +import math def test_create(): c = 4 + 4j @@ -91,6 +92,46 @@ def test_sub(): assert (1.5 - c2) == complex(-0.5, -2) +def test_mixed_real_complex_zero_signs(): + z = complex(0.0, -0.0) + + def add_int_local(): + x = 0 + return z + x, x + z + + def add_float_local(): + x = 0.0 + return z + x, x + z + + def add_bool_local(): + x = False + return z + x, x + z + + for left, right in (add_int_local(), add_float_local(), add_bool_local()): + assert left == right + assert math.copysign(1.0, left.imag) == 1.0 + assert math.copysign(1.0, right.imag) == 1.0 + + def sub_int_local(): + x = 0 + return x - z, z - x + + def sub_float_local(): + x = 0.0 + return x - z, z - x + + def sub_bool_local(): + x = False + return x - z, z - x + + # Subtraction is not commutative, but sign handling should follow CPython. + for left, right in (sub_int_local(), sub_float_local(), sub_bool_local()): + assert left == 0j + assert right == -0j + assert math.copysign(1.0, left.imag) == 1.0 + assert math.copysign(1.0, right.imag) == -1.0 + + def test_div(): c2 = 2+2j assert (c2 / 2) == complex(1, 1) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java index 0b064abb96..4a62ca6b0b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java @@ -966,13 +966,25 @@ abstract static class AddNode extends BinaryOpBuiltinNode { @Specialization static PComplex doInt(PComplex left, int right, @Bind PythonLanguage language) { - return PFactory.createComplex(language, left.getReal() + right, left.getImag()); + return PFactory.createComplex(language, left.getReal() + right, left.getImag() + 0.0); } @Specialization static PComplex doDouble(PComplex left, double right, @Bind PythonLanguage language) { - return PFactory.createComplex(language, left.getReal() + right, left.getImag()); + return PFactory.createComplex(language, left.getReal() + right, left.getImag() + 0.0); + } + + @Specialization + static PComplex doInt(int left, PComplex right, + @Bind PythonLanguage language) { + return PFactory.createComplex(language, left + right.getReal(), 0.0 + right.getImag()); + } + + @Specialization + static PComplex doDouble(double left, PComplex right, + @Bind PythonLanguage language) { + return PFactory.createComplex(language, left + right.getReal(), 0.0 + right.getImag()); } @Specialization @@ -1082,13 +1094,25 @@ static ComplexValue multiply(ComplexValue left, ComplexValue right) { abstract static class SubNode extends BinaryOpBuiltinNode { static PComplex doComplex(PComplex left, double right, @Bind PythonLanguage language) { - return PFactory.createComplex(language, left.getReal() - right, left.getImag()); + return PFactory.createComplex(language, left.getReal() - right, left.getImag() - 0.0); } @Specialization static PComplex doComplex(PComplex left, int right, @Bind PythonLanguage language) { - return PFactory.createComplex(language, left.getReal() - right, left.getImag()); + return PFactory.createComplex(language, left.getReal() - right, left.getImag() - 0.0); + } + + @Specialization + static PComplex doComplex(int left, PComplex right, + @Bind PythonLanguage language) { + return PFactory.createComplex(language, left - right.getReal(), 0.0 - right.getImag()); + } + + @Specialization + static PComplex doComplex(double left, PComplex right, + @Bind PythonLanguage language) { + return PFactory.createComplex(language, left - right.getReal(), 0.0 - right.getImag()); } @Specialization