Re: [PATCH] mini-gmp: avoid a mpz_sizeinbase call in mpz_get_str
Marco Bodrato
bodrato at anjara.org
Thu Oct 15 08:02:41 CEST 2026
Ciao David,
Il giorno Mercoledi, Ottobre 14, 2026 21:31 CEST, David Sparks <sparks05 at proton.me> ha scritto:
> > 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?
The formula proposed by Niels is exactly the one used by the main GMP library.
So...
> (TL;DR: The first failure occurs when b=5 and k=2655232169.)
> Making the search easy, the worst case happens very early, in base 5.
> 2^32 * log_5 2 = 1849741732.079068, rounding up by \eps = 0.920932
> to w = 1849741733. From there, it's easy to see that we don't need
> to consider bases greater than 6.144 (although I checked up to 1000
> in my first draft code).
...as we can check that value 1849741732 + 1 is exactly the one generated
$ tcc -run gen-bases.c table 32 0 | grep \ 5\
/* 5 */ { 13, CNST_LIMB(0x6e40d1a4), CNST_LIMB(0x4a4d3c25), CNST_LIMB(0x48c27395), CNST_LIMB(0xc25c2684) },
0x6e40d1a4 is 1849741732
> FWIW, here are the first 10 failures in base-5:
> Gotcha! k=2655232169 n=1143546251 n'=1143546253
...should we take this as a bug report against the 32-bits version of the main library?
gmp-impl.h reads
#define DIGITS_IN_BASEGT2_FROM_BITS(res, nbits, b) \
do { \
mp_limb_t _ph, _dummy; \
size_t _nbits = (nbits); \
umul_ppmm (_ph, _dummy, mp_bases[b].logb2 + 1, _nbits); \
res = _ph + 1; \
} while (0)
I tried this with the main library:
void check_5 (void)
{
mpz_t n;
unsigned long base = 5;
unsigned long exponent = 1143546251UL;
mpz_init (n);
mpz_ui_pow_ui (n, base, exponent);
mpz_sub_ui (n, n, 1);
printf("Should have %lu <= %zu <= %lu\n", exponent, mpz_sizeinbase (n, base), exponent + 1);
}
With the 32-bits version of the library, it prints
Should have 1143546251 <= 1143546253 <= 1143546252
We should reconsider the implementation of sizeinbase for the main library too.
Ĝis,
mb
More information about the gmp-devel
mailing list