py: Use float-to-int classifications for mp_obj_new_int_from_float() functions
diff --git a/py/objint.c b/py/objint.c
index 370c6a5..fd0b2be 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -306,9 +306,19 @@
#if MICROPY_PY_BUILTINS_FLOAT
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
- // TODO raise an exception if the int won't fit
- mp_int_t i = MICROPY_FLOAT_C_FUN(trunc)(val);
- return mp_obj_new_int(i);
+ int cl = fpclassify(val);
+ if (cl == FP_INFINITE) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
+ } else if (cl == FP_NAN) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "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) {
+ return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "float too big"));
+ }
+ }
}
#endif
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 394ae11..83e1c67 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -187,9 +187,21 @@
#if MICROPY_PY_BUILTINS_FLOAT
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
- // TODO raise an exception if the unsigned long long won't fit
- long long i = MICROPY_FLOAT_C_FUN(trunc)(val);
- return mp_obj_new_int_from_ll(i);
+ int cl = fpclassify(val);
+ if (cl == FP_INFINITE) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
+ } else if (cl == FP_NAN) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "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) {
+ return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
+ } else if (icl == MP_FP_CLASS_FIT_LONGINT) {
+ return mp_obj_new_int_from_ll((long long)val);
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "float too big"));
+ }
+ }
}
#endif
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 02b3ec0..c46692e 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -303,13 +303,15 @@
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
} else if (cl == FP_NAN) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
- } else if (MICROPY_FLOAT_C_FUN(fabs)(val) < 10000) {
- // temporary(?) fix for optimising case where int will be small int
- return MP_OBJ_NEW_SMALL_INT(MICROPY_FLOAT_C_FUN(trunc)(val));
} else {
- mp_obj_int_t *o = mp_obj_int_new_mpz();
- mpz_set_from_float(&o->mpz, val);
- return o;
+ mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
+ if (icl == MP_FP_CLASS_FIT_SMALLINT) {
+ return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
+ } else {
+ mp_obj_int_t *o = mp_obj_int_new_mpz();
+ mpz_set_from_float(&o->mpz, val);
+ return o;
+ }
}
}
#endif