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
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy