[PATCH] mini-gmp: avoid a mpz_sizeinbase call in mpz_get_str
Pádraig Brady
P at draigBrady.com
Wed Oct 14 21:38:37 CEST 2026
On 14/10/2026 14:59, Niels Möller wrote:
> Niels Möller <nisse at lysator.liu.se> writes:
>
>> The reason it wasn't implemented that way in mini-gmp was that I
>> haven't worked out the required error analysis.
>
> Looking briefly at this again. Assume that x > 0 is an integer of k bits
> and n digits in base b. Then
>
> 2^{k-1} <= x < 2^k
>
> meaning that k = 1 + floor(log_2 x). Similarly
>
> b^{n-1} <= x < b^n
>
> so that n = 1 + floor(log_b x). And the problem of mpn_sizeinbase is
> that given only k, we want to compute an n' such that n <= n' <= n+1.
>
> Since log_b x = log_2 x / log_2 b, we can bound n like
>
> n = 1 + floor (log_b x) = 1 + floor (log_2 x / log_2 b)
> <= 1 + floor (k / log_2 b)
>
> And for the other direction, we can start from
>
> n > log_b x = log_2 x / log_2 b >= (k-1) / log_2 b
> >= floor ((k-1) / log_2 b)
>
> Since n is an integer, the strict inequality implies
>
> n >= 1 + floor ((k-1) / log_2 b)
>
> So we have a rather narrow range
>
> 1 + floor ((k-1) / log_2 b) <= n <= 1 + floor (k / log_2 b)
>
> So it seems natural to use an approximation of 1 / log_2 b. E.g., say we
> put w = ceil (2^{32} / log_2 b), and
>
> n' = 1 + floor (k w / 2^{32})
>
> Then n' >= n, but can n' be too large? The accuracy of w is limited, so
> for large enough k we'll surely get n' > n+1, but how large must k be
> for that to become a problem?
Your analysis looks correct to me.
You could use that to shortcut a huge range,
falling back to the existing implementation outside of that.
So how to bound the combined error from using the bit count
and rounding the reciprocal logarithm upwards?
Using k instead of log_2(x) overestimates by at most one bit.
In base b, that contributes at most 1/log_2(b) digits.
Since non-power-of-two bases are at least 3, this contribution is less than 3/4 of a digit.
Rounding 1/log_2(b) upward to a multiple of 2^-32 adds less than 2^-32 to the coefficient.
Multiplying by k therefore adds less than k/2^32 digits. For k <= 2^30, that is less than 1/4 of a digit.
The combined overestimate is thus less than one digit.
So the proposed approximation is safe through at least
2^30 bits, which is a handy cutoff point.
I've attached a proposed implementation to do that.
cheers,
Padraig
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mini-mpz_sizeinbase-fast.diff
Type: text/x-patch
Size: 1888 bytes
Desc: not available
URL: <https://gmplib.org/list-archives/gmp-devel/attachments/20261014/57e02f93/attachment.bin>
More information about the gmp-devel
mailing list