Skip to content

Commit

Permalink
py/objint: Do not use fpclassify.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
stinos authored and dpgeorge committed Apr 18, 2020
1 parent 70affd9 commit f31f9a8
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 5 deletions.
14 changes: 9 additions & 5 deletions py/objint.c
Expand Up @@ -135,11 +135,15 @@ STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
#undef MP_FLOAT_EXP_SHIFT_I32

mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
int cl = fpclassify(val);
if (cl == FP_INFINITE) {
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int"));
} else if (cl == FP_NAN) {
mp_raise_ValueError(MP_ERROR_TEXT("can't convert NaN to int"));
mp_float_union_t u = {val};
// IEEE-754: if biased exponent is all 1 bits...
if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) {
// ...then number is Inf (positive or negative) if fraction is 0, else NaN.
if (u.p.frc == 0) {
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int"));
} else {
mp_raise_ValueError(MP_ERROR_TEXT("can't convert NaN to int"));
}
} else {
mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
if (icl == MP_FP_CLASS_FIT_SMALLINT) {
Expand Down
1 change: 1 addition & 0 deletions tests/float/float2int_doubleprec_intbig.py
Expand Up @@ -96,6 +96,7 @@ def fp2int_test(num, name, should_fail):
fp2int_test(1.9999999999999981 * 2.0 ** 1023.0, "large pos", False)

fp2int_test(float("inf"), "inf test", True)
fp2int_test(float("-inf"), "inf test", True)
fp2int_test(float("nan"), "NaN test", True)

# test numbers < 1 (this used to fail; see issue #1044)
Expand Down
1 change: 1 addition & 0 deletions tests/float/float2int_fp30_intbig.py
Expand Up @@ -93,6 +93,7 @@ def fp2int_test(num, name, should_fail):
fp2int_test(1.999999879 * 2.0 ** 126.0, "large pos", False)

fp2int_test(float("inf"), "inf test", True)
fp2int_test(float("-inf"), "inf test", True)
fp2int_test(float("nan"), "NaN test", True)

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

0 comments on commit f31f9a8

Please sign in to comment.