I'm using GMP's low-level interface (mpn_
, see https://gmplib.org/manual/Low_002dlevel-Functions) to do some fixed-size 192 bit (three limb) integer calculations.
Currently I am trying to divide one random uint192 by another random uint192 and fail to select the right function. There are multiple candidates:
mpn_tdiv_qr
- Documentation says "most significant limb of the divisor must be non-zero"mpn_divrem
- Documentation says "obsolete"mpn_divrem_1
- Takes a single limb as a divisormpn_divexact_1
- Documentation says "expecting ... to divide exactly"So there is an obsolete function (mpn_divrem
), a function that takes small (<= 64bit) divisors only (mpn_divrem_1
), one that has undefined behavior with remainders (mpn_divexact_1
) and one that takes large (>= 129bit) divisors only (mpn_tdiv_qr
).
I tried mpn_tdiv_qr
since I thought I'm misunderstanding the documentation and because it replaces the obsolete function. But it actually crashes when most significant limb is zero.
Did I miss something? How can I divide two random 3-limb-numbers? Or numbers with a divisor of 65..128 non-zero bits (e.g. 0xffffffff'ffffffffffffffff'ffffffffffffffff / 0xff'ffffffffffffffff
)?
Ok, solution is simple: Instead of passing the number of allocated limbs to mpn_tdiv_qr
pass the number of limbs minus the number of leading zero limbs of the divisor instead. E.g. when using 3 limbs and a concrete divisor has limb[2] == 0
, limb[1] != 0
and limb[0] == 0
a 2
is passed for the divisor length. This way it is guaranteed that the most significant limb (in this case [1]
) is non-zero.