py/mpz: Implement mpz_set_from_bytes() as a foundation for int.from_bytes().

This commit is contained in:
Paul Sokolovsky 2017-01-21 20:07:50 +03:00
parent 5298472fee
commit 1b42f5251f
2 changed files with 32 additions and 0 deletions

View File

@ -909,6 +909,37 @@ 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, const byte *buf) {
int delta = 1;
if (big_endian) {
buf += len - 1;
delta = -1;
}
mpz_need_dig(z, (len * 8 + DIG_SIZE - 1) / DIG_SIZE);
mpz_dig_t d = 0;
int num_bits = 0;
z->neg = 0;
z->len = 0;
while (len) {
while (len && num_bits < DIG_SIZE) {
d |= *buf << num_bits;
num_bits += 8;
buf += delta;
len--;
}
z->dig[z->len++] = d & DIG_MASK;
// Need this #if because it's C undefined behavior to do: uint32_t >> 32
#if DIG_SIZE != 8 && DIG_SIZE != 16 && DIG_SIZE != 32
d >>= DIG_SIZE;
#else
d = 0;
#endif
num_bits -= DIG_SIZE;
}
}
bool mpz_is_zero(const mpz_t *z) {
return z->len == 0;
}

View File

@ -109,6 +109,7 @@ void mpz_set_from_ll(mpz_t *z, long long i, bool is_signed);
void mpz_set_from_float(mpz_t *z, mp_float_t src);
#endif
mp_uint_t mpz_set_from_str(mpz_t *z, const char *str, mp_uint_t len, bool neg, mp_uint_t base);
void mpz_set_from_bytes(mpz_t *z, bool big_endian, mp_uint_t len, const byte *buf);
bool mpz_is_zero(const mpz_t *z);
int mpz_cmp(const mpz_t *lhs, const mpz_t *rhs);