core: Introduce mp_obj_new_long_ll.
Since #9531 a few ways remained to produce long ints that were not reduced to small ints. Explicitly introduce "mp_obj_new_long_from_ll" and make the "new_int" functions always produce small ints when possible. At sites where a long int is really intended (or will eventually be reduced to a small int if the result fits), the called function is changed to be the new _long_ function. Signed-off-by: Jeff Epler <jepler@gmail.com>
This commit is contained in:
parent
c68d8ac358
commit
decc0c75a7
6 changed files with 52 additions and 26 deletions
|
|
@ -527,9 +527,9 @@ static mp_obj_t extra_coverage(void) {
|
||||||
mp_printf(&mp_plat_print, "%f\n", mpz_as_float(&mpz));
|
mp_printf(&mp_plat_print, "%f\n", mpz_as_float(&mpz));
|
||||||
|
|
||||||
// convert a large integer value (stored in a mpz) to mp_uint_t and to ll;
|
// convert a large integer value (stored in a mpz) to mp_uint_t and to ll;
|
||||||
mp_obj_t obj_bigint = mp_obj_new_int_from_uint((mp_uint_t)0xdeadbeef);
|
mp_obj_t obj_bigint = mp_obj_new_int_from_ull((unsigned long long)0xdeadbeef);
|
||||||
mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint));
|
mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint));
|
||||||
obj_bigint = mp_obj_new_int_from_ll(0xc0ffee777c0ffeell);
|
obj_bigint = mp_obj_new_long_from_ll(0xc0ffee777c0ffeell);
|
||||||
long long value_ll = mp_obj_get_ll(obj_bigint);
|
long long value_ll = mp_obj_get_ll(obj_bigint);
|
||||||
mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll);
|
mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll);
|
||||||
|
|
||||||
|
|
@ -541,7 +541,7 @@ static mp_obj_t extra_coverage(void) {
|
||||||
mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll);
|
mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll);
|
||||||
|
|
||||||
// convert a smaller integer value to mp_uint_t and to ll
|
// convert a smaller integer value to mp_uint_t and to ll
|
||||||
obj_bigint = mp_obj_new_int_from_uint(0xc0ffee);
|
obj_bigint = mp_obj_new_int_from_ull(0xc0ffeeull);
|
||||||
mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint));
|
mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint));
|
||||||
value_ll = mp_obj_get_ll(obj_bigint);
|
value_ll = mp_obj_get_ll(obj_bigint);
|
||||||
mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll);
|
mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll);
|
||||||
|
|
@ -568,7 +568,7 @@ static mp_obj_t extra_coverage(void) {
|
||||||
mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(1)));
|
mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(1)));
|
||||||
|
|
||||||
// mp_obj_int_get_uint_checked with non-negative big-int
|
// mp_obj_int_get_uint_checked with non-negative big-int
|
||||||
mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(mp_obj_new_int_from_ll(2)));
|
mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(mp_obj_new_long_from_ll(2)));
|
||||||
|
|
||||||
// mp_obj_int_get_uint_checked with negative small-int (should raise exception)
|
// mp_obj_int_get_uint_checked with negative small-int (should raise exception)
|
||||||
nlr_buf_t nlr;
|
nlr_buf_t nlr;
|
||||||
|
|
@ -581,7 +581,7 @@ static mp_obj_t extra_coverage(void) {
|
||||||
|
|
||||||
// mp_obj_int_get_uint_checked with negative big-int (should raise exception)
|
// mp_obj_int_get_uint_checked with negative big-int (should raise exception)
|
||||||
if (nlr_push(&nlr) == 0) {
|
if (nlr_push(&nlr) == 0) {
|
||||||
mp_obj_int_get_uint_checked(mp_obj_new_int_from_ll(-2));
|
mp_obj_int_get_uint_checked(mp_obj_new_long_from_ll(-2));
|
||||||
nlr_pop();
|
nlr_pop();
|
||||||
} else {
|
} else {
|
||||||
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
|
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||||
|
|
@ -853,12 +853,12 @@ static mp_obj_t extra_coverage(void) {
|
||||||
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_bool(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_bool(mp_const_none));
|
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_bool(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_bool(mp_const_none));
|
||||||
|
|
||||||
// mp_obj_is_integer accepts ints and booleans
|
// mp_obj_is_integer accepts ints and booleans
|
||||||
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_integer(mp_obj_new_int_from_ll(1)));
|
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_integer(mp_obj_new_long_from_ll(1)));
|
||||||
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_const_true), mp_obj_is_integer(mp_const_false));
|
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_const_true), mp_obj_is_integer(mp_const_false));
|
||||||
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_obj_new_str_from_cstr("1")), mp_obj_is_integer(mp_const_none));
|
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_obj_new_str_from_cstr("1")), mp_obj_is_integer(mp_const_none));
|
||||||
|
|
||||||
// mp_obj_is_int accepts small int and object ints
|
// mp_obj_is_int accepts small int and object ints
|
||||||
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_int(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_int(mp_obj_new_int_from_ll(1)));
|
mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_int(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_int(mp_obj_new_long_from_ll(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Legacy stackctrl.h API, this has been replaced by cstack.h
|
// Legacy stackctrl.h API, this has been replaced by cstack.h
|
||||||
|
|
|
||||||
5
py/obj.h
5
py/obj.h
|
|
@ -994,8 +994,9 @@ mp_obj_t mp_obj_new_cell(mp_obj_t obj);
|
||||||
mp_obj_t mp_obj_new_int(mp_int_t value);
|
mp_obj_t mp_obj_new_int(mp_int_t value);
|
||||||
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value);
|
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value);
|
||||||
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base);
|
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base);
|
||||||
mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception)
|
mp_obj_t mp_obj_new_int_from_ll(long long val); // returns a small int if value fits
|
||||||
mp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // this must return a multi-precision integer object (or raise an overflow exception)
|
mp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // returns a small int if value fits
|
||||||
|
mp_obj_t mp_obj_new_long_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception)
|
||||||
mp_obj_t mp_obj_new_str(const char *data, size_t len); // will check utf-8 (raises UnicodeError)
|
mp_obj_t mp_obj_new_str(const char *data, size_t len); // will check utf-8 (raises UnicodeError)
|
||||||
mp_obj_t mp_obj_new_str_from_cstr(const char *str); // // accepts null-terminated string, will check utf-8 (raises UnicodeError)
|
mp_obj_t mp_obj_new_str_from_cstr(const char *str); // // accepts null-terminated string, will check utf-8 (raises UnicodeError)
|
||||||
mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); // input data must be valid utf-8
|
mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); // input data must be valid utf-8
|
||||||
|
|
|
||||||
|
|
@ -326,7 +326,13 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i
|
||||||
|
|
||||||
// This is called only with strings whose value doesn't fit in SMALL_INT
|
// This is called only with strings whose value doesn't fit in SMALL_INT
|
||||||
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
|
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
|
||||||
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("long int not supported in this build"));
|
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)
|
||||||
|
mp_obj_t mp_obj_new_long_from_ll(long long val) {
|
||||||
|
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -298,14 +298,18 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
|
||||||
return mp_obj_new_int_from_ll(value);
|
return mp_obj_new_int_from_ll(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mp_obj_t mp_obj_new_long_from_ll(long long val) {
|
||||||
|
mp_obj_int_t *o = mp_obj_malloc(mp_obj_int_t, &mp_type_int);
|
||||||
|
o->val = val;
|
||||||
|
return MP_OBJ_FROM_PTR(o);
|
||||||
|
}
|
||||||
|
|
||||||
mp_obj_t mp_obj_new_int_from_ll(long long val) {
|
mp_obj_t mp_obj_new_int_from_ll(long long val) {
|
||||||
if ((long long)(mp_int_t)val == val && MP_SMALL_INT_FITS(val)) {
|
if ((long long)(mp_int_t)val == val && MP_SMALL_INT_FITS(val)) {
|
||||||
return MP_OBJ_NEW_SMALL_INT(val);
|
return MP_OBJ_NEW_SMALL_INT(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_int_t *o = mp_obj_malloc(mp_obj_int_t, &mp_type_int);
|
return mp_obj_new_long_from_ll(val);
|
||||||
o->val = val;
|
|
||||||
return MP_OBJ_FROM_PTR(o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
|
mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
|
||||||
|
|
|
||||||
|
|
@ -382,23 +382,38 @@ mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// This routine *always* returns an mpz integer. Call it only if the value is *known*
|
||||||
|
// to exceed the small integer range, because integers that fit are required to always
|
||||||
|
// be returned as small integers.
|
||||||
|
static mp_obj_t mp_obj_new_mpz_from_ll(long long val, bool is_signed) {
|
||||||
|
mp_obj_int_t *o = mp_obj_int_new_mpz();
|
||||||
|
mpz_set_from_ll(&o->mpz, val, is_signed);
|
||||||
|
return MP_OBJ_FROM_PTR(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t mp_obj_new_long_from_ll(long long val) {
|
||||||
|
return mp_obj_new_mpz_from_ll(val, true);
|
||||||
|
}
|
||||||
|
|
||||||
mp_obj_t mp_obj_new_int(mp_int_t value) {
|
mp_obj_t mp_obj_new_int(mp_int_t value) {
|
||||||
if (MP_SMALL_INT_FITS(value)) {
|
if (MP_SMALL_INT_FITS(value)) {
|
||||||
return MP_OBJ_NEW_SMALL_INT(value);
|
return MP_OBJ_NEW_SMALL_INT(value);
|
||||||
}
|
}
|
||||||
return mp_obj_new_int_from_ll(value);
|
return mp_obj_new_mpz_from_ll(value, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t mp_obj_new_int_from_ll(long long val) {
|
mp_obj_t mp_obj_new_int_from_ll(long long val) {
|
||||||
mp_obj_int_t *o = mp_obj_int_new_mpz();
|
if (val == (mp_int_t)val && MP_SMALL_INT_FITS((mp_int_t)val)) {
|
||||||
mpz_set_from_ll(&o->mpz, val, true);
|
return MP_OBJ_NEW_SMALL_INT(val);
|
||||||
return MP_OBJ_FROM_PTR(o);
|
}
|
||||||
|
return mp_obj_new_mpz_from_ll(val, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
|
mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
|
||||||
mp_obj_int_t *o = mp_obj_int_new_mpz();
|
if ((val & ~(unsigned long long)MP_SMALL_INT_POSITIVE_MASK) == 0) {
|
||||||
mpz_set_from_ll(&o->mpz, val, false);
|
return mp_obj_new_int(val);
|
||||||
return MP_OBJ_FROM_PTR(o);
|
}
|
||||||
|
return mp_obj_new_mpz_from_ll(val, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
|
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
|
||||||
|
|
@ -407,7 +422,7 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
|
||||||
if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {
|
if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {
|
||||||
return MP_OBJ_NEW_SMALL_INT(value);
|
return MP_OBJ_NEW_SMALL_INT(value);
|
||||||
}
|
}
|
||||||
return mp_obj_new_int_from_ull(value);
|
return mp_obj_new_mpz_from_ll(value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
|
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
|
||||||
|
|
|
||||||
10
py/runtime.c
10
py/runtime.c
|
|
@ -456,7 +456,7 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs
|
||||||
|| lhs_val > (MP_SMALL_INT_MAX >> rhs_val)
|
|| lhs_val > (MP_SMALL_INT_MAX >> rhs_val)
|
||||||
|| lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) {
|
|| lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) {
|
||||||
// left-shift will overflow, so use higher precision integer
|
// left-shift will overflow, so use higher precision integer
|
||||||
lhs = mp_obj_new_int_from_ll(lhs_val);
|
lhs = mp_obj_new_long_from_ll(lhs_val);
|
||||||
goto generic_binary_op;
|
goto generic_binary_op;
|
||||||
} else {
|
} else {
|
||||||
// use standard precision
|
// use standard precision
|
||||||
|
|
@ -498,7 +498,7 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs
|
||||||
long long res = (long long)lhs_val * (long long)rhs_val;
|
long long res = (long long)lhs_val * (long long)rhs_val;
|
||||||
if (res > MP_SMALL_INT_MAX || res < MP_SMALL_INT_MIN) {
|
if (res > MP_SMALL_INT_MAX || res < MP_SMALL_INT_MIN) {
|
||||||
// result overflowed SMALL_INT, so return higher precision integer
|
// result overflowed SMALL_INT, so return higher precision integer
|
||||||
return mp_obj_new_int_from_ll(res);
|
return mp_obj_new_long_from_ll(res);
|
||||||
} else {
|
} else {
|
||||||
// use standard precision
|
// use standard precision
|
||||||
lhs_val = (mp_int_t)res;
|
lhs_val = (mp_int_t)res;
|
||||||
|
|
@ -508,7 +508,7 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs
|
||||||
mp_int_t int_res;
|
mp_int_t int_res;
|
||||||
if (mp_small_int_mul_overflow(lhs_val, rhs_val, &int_res)) {
|
if (mp_small_int_mul_overflow(lhs_val, rhs_val, &int_res)) {
|
||||||
// use higher precision
|
// use higher precision
|
||||||
lhs = mp_obj_new_int_from_ll(lhs_val);
|
lhs = mp_obj_new_long_from_ll(lhs_val);
|
||||||
goto generic_binary_op;
|
goto generic_binary_op;
|
||||||
} else {
|
} else {
|
||||||
// use standard precision
|
// use standard precision
|
||||||
|
|
@ -573,7 +573,7 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs
|
||||||
|
|
||||||
power_overflow:
|
power_overflow:
|
||||||
// use higher precision
|
// use higher precision
|
||||||
lhs = mp_obj_new_int_from_ll(MP_OBJ_SMALL_INT_VALUE(lhs));
|
lhs = mp_obj_new_long_from_ll(MP_OBJ_SMALL_INT_VALUE(lhs));
|
||||||
goto generic_binary_op;
|
goto generic_binary_op;
|
||||||
|
|
||||||
case MP_BINARY_OP_DIVMOD: {
|
case MP_BINARY_OP_DIVMOD: {
|
||||||
|
|
@ -603,7 +603,7 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs
|
||||||
if (MP_SMALL_INT_FITS(lhs_val)) {
|
if (MP_SMALL_INT_FITS(lhs_val)) {
|
||||||
return MP_OBJ_NEW_SMALL_INT(lhs_val);
|
return MP_OBJ_NEW_SMALL_INT(lhs_val);
|
||||||
} else {
|
} else {
|
||||||
return mp_obj_new_int_from_ll(lhs_val);
|
return mp_obj_new_long_from_ll(lhs_val);
|
||||||
}
|
}
|
||||||
#if MICROPY_PY_BUILTINS_FLOAT
|
#if MICROPY_PY_BUILTINS_FLOAT
|
||||||
} else if (mp_obj_is_float(rhs)) {
|
} else if (mp_obj_is_float(rhs)) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue