diff --git a/py/mpconfig.h b/py/mpconfig.h index afef744ab5b01..febd1a627ce79 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1144,6 +1144,11 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_ROUND_INT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif +// Whether to support int.bit_length(n) +#ifndef MICROPY_PY_BUILTINS_INT_BIT_LENGTH +#define MICROPY_PY_BUILTINS_INT_BIT_LENGTH (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) +#endif + // Whether to support complete set of special methods for user // classes, or only the most used ones. "Inplace" methods are // controlled by MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS below. diff --git a/py/mpz.c b/py/mpz.c index b61997e2fd4ed..c6d31fb961d5a 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -1390,6 +1390,21 @@ void mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t mpz_free(n); } +#if MICROPY_PY_BUILTINS_INT_BIT_LENGTH +mp_uint_t mpz_bit_length_inpl(mpz_t *n) { + if (n->len == 0) { + return 0; + } + mpz_dig_t d = n->dig[n->len - 1]; + mp_uint_t num_bits = 0; + while (d) { + d >>= 1; + ++num_bits; + } + return MPZ_DIG_SIZE * (n->len - 1) + num_bits; +} +#endif + #if 0 these functions are unused diff --git a/py/mpz.h b/py/mpz.h index d27f5724047ae..6b59b840425fe 100644 --- a/py/mpz.h +++ b/py/mpz.h @@ -138,6 +138,9 @@ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); 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); +#if MICROPY_PY_BUILTINS_INT_BIT_LENGTH +mp_uint_t mpz_bit_length_inpl(mpz_t *dest); +#endif static inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_SIZE; diff --git a/py/objint.c b/py/objint.c index be5f4653a7dec..7162080446eca 100644 --- a/py/objint.c +++ b/py/objint.c @@ -367,6 +367,22 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { return MP_OBJ_SMALL_INT_VALUE(self_in); } +#if MICROPY_PY_BUILTINS_INT_BIT_LENGTH +STATIC mp_obj_t int_bit_length(mp_obj_t self_in) { + mp_int_t val = MP_OBJ_SMALL_INT_VALUE(self_in); + if (val < 0) { + val = -val; + } + mp_uint_t n = 0; + while (val) { + val >>= 1; + ++n; + } + return MP_OBJ_NEW_SMALL_INT(n); +} +MP_DEFINE_CONST_FUN_OBJ_1(int_bit_length_obj, int_bit_length); +#endif + #endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE // This dispatcher function is expected to be independent of the implementation of long int @@ -453,6 +469,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_to_bytes_obj, 3, 4, int_to_bytes) STATIC const mp_rom_map_elem_t int_locals_dict_table[] = { { 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) }, + #if MICROPY_PY_BUILTINS_INT_BIT_LENGTH + { MP_ROM_QSTR(MP_QSTR_bit_length), MP_ROM_PTR(&int_bit_length_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table); diff --git a/py/objint.h b/py/objint.h index 5eed87705dedb..f0ce4ee0b3a2f 100644 --- a/py/objint.h +++ b/py/objint.h @@ -62,4 +62,6 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus); +MP_DECLARE_CONST_FUN_OBJ_1(int_bit_length_obj); + #endif // MICROPY_INCLUDED_PY_OBJINT_H diff --git a/py/objint_longlong.c b/py/objint_longlong.c index ee499e0265b32..d78c107b1c962 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -292,4 +292,21 @@ mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) { } #endif +#if MICROPY_PY_BUILTINS_INT_BIT_LENGTH +STATIC mp_obj_t int_bit_length(mp_obj_t self_in) { + mp_obj_int_t *self = self_in; + long long val = self->val; + if (val < 0) { + val = -val; + } + mp_uint_t n = 0; + while (val) { + val >>= 1; + ++n; + } + return MP_OBJ_NEW_SMALL_INT(n); +} +MP_DEFINE_CONST_FUN_OBJ_1(int_bit_length_obj, int_bit_length); +#endif + #endif diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 8078441d66a0b..fd98f47e3c5ad 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -457,4 +457,25 @@ mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) { } #endif +#if MICROPY_PY_BUILTINS_INT_BIT_LENGTH +STATIC mp_obj_t int_bit_length(mp_obj_t self_in) { + if (mp_obj_is_small_int(self_in)) { + mp_int_t val = MP_OBJ_SMALL_INT_VALUE(self_in); + if (val < 0) { + val = -val; + } + mp_uint_t n = 0; + while (val) { + val >>= 1; + ++n; + } + return MP_OBJ_NEW_SMALL_INT(n); + } else { + mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(mpz_bit_length_inpl(&self->mpz)); + } +} +MP_DEFINE_CONST_FUN_OBJ_1(int_bit_length_obj, int_bit_length); +#endif + #endif diff --git a/tests/basics/builtin_help.py.exp b/tests/basics/builtin_help.py.exp index ed8a7d74b8541..5f8d71c318d65 100644 --- a/tests/basics/builtin_help.py.exp +++ b/tests/basics/builtin_help.py.exp @@ -3,9 +3,11 @@ object is of type function object is of type type from_bytes -- to_bytes -- +######## object 1 is of type int from_bytes -- to_bytes -- +######## object is of type module __name__ -- micropython const -- diff --git a/tests/basics/int_bit_length.py b/tests/basics/int_bit_length.py new file mode 100644 index 0000000000000..e1ab02bc83e59 --- /dev/null +++ b/tests/basics/int_bit_length.py @@ -0,0 +1,18 @@ +# tests int.bit_length + +try: + int.bit_length +except AttributeError: + print('SKIP') + raise SystemExit + +for n in (0, 37, 1024, 1<<29, 1<<30, 1<<31, 1<<32, 1<<61, 1<<62, 1<<63, 1<<64): + for j in (-1921, -302, -3, -2, -1, 0, 1, 2, 3, 1821): + for s in (-1, 1): + x = (s * (n+j)) + print(x, x.bit_length()) + +print((2048).bit_length()) +print((-2048).bit_length()) + +print(int.bit_length(5)) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy