core: add int.bit_length() when MICROPY_CYPTHON_COMPAT is enabled
This method of integer objects is needed for a port of python3's decimal.py module. MICROPY_CPYTHON_COMPAT is enabled by CIRCUITPY_FULL_BUILD.
This commit is contained in:
parent
5d17d6402d
commit
20c2dd0c08
3
py/mpz.h
3
py/mpz.h
|
@ -135,6 +135,9 @@ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
|||
void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs);
|
||||
|
||||
static inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_SIZE; }
|
||||
static inline size_t mpz_num_bits(const mpz_t *z) {
|
||||
size_t last_bits = (8 * (sizeof(long) - sizeof(mpz_dig_t))) - __builtin_clzl(z->dig[z->len-1]);
|
||||
return z->len * MPZ_DIG_SIZE + last_bits; }
|
||||
mp_int_t mpz_hash(const mpz_t *z);
|
||||
bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value);
|
||||
bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value);
|
||||
|
|
25
py/objint.c
25
py/objint.c
|
@ -457,6 +457,28 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp
|
|||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
STATIC mp_obj_t int_bit_length(mp_obj_t self_in) {
|
||||
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
|
||||
if (!MP_OBJ_IS_SMALL_INT(self_in)) {
|
||||
return mp_obj_int_bit_length_impl(self_in);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
mp_int_t int_val = MP_OBJ_SMALL_INT_VALUE(self_in);
|
||||
mp_uint_t value =
|
||||
(int_val == 0) ? 0 :
|
||||
(int_val == MP_SMALL_INT_MIN) ? 8 * sizeof(mp_int_t) :
|
||||
(int_val < 0) ? 8 * sizeof(long) - __builtin_clzl(-int_val) :
|
||||
8 * sizeof(long) - __builtin_clzl(int_val);
|
||||
return mp_obj_new_int_from_uint(value);
|
||||
}
|
||||
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(int_bit_length_obj, int_bit_length);
|
||||
#endif
|
||||
|
||||
// this is a classmethod
|
||||
STATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {
|
||||
// TODO: Support signed param (assumes signed=False at the moment)
|
||||
|
@ -537,6 +559,9 @@ STATIC mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
|
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(int_to_bytes_obj, 3, int_to_bytes);
|
||||
|
||||
STATIC const mp_rom_map_elem_t int_locals_dict_table[] = {
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
{ MP_ROM_QSTR(MP_QSTR_bit_length), MP_ROM_PTR(&int_bit_length_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_from_bytes), MP_ROM_PTR(&int_from_bytes_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_to_bytes), MP_ROM_PTR(&int_to_bytes_obj) },
|
||||
};
|
||||
|
|
|
@ -60,6 +60,7 @@ void mp_obj_int_buffer_overflow_check(mp_obj_t self_in, size_t nbytes, bool is_s
|
|||
void mp_small_int_buffer_overflow_check(mp_int_t val, size_t nbytes, bool is_signed);
|
||||
|
||||
mp_int_t mp_obj_int_hash(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf);
|
||||
void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf);
|
||||
int mp_obj_int_sign(mp_obj_t self_in);
|
||||
|
|
|
@ -45,6 +45,17 @@
|
|||
const mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX};
|
||||
#endif
|
||||
|
||||
mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
|
||||
mp_obj_int_t *self = self_in;
|
||||
long long val = self->val;
|
||||
return MP_OBJ_NEW_SMALL_INT(
|
||||
(val == 0) ? 0 :
|
||||
(val == MP_SMALL_INT_MIN) ? 8 * sizeof(long long) :
|
||||
(val < 0) ? 8 * sizeof(long long) - __builtin_clzll(-val) :
|
||||
8 * sizeof(long long) - __builtin_clzll(val));
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {
|
||||
int delta = 1;
|
||||
if (!big_endian) {
|
||||
|
|
|
@ -107,6 +107,12 @@ char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size,
|
|||
return str;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
|
||||
mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(mpz_num_bits(&self->mpz));
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {
|
||||
mp_obj_int_t *o = mp_obj_int_new_mpz();
|
||||
mpz_set_from_bytes(&o->mpz, big_endian, len, buf);
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
for i in range(129):
|
||||
j = (1 << i)
|
||||
print(i, (j-1).bit_length(), (j).bit_length(), (j+1).bit_length())
|
||||
print(i, (-j-1).bit_length(), (-j).bit_length(), (-j+1).bit_length())
|
|
@ -1,14 +1,14 @@
|
|||
########
|
||||
object <function> is of type function
|
||||
object <class 'int'> is of type type
|
||||
bit_length -- <function>
|
||||
from_bytes -- <classmethod>
|
||||
to_bytes -- <function>
|
||||
object 1 is of type int
|
||||
bit_length -- <function>
|
||||
from_bytes -- <classmethod>
|
||||
to_bytes -- <function>
|
||||
object <module 'micropython'> is of type module
|
||||
__name__ -- micropython
|
||||
const -- <function>
|
||||
opt_level -- <function>
|
||||
########
|
||||
done
|
||||
|
|
Loading…
Reference in New Issue