Skip to content

Commit bbd8029

Browse files
authored
Merge pull request #3377 from jepler/support-udecimal
core: Enable some features neede for a port of python3's decimal module
2 parents 540e6d4 + 7d58cdb commit bbd8029

File tree

9 files changed

+54
-3
lines changed

9 files changed

+54
-3
lines changed

py/circuitpy_mpconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ typedef long mp_off_t;
185185
// Turning off FULL_BUILD removes some functionality to reduce flash size on tiny SAMD21s
186186
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (CIRCUITPY_FULL_BUILD)
187187
#define MICROPY_CPYTHON_COMPAT (CIRCUITPY_FULL_BUILD)
188+
#define MICROPY_PY_BUILTINS_POW3 (CIRCUITPY_FULL_BUILD)
188189
#define MICROPY_COMP_FSTRING_LITERAL (MICROPY_CPYTHON_COMPAT)
189190
#define MICROPY_MODULE_WEAK_LINKS (CIRCUITPY_FULL_BUILD)
190191
#define MICROPY_PY_ALL_SPECIAL_METHODS (CIRCUITPY_FULL_BUILD)

py/mpz.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
135135
void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs);
136136

137137
static inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_SIZE; }
138+
static inline size_t mpz_num_bits(const mpz_t *z) {
139+
size_t last_bits = (8 * (sizeof(long) - sizeof(mpz_dig_t))) - __builtin_clzl(z->dig[z->len-1]);
140+
return z->len * MPZ_DIG_SIZE + last_bits; }
138141
mp_int_t mpz_hash(const mpz_t *z);
139142
bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value);
140143
bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value);

py/objint.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
457457
return MP_OBJ_NULL; // op not supported
458458
}
459459

460+
#if MICROPY_CPYTHON_COMPAT
461+
STATIC mp_obj_t int_bit_length(mp_obj_t self_in) {
462+
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
463+
if (!MP_OBJ_IS_SMALL_INT(self_in)) {
464+
return mp_obj_int_bit_length_impl(self_in);
465+
}
466+
else
467+
#endif
468+
{
469+
mp_int_t int_val = MP_OBJ_SMALL_INT_VALUE(self_in);
470+
mp_uint_t value =
471+
(int_val == 0) ? 0 :
472+
(int_val == MP_SMALL_INT_MIN) ? 8 * sizeof(mp_int_t) :
473+
(int_val < 0) ? 8 * sizeof(long) - __builtin_clzl(-int_val) :
474+
8 * sizeof(long) - __builtin_clzl(int_val);
475+
return mp_obj_new_int_from_uint(value);
476+
}
477+
478+
}
479+
MP_DEFINE_CONST_FUN_OBJ_1(int_bit_length_obj, int_bit_length);
480+
#endif
481+
460482
// this is a classmethod
461483
STATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {
462484
// 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 *
537559
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(int_to_bytes_obj, 3, int_to_bytes);
538560

539561
STATIC const mp_rom_map_elem_t int_locals_dict_table[] = {
562+
#if MICROPY_CPYTHON_COMPAT
563+
{ MP_ROM_QSTR(MP_QSTR_bit_length), MP_ROM_PTR(&int_bit_length_obj) },
564+
#endif
540565
{ MP_ROM_QSTR(MP_QSTR_from_bytes), MP_ROM_PTR(&int_from_bytes_obj) },
541566
{ MP_ROM_QSTR(MP_QSTR_to_bytes), MP_ROM_PTR(&int_to_bytes_obj) },
542567
};

py/objint.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ void mp_obj_int_buffer_overflow_check(mp_obj_t self_in, size_t nbytes, bool is_s
6060
void mp_small_int_buffer_overflow_check(mp_int_t val, size_t nbytes, bool is_signed);
6161

6262
mp_int_t mp_obj_int_hash(mp_obj_t self_in);
63+
mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in);
6364
mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf);
6465
void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf);
6566
int mp_obj_int_sign(mp_obj_t self_in);

py/objint_longlong.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@
4545
const mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX};
4646
#endif
4747

48+
mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in) {
49+
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
50+
mp_obj_int_t *self = self_in;
51+
long long val = self->val;
52+
return MP_OBJ_NEW_SMALL_INT(
53+
(val == 0) ? 0 :
54+
(val == MP_SMALL_INT_MIN) ? 8 * sizeof(long long) :
55+
(val < 0) ? 8 * sizeof(long long) - __builtin_clzll(-val) :
56+
8 * sizeof(long long) - __builtin_clzll(val));
57+
}
58+
4859
mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {
4960
int delta = 1;
5061
if (!big_endian) {

py/objint_mpz.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size,
107107
return str;
108108
}
109109

110+
mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in) {
111+
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
112+
mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
113+
return MP_OBJ_NEW_SMALL_INT(mpz_num_bits(&self->mpz));
114+
}
115+
110116
mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {
111117
mp_obj_int_t *o = mp_obj_int_new_mpz();
112118
mpz_set_from_bytes(&o->mpz, big_endian, len, buf);

tests/basics/bit_length.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
for i in range(129):
2+
j = (1 << i)
3+
print(i, (j-1).bit_length(), (j).bit_length(), (j+1).bit_length())
4+
print(i, (-j-1).bit_length(), (-j).bit_length(), (-j+1).bit_length())

tests/basics/builtin_help.py.exp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
########
22
object <function> is of type function
33
object <class 'int'> is of type type
4+
bit_length -- <function>
45
from_bytes -- <classmethod>
56
to_bytes -- <function>
67
object 1 is of type int
8+
bit_length -- <function>
79
from_bytes -- <classmethod>
810
to_bytes -- <function>
911
object <module 'micropython'> is of type module
1012
__name__ -- micropython
11-
const -- <function>
12-
opt_level -- <function>
1313
########
1414
done

tests/cmdline/repl_autocomplete.py.exp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Use \.\+
1212
'abc'
1313
>>> x = 5
1414
>>> x.
15-
from_bytes to_bytes
15+
bit_length from_bytes to_bytes
1616
>>> x.
1717
>>> x.__class__
1818
<class 'int'>

0 commit comments

Comments
 (0)