summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott@adafruit.com>2020-09-08 13:10:57 -0700
committerGitHub <noreply@github.com>2020-09-08 13:10:57 -0700
commitbbd802940ee707fbf8647e0f1017dfb713a94c14 (patch)
treea7ae784edbb390d49e88b31cac36c9b3d645c724
parent540e6d428564f67ad821aeb1da29e11d712a792f (diff)
parent7d58cdb12c001f5a4a0fdf2fc0d1e8c1d4029045 (diff)
Merge pull request #3377 from jepler/support-udecimal
core: Enable some features neede for a port of python3's decimal module
-rw-r--r--py/circuitpy_mpconfig.h1
-rw-r--r--py/mpz.h3
-rw-r--r--py/objint.c25
-rw-r--r--py/objint.h1
-rw-r--r--py/objint_longlong.c11
-rw-r--r--py/objint_mpz.c6
-rw-r--r--tests/basics/bit_length.py4
-rw-r--r--tests/basics/builtin_help.py.exp4
-rw-r--r--tests/cmdline/repl_autocomplete.py.exp2
9 files changed, 54 insertions, 3 deletions
diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h
index 76b91defa..d144f0ba8 100644
--- a/py/circuitpy_mpconfig.h
+++ b/py/circuitpy_mpconfig.h
@@ -185,6 +185,7 @@ typedef long mp_off_t;
// Turning off FULL_BUILD removes some functionality to reduce flash size on tiny SAMD21s
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (CIRCUITPY_FULL_BUILD)
#define MICROPY_CPYTHON_COMPAT (CIRCUITPY_FULL_BUILD)
+#define MICROPY_PY_BUILTINS_POW3 (CIRCUITPY_FULL_BUILD)
#define MICROPY_COMP_FSTRING_LITERAL (MICROPY_CPYTHON_COMPAT)
#define MICROPY_MODULE_WEAK_LINKS (CIRCUITPY_FULL_BUILD)
#define MICROPY_PY_ALL_SPECIAL_METHODS (CIRCUITPY_FULL_BUILD)
diff --git a/py/mpz.h b/py/mpz.h
index e412f5cce..ade04a4f7 100644
--- a/py/mpz.h
+++ b/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);
diff --git a/py/objint.c b/py/objint.c
index b12bb3995..5a33ccbc0 100644
--- a/py/objint.c
+++ b/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) },
};
diff --git a/py/objint.h b/py/objint.h
index bba9ff50a..68997ced2 100644
--- a/py/objint.h
+++ b/py/objint.h
@@ -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);
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 189049630..0a65098c7 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -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) {
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 90060114e..d32fdfbe8 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -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);
diff --git a/tests/basics/bit_length.py b/tests/basics/bit_length.py
new file mode 100644
index 000000000..5eb33f604
--- /dev/null
+++ b/tests/basics/bit_length.py
@@ -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())
diff --git a/tests/basics/builtin_help.py.exp b/tests/basics/builtin_help.py.exp
index ed8a7d74b..89350a6c7 100644
--- a/tests/basics/builtin_help.py.exp
+++ b/tests/basics/builtin_help.py.exp
@@ -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
diff --git a/tests/cmdline/repl_autocomplete.py.exp b/tests/cmdline/repl_autocomplete.py.exp
index 7d160e7bf..0dabc9014 100644
--- a/tests/cmdline/repl_autocomplete.py.exp
+++ b/tests/cmdline/repl_autocomplete.py.exp
@@ -12,7 +12,7 @@ Use \.\+
'abc'
>>> x = 5
>>> x.
-from_bytes to_bytes
+bit_length from_bytes to_bytes
>>> x.
>>> x.__class__
<class 'int'>