Skip to content

Commit 5faab51

Browse files
committed
Fixed long to double comparison
1 parent c832d87 commit 5faab51

File tree

4 files changed

+48
-46
lines changed

4 files changed

+48
-46
lines changed

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,23 @@ def test_floatasratio(self):
172172
self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
173173
self.assertRaises(ValueError, float('nan').as_integer_ratio)
174174

175+
def test_compare(self):
176+
i = 2**53 + 1
177+
f = float(i)
178+
self.assertFalse(f == i)
179+
self.assertTrue(f != i)
180+
self.assertTrue(f < i)
181+
self.assertTrue(f <= i)
182+
self.assertFalse(f > i)
183+
self.assertFalse(f >= i)
184+
self.assertFalse(i == f)
185+
self.assertTrue(i != f)
186+
self.assertFalse(i < f)
187+
self.assertFalse(i <= f)
188+
self.assertTrue(i > f)
189+
self.assertTrue(i >= f)
190+
191+
175192
fromHex = float.fromhex
176193

177194
class HexFloatTests(unittest.TestCase):

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

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
import com.oracle.graal.python.builtins.PythonBuiltins;
8282
import com.oracle.graal.python.builtins.objects.PNone;
8383
import com.oracle.graal.python.builtins.objects.PNotImplemented;
84+
import com.oracle.graal.python.builtins.objects.floats.FloatBuiltins;
8485
import com.oracle.graal.python.builtins.objects.ints.PInt;
8586
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
8687
import com.oracle.graal.python.nodes.ErrorMessages;
@@ -591,30 +592,17 @@ boolean doComplex(PComplex left, PComplex right) {
591592

592593
@Specialization
593594
boolean doComplexInt(PComplex left, long right) {
594-
if (left.getImag() == 0) {
595-
return left.getReal() == right;
596-
}
597-
return false;
595+
return left.getImag() == 0 && FloatBuiltins.EqNode.compareDoubleToLong(left.getReal(), right) == 0;
598596
}
599597

600598
@Specialization
601599
boolean doComplexInt(PComplex left, PInt right) {
602-
if (left.getImag() == 0) {
603-
try {
604-
return left.getReal() == right.longValueExact();
605-
} catch (ArithmeticException e) {
606-
// do nothing -> return false;
607-
}
608-
}
609-
return false;
600+
return left.getImag() == 0 && FloatBuiltins.EqNode.compareDoubleToLargeInt(left.getReal(), right) == 0;
610601
}
611602

612603
@Specialization
613604
boolean doComplexInt(PComplex left, double right) {
614-
if (left.getImag() == 0) {
615-
return left.getReal() == right;
616-
}
617-
return false;
605+
return left.getImag() == 0 && left.getReal() == right;
618606
}
619607

620608
@SuppressWarnings("unused")
@@ -699,12 +687,12 @@ boolean doComplex(PComplex left, PComplex right) {
699687

700688
@Specialization
701689
boolean doComplex(PComplex left, long right) {
702-
return left.getImag() != 0 || left.getReal() != right;
690+
return left.getImag() != 0 || FloatBuiltins.EqNode.compareDoubleToLong(left.getReal(), right) != 0;
703691
}
704692

705693
@Specialization
706694
boolean doComplex(PComplex left, PInt right) {
707-
return left.getImag() != 0 || left.getReal() != right.doubleValue();
695+
return left.getImag() != 0 || FloatBuiltins.EqNode.compareDoubleToLargeInt(left.getReal(), right) != 0;
708696
}
709697

710698
@Specialization

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ long round(double x, @SuppressWarnings("unused") PNone none,
999999
@Builtin(name = __EQ__, minNumOfPositionalArgs = 2)
10001000
@GenerateNodeFactory
10011001
@TypeSystemReference(PythonArithmeticTypes.class)
1002-
abstract static class EqNode extends PythonBinaryBuiltinNode {
1002+
public abstract static class EqNode extends PythonBinaryBuiltinNode {
10031003

10041004
@Specialization
10051005
boolean eqDbDb(double a, double b) {
@@ -1008,7 +1008,7 @@ boolean eqDbDb(double a, double b) {
10081008

10091009
@Specialization
10101010
boolean eqDbLn(double a, long b) {
1011-
return a == b;
1011+
return compareDoubleToLong(a, b) == 0;
10121012
}
10131013

10141014
@Specialization
@@ -1041,7 +1041,24 @@ PNotImplemented eq(Object a, Object b) {
10411041
}
10421042

10431043
// adapted from CPython's float_richcompare in floatobject.c
1044-
static double compareDoubleToLargeInt(double v, PInt w) {
1044+
public static double compareDoubleToLong(double v, long w) {
1045+
if (!Double.isFinite(v)) {
1046+
return v;
1047+
}
1048+
int vsign = v == 0.0 ? 0 : v < 0.0 ? -1 : 1;
1049+
int wsign = Long.signum(w);
1050+
if (vsign != wsign) {
1051+
return vsign - wsign;
1052+
}
1053+
if (w > -0x1000000000000L && w < 0x1000000000000L) { // w is at most 48 bits
1054+
return v - w;
1055+
} else {
1056+
return compareUsingBigDecimal(v, BigInteger.valueOf(w));
1057+
}
1058+
}
1059+
1060+
// adapted from CPython's float_richcompare in floatobject.c
1061+
public static double compareDoubleToLargeInt(double v, PInt w) {
10451062
if (!Double.isFinite(v)) {
10461063
return v;
10471064
}
@@ -1074,7 +1091,7 @@ boolean neDbDb(double a, double b) {
10741091

10751092
@Specialization
10761093
boolean neDbLn(double a, long b) {
1077-
return a != b;
1094+
return EqNode.compareDoubleToLong(a, b) != 0;
10781095
}
10791096

10801097
@Specialization
@@ -1118,7 +1135,7 @@ boolean doDD(double x, double y) {
11181135

11191136
@Specialization
11201137
boolean doDL(double x, long y) {
1121-
return x < y;
1138+
return EqNode.compareDoubleToLong(x, y) < 0;
11221139
}
11231140

11241141
@Specialization
@@ -1183,7 +1200,7 @@ boolean doDD(double x, double y) {
11831200

11841201
@Specialization
11851202
boolean doDL(double x, long y) {
1186-
return x <= y;
1203+
return EqNode.compareDoubleToLong(x, y) <= 0;
11871204
}
11881205

11891206
@Specialization
@@ -1248,7 +1265,7 @@ boolean doDD(double x, double y) {
12481265

12491266
@Specialization
12501267
boolean doDL(double x, long y) {
1251-
return x > y;
1268+
return EqNode.compareDoubleToLong(x, y) > 0;
12521269
}
12531270

12541271
@Specialization
@@ -1313,7 +1330,7 @@ boolean doDD(double x, double y) {
13131330

13141331
@Specialization
13151332
boolean doDL(double x, long y) {
1316-
return x >= y;
1333+
return EqNode.compareDoubleToLong(x, y) >= 0;
13171334
}
13181335

13191336
@Specialization

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/BinaryComparisonNode.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -208,16 +208,6 @@ boolean doLI(VirtualFrame frame, long left, long right) {
208208
}
209209
}
210210

211-
@Specialization
212-
boolean doLI(VirtualFrame frame, long left, double right) {
213-
try {
214-
return profileCondition(callNode.executeBool(frame, left, right));
215-
} catch (UnexpectedResultException e) {
216-
CompilerDirectives.transferToInterpreterAndInvalidate();
217-
throw new IllegalStateException("Comparison on primitive values didn't return a boolean");
218-
}
219-
}
220-
221211
@Specialization
222212
boolean doDB(VirtualFrame frame, double left, boolean right) {
223213
try {
@@ -238,16 +228,6 @@ boolean doDI(VirtualFrame frame, double left, int right) {
238228
}
239229
}
240230

241-
@Specialization
242-
boolean doDL(VirtualFrame frame, double left, long right) {
243-
try {
244-
return profileCondition(callNode.executeBool(frame, left, right));
245-
} catch (UnexpectedResultException e) {
246-
CompilerDirectives.transferToInterpreterAndInvalidate();
247-
throw new IllegalStateException("Comparison on primitive values didn't return a boolean");
248-
}
249-
}
250-
251231
@Specialization
252232
boolean doDD(VirtualFrame frame, double left, double right) {
253233
try {

0 commit comments

Comments
 (0)