diff options
author | Damien George <damien.p.george@gmail.com> | 2015-04-25 23:16:39 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2015-04-25 23:16:39 +0100 |
commit | 271d18eb08ec488ee45f8e6cd852e8236074f082 (patch) | |
tree | f5ba5d1b28cb48e72334fb079a5d6ef148083970 /py/mpz.c | |
parent | 7c8b4c1a8b8278d864649c127857e34a6bd29504 (diff) |
py: Support conversion of bignum to bytes.
This gets int.to_bytes working for bignum, and also struct.pack with 'q'
and 'Q' args on 32-bit machines.
Addresses issue #1155.
Diffstat (limited to 'py/mpz.c')
-rw-r--r-- | py/mpz.c | 34 |
1 files changed, 34 insertions, 0 deletions
@@ -1425,6 +1425,40 @@ bool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) { return true; } +// writes at most len bytes to buf (so buf should be zeroed before calling) +void mpz_as_bytes(const mpz_t *z, bool big_endian, mp_uint_t len, byte *buf) { + byte *b = buf; + if (big_endian) { + b += len; + } + mpz_dig_t *zdig = z->dig; + int bits = 0; + mpz_dbl_dig_t d = 0; + mpz_dbl_dig_t carry = 1; + for (mp_uint_t zlen = z->len; zlen > 0; --zlen) { + bits += DIG_SIZE; + d = (d << DIG_SIZE) | *zdig++; + for (; bits >= 8; bits -= 8, d >>= 8) { + mpz_dig_t val = d; + if (z->neg) { + d = (~d & 0xff) + carry; + carry = d >> 8; + } + if (big_endian) { + *--b = val; + if (b == buf) { + return; + } + } else { + *b++ = val; + if (b == buf + len) { + return; + } + } + } + } +} + #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mpz_as_float(const mpz_t *i) { mp_float_t val = 0; |