Skip to content

Commit f31f9a8

Browse files
stinosdpgeorge
authored andcommitted
py/objint: Do not use fpclassify.
For combinations of certain versions of glibc and gcc the definition of fpclassify always takes float as argument instead of adapting itself to float/double/long double as required by the C99 standard. At the time of writing this happens for instance for glibc 2.27 with gcc 7.5.0 when compiled with -Os and glibc 3.0.7 with gcc 9.3.0. When calling fpclassify with double as argument, as in objint.c, this results in an implicit narrowing conversion which is not really correct plus results in a warning when compiled with -Wfloat-conversion. So fix this by spelling out the logic manually.
1 parent 70affd9 commit f31f9a8

File tree

3 files changed

+11
-5
lines changed

3 files changed

+11
-5
lines changed

py/objint.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,15 @@ STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
135135
#undef MP_FLOAT_EXP_SHIFT_I32
136136

137137
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
138-
int cl = fpclassify(val);
139-
if (cl == FP_INFINITE) {
140-
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int"));
141-
} else if (cl == FP_NAN) {
142-
mp_raise_ValueError(MP_ERROR_TEXT("can't convert NaN to int"));
138+
mp_float_union_t u = {val};
139+
// IEEE-754: if biased exponent is all 1 bits...
140+
if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) {
141+
// ...then number is Inf (positive or negative) if fraction is 0, else NaN.
142+
if (u.p.frc == 0) {
143+
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int"));
144+
} else {
145+
mp_raise_ValueError(MP_ERROR_TEXT("can't convert NaN to int"));
146+
}
143147
} else {
144148
mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
145149
if (icl == MP_FP_CLASS_FIT_SMALLINT) {

tests/float/float2int_doubleprec_intbig.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ def fp2int_test(num, name, should_fail):
9696
fp2int_test(1.9999999999999981 * 2.0 ** 1023.0, "large pos", False)
9797

9898
fp2int_test(float("inf"), "inf test", True)
99+
fp2int_test(float("-inf"), "inf test", True)
99100
fp2int_test(float("nan"), "NaN test", True)
100101

101102
# test numbers < 1 (this used to fail; see issue #1044)

tests/float/float2int_fp30_intbig.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ def fp2int_test(num, name, should_fail):
9393
fp2int_test(1.999999879 * 2.0 ** 126.0, "large pos", False)
9494

9595
fp2int_test(float("inf"), "inf test", True)
96+
fp2int_test(float("-inf"), "inf test", True)
9697
fp2int_test(float("nan"), "NaN test", True)
9798

9899
# test numbers < 1 (this used to fail; see issue #1044)

0 commit comments

Comments
 (0)