8000 py/obj: Fix comparison of float/complex NaN with itself. · guidebee/micropython@d4b75f6 · GitHub
[go: up one dir, main page]

Skip to content

Commit d4b75f6

Browse files
committed
py/obj: Fix comparison of float/complex NaN with itself.
IEEE floating point is specified such that a comparison of NaN with itself returns false, and Python respects these semantics. This patch makes uPy also have these semantics. The fix has a minor impact on the speed of the object-equality fast-path, but that seems to be unavoidable and it's much more important to have correct behaviour (especially in this case where the wrong answer for nan==nan is silently returned).
1 parent 9950865 commit d4b75f6

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

py/obj.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,16 @@ bool mp_obj_is_callable(mp_obj_t o_in) {
162162
// comparison returns NotImplemented, == and != are decided by comparing the object
163163
// pointer."
164164
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
165-
if (o1 == o2) {
165+
// Float (and complex) NaN is never equal to anything, not even itself,
166+
// so we must have a special check here to cover those cases.
167+
if (o1 == o2
168+
#if MICROPY_PY_BUILTINS_FLOAT
169+
&& !mp_obj_is_float(o1)
170+
#endif
171+
#if MICROPY_PY_BUILTINS_COMPLEX
172+
&& !MP_OBJ_IS_TYPE(o1, &mp_type_complex)
173+
#endif
174+
) {
166175
return true;
167176
}
168177
if (o1 == mp_const_none || o2 == mp_const_none) {

tests/float/complex1.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
print(1j == 1)
3838
print(1j == 1j)
3939

40+
# comparison of nan is special
41+
nan = float('nan') * 1j
42+
print(nan == 1j)
43+
print(nan == nan)
44+
4045
# builtin abs
4146
print(abs(1j))
4247
print("%.5g" % abs(1j + 2))

tests/float/float1.py

Lines changed: 5 additions & 0 deletions
< 7F29 div data-testid="addition diffstat" class="DiffSquares-module__diffSquare--h5kjy DiffSquares-module__addition--jeNtt">
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@
6060
print(1.2 >= 3.4)
6161
print(1.2 >= -3.4)
6262

63+
# comparison of nan is special
64+
nan = float('nan')
65+
print(nan == 1.2)
66+
print(nan == nan)
67+
6368
try:
6469
1.0 / 0
6570
except ZeroDivisionError:

0 commit comments

Comments
 (0)
0