aboutsummaryrefslogtreecommitdiff
path: root/py/mpz.c
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2017-01-21 20:07:50 +0300
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2017-01-21 20:07:50 +0300
commit1b42f5251fb126496584e2fc61fad12bca7f7152 (patch)
tree60949a74d7f8ca717ea8767de7651e2e38b6937d /py/mpz.c
parent5298472fee1a83878e4670c1f8c885aefc087765 (diff)
py/mpz: Implement mpz_set_from_bytes() as a foundation for int.from_bytes().
Diffstat (limited to 'py/mpz.c')
-rw-r--r--py/mpz.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/py/mpz.c b/py/mpz.c
index e503927d0..6477c3f8d 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -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;
}