Skip to content

Commit 3ad25a2

Browse files
committed
Fix complex add/sub handling of negative zero
Fixes #585
1 parent 39cda33 commit 3ad25a2

File tree

2 files changed

+69
-4
lines changed

2 files changed

+69
-4
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_complex.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import sys
4040
import unittest
4141
from math import atan2
42+
import math
4243

4344
def test_create():
4445
c = 4 + 4j
@@ -91,6 +92,46 @@ def test_sub():
9192
assert (1.5 - c2) == complex(-0.5, -2)
9293

9394

95+
def test_mixed_real_complex_zero_signs():
96+
z = complex(0.0, -0.0)
97+
98+
def add_int_local():
99+
x = 0
100+
return z + x, x + z
101+
102+
def add_float_local():
103+
x = 0.0
104+
return z + x, x + z
105+
106+
def add_bool_local():
107+
x = False
108+
return z + x, x + z
109+
110+
for left, right in (add_int_local(), add_float_local(), add_bool_local()):
111+
assert left == right
112+
assert math.copysign(1.0, left.imag) == 1.0
113+
assert math.copysign(1.0, right.imag) == 1.0
114+
115+
def sub_int_local():
116+
x = 0
117+
return x - z, z - x
118+
119+
def sub_float_local():
120+
x = 0.0
121+
return x - z, z - x
122+
123+
def sub_bool_local():
124+
x = False
125+
return x - z, z - x
126+
127+
# Subtraction is not commutative, but sign handling should follow CPython.
128+
for left, right in (sub_int_local(), sub_float_local(), sub_bool_local()):
129+
assert left == 0j
130+
assert right == -0j
131+
assert math.copysign(1.0, left.imag) == 1.0
132+
assert math.copysign(1.0, right.imag) == -1.0
133+
134+
94135
def test_div():
95136
c2 = 2+2j
96137
assert (c2 / 2) == complex(1, 1)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -966,13 +966,25 @@ abstract static class AddNode extends BinaryOpBuiltinNode {
966966
@Specialization
967967
static PComplex doInt(PComplex left, int right,
968968
@Bind PythonLanguage language) {
969-
return PFactory.createComplex(language, left.getReal() + right, left.getImag());
969+
return PFactory.createComplex(language, left.getReal() + right, left.getImag() + 0.0);
970970
}
971971

972972
@Specialization
973973
static PComplex doDouble(PComplex left, double right,
974974
@Bind PythonLanguage language) {
975-
return PFactory.createComplex(language, left.getReal() + right, left.getImag());
975+
return PFactory.createComplex(language, left.getReal() + right, left.getImag() + 0.0);
976+
}
977+
978+
@Specialization
979+
static PComplex doInt(int left, PComplex right,
980+
@Bind PythonLanguage language) {
981+
return PFactory.createComplex(language, left + right.getReal(), 0.0 + right.getImag());
982+
}
983+
984+
@Specialization
985+
static PComplex doDouble(double left, PComplex right,
986+
@Bind PythonLanguage language) {
987+
return PFactory.createComplex(language, left + right.getReal(), 0.0 + right.getImag());
976988
}
977989

978990
@Specialization
@@ -1082,13 +1094,25 @@ static ComplexValue multiply(ComplexValue left, ComplexValue right) {
10821094
abstract static class SubNode extends BinaryOpBuiltinNode {
10831095
static PComplex doComplex(PComplex left, double right,
10841096
@Bind PythonLanguage language) {
1085-
return PFactory.createComplex(language, left.getReal() - right, left.getImag());
1097+
return PFactory.createComplex(language, left.getReal() - right, left.getImag() - 0.0);
10861098
}
10871099

10881100
@Specialization
10891101
static PComplex doComplex(PComplex left, int right,
10901102
@Bind PythonLanguage language) {
1091-
return PFactory.createComplex(language, left.getReal() - right, left.getImag());
1103+
return PFactory.createComplex(language, left.getReal() - right, left.getImag() - 0.0);
1104+
}
1105+
1106+
@Specialization
1107+
static PComplex doComplex(int left, PComplex right,
1108+
@Bind PythonLanguage language) {
1109+
return PFactory.createComplex(language, left - right.getReal(), 0.0 - right.getImag());
1110+
}
1111+
1112+
@Specialization
1113+
static PComplex doComplex(double left, PComplex right,
1114+
@Bind PythonLanguage language) {
1115+
return PFactory.createComplex(language, left - right.getReal(), 0.0 - right.getImag());
10921116
}
10931117

10941118
@Specialization

0 commit comments

Comments
 (0)