Search code examples
c++gmp

Effectively get the most significant byte of mpz_t struct


I wasn't able to find how gmpxx stores the mpz_t structs under the hood. Thus the only way to get the most significant byte of a number stored as mpz_t is using the mpz_get_str method, but I would expect it to be very slow.

Do you know of a more effective (and simple) way of doing this?

I mean the 'most significant byte' of the number (which is in my case saved as mpz_t) in binary. I.e. for 12345 (10) = 11000000111001 (2) it would be 11000000, no matter gmpxx actually stores it.


Solution

  • Two functions to look at here: size_t mpz_sizeinbase(mpz_t op, int base): this returns the length in a base, and for base=2, it gives the number of bits. void mpz_tdiv_r_2exp (mpz_t r, const mpz_t n, mp_bitcnt_t b): this is equivalent to r = n >> b;. Combined, the operation you are looking for is to bit-shift right exactly sizeinbase-8times:

    size_t bit_length = mpz_sizeinbase(number, 2);
    mpz_tdiv_r_2exp(last_byte, number, bit_length-8);
    

    As a sidenote, the mpz_t struct is stored in "limbs", which are primitives that are chained together. These limbs can have leading 0's to make editing the number easier for small value changes - so accessing them directly is not recommended.

    A limb means the part of a multi-precision number that fits in a single machine word. (We chose this word because a limb of the human body is analogous to a digit, only larger, and containing several digits.) Normally a limb is 32 or 64 bits. The C data type for a limb is mp_limb_t. ~https://gmplib.org/manual/Nomenclature-and-Types.html#Nomenclature-and-Types