From 0fb17f6ef46ade018a3fda8d4266f15638ddf5e3 Mon Sep 17 00:00:00 2001 From: David Steinberg Date: Tue, 13 Jan 2015 15:22:30 +0000 Subject: [PATCH] py: Use float-to-int classifications for mp_obj_new_int_from_float() functions --- py/objint.c | 16 +++++++++++++--- py/objint_longlong.c | 18 +++++++++++++++--- py/objint_mpz.c | 14 ++++++++------ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/py/objint.c b/py/objint.c index 370c6a5df3..fd0b2be559 100644 --- a/py/objint.c +++ b/py/objint.c @@ -306,9 +306,19 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) { #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 394ae111ad..83e1c67d6d 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -187,9 +187,21 @@ mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) { #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 02b3ec0fe4..c46692ec76 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -303,13 +303,15 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) { 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