-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
.from_bytes() implementation for long MPZ ints #2791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@nickovs: FYI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The usual problem here is to make it work with all configuration options for long ints that we have
What you have here is a good start for the most used case of mpz. Other implementations can follow later, but at least put a dummy implementation of mp_obj_int_from_bytes_impl
for non-mpz cases.
@@ -909,6 +909,36 @@ mp_uint_t mpz_set_from_str(mpz_t *z, const char *str, mp_uint_t len, bool neg, m | |||
return cur - str; | |||
} | |||
|
|||
void mpz_set_from_bytes(mpz_t *z, bool big_endian, mp_uint_t len, byte *buf) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const byte *
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
mpz_dig_t d = 0; | ||
int num_bits = 0; | ||
z->len = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to set z->neg=0
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -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_from_bytes_impl(bool big_endian, size_t len, byte *buf) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const byte *
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
// get the buffer info | ||
mp_buffer_info_t bufinfo; | ||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); | ||
|
||
// convert the bytes to an integer | ||
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be desirable to use the original code path (ie convert to small-int) if the value fits in a small integer. To keep it simple one could just do something like if (MP_SMALL_INT_FITS(1 << (bufinfo.len * 8 -1))) ...
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I of course thought about that, but checking exact conditions for that is boring, so as you point, only heuristic conditions would fit. And then, endian="big" was not implemented for that case. Ok, now I implemented "big" case, that's good. But I still don't think it's worth to spend bytes on this heuristic optimization - not before it was shown to be useful at lease. We have optimizations found to be useful from practice (e.g. #2719), it's better to save bytes for those.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I still don't think it's worth to spend bytes on this heuristic optimization - not before it was shown to be useful at lease
A case where it would be useful is instead of struct.unpack('I', buf)
which creates a tuple to return the single value. Instead one could use int.from_bytes
and it could work without allocating on the heap. See eg end of esp8266/modules/ds18x20.py which does ad-hoc bit shifting to unpack a signed 2-byte integer, in order to avoid allocating memory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It won't help with struct.unpack('I', buf)
, only with struct.unpack('H', buf)
, which is 2 bytes, which is indeed can be easily replaced with shift-or. I will add that optimization later, unless you finally agree it doesn't add much useful ;-).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm getting confused here, and just realised that the title of this PR is wrong, should be from_bytes not to_bytes.
You are right that "I" wont use the small-int path with the simple check for length of incoming buffer. But the more useful case is 'h', ie a signed 2-byte conversion, because that requires more than a shift-or in Python to implement.
My main concern is that this PR is a breaking-change, in the sense that someone who already uses int.from_bytes with the heap locked (eg in an irq) will find that their code stops working after this is merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Title is fixed, sorry. Signed conversion for .from_bytes() is again not implemented. But sounds good, I'll implement what you suggest.
f17dbba
to
96e2235
Compare
@@ -59,6 +59,7 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co | |||
char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, | |||
int base, const char *prefix, char base_char, char comma); | |||
mp_int_t mp_obj_int_hash(mp_obj_t self_in); | |||
mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, byte *buf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you make this const?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now done.
f18b0cb
to
0176acc
Compare
An implementation of int.from_bytes() is now delegated to function mp_obj_int_from_bytes_impl() of particular objint implementation. A version for objint_mpz is provided.
This test works only for MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ and needs a way of skipping in other cases.
To be implemented later.
0176acc
to
04b03bc
Compare
…/o alloc. For a small number of bytes, it's expected to return a small int without allocation.
Ok, this is fully implemented, I'm flushing it to master. |
Squashed a bit and merged. |
Thanks! |
For the unix port, when I test this on Linux it works correctly but when I test this on MacOS it does not work. After a
When I do the same on MacOS I get:
I'm not quite sure what's going on here but something is clearly not right. |
Thanks for the report! Should be fixed by eaa7745 |
Yes, that seems to fix it. |
* Tweak scroll area position so last line is complete and top is under the title bar. * Pick Blinka size based on the font to minimize unused space in title bar. Related to micropython#2791 * Update the title bar after terminal is started. Fixes micropython#6078 Fixes micropython#6668
* Tweak scroll area position so last line is complete and top is under the title bar. * Pick Blinka size based on the font to minimize unused space in title bar. Related to micropython#2791 * Update the title bar after terminal is started. Fixes micropython#6078 Fixes micropython#6668
* Tweak scroll area position so last line is complete and top is under the title bar. * Pick Blinka size based on the font to minimize unused space in title bar. Related to micropython#2791 * Update the title bar after terminal is started. Fixes micropython#6078 Fixes micropython#6668
This is WIP for the discussion in #682 (comment) . The usual problem here is to make it work with all configuration options for long ints that we have, and that update tests for that. That takes me extended time, so I post this WIP for now (which works well for unix port and passes tests).