FLINT3.7.0-dev

Converting between radix B and binary

Synopsis#include <flint/radix.h>
slong radix_get_mpn(nn_ptr res, nn_srcptr a, slong an, const radix_t radix)source
slong radix_get_mpn_basecase(nn_ptr res, nn_srcptr a, slong an, const radix_t radix)source
slong radix_get_mpn_divconquer(nn_ptr res, nn_srcptr a, slong an, const radix_t radix)source

Convert (a,an)(a, \mathit{an}) from radix BB to the binary radix, writing the limbs to res and returning the normalised length of the result. Leading zero limbs are not counted and may or may not be written. res must have room for the largest integer with an\mathit{an} limbs in radix BB, plus one extra limb, and must not overlap aa. The basecase is Horner's rule (used below 50 limbs).

slong radix_set_mpn(nn_ptr res, nn_srcptr a, slong an, const radix_t radix)source
slong radix_set_mpn_basecase(nn_ptr res, nn_srcptr a, slong an, const radix_t radix)source
slong radix_set_mpn_divconquer(nn_ptr res, nn_srcptr a, slong an, const radix_t radix)source

Convert the binary (a,an)(a, \mathit{an}) to radix BB, writing the limbs to res and returning the normalised length of the result. res must have room for radix_set_mpn_need_alloc(an, radix) limbs and must not overlap aa. The basecase is repeated division by BB (used below 40 limbs). The divide and conquer version caches the most recently used table of powers (per thread), so that repeated conversions of inputs of the same size, as when printing many numbers, do not recompute it.

radix_set_mpn converts a binary limb array to radix B=beB = b^e and radix_get_mpn converts back. For B=1019B = 10^{19} the first is the expensive half of printing a number in decimal, and FLINT's flint_mpn_get_str (hence fmpz_get_str) uses it for base 10 when fft_small is available; once the number is in radix 101910^{19}, writing the digits takes linear time (radix_get_str_decimal).

Both directions use divide and conquer with multiplications only. To convert from radix BB to binary, the input is split as a=alo+ahiBka = a_{\mathrm{lo}} + a_{\mathrm{hi}} B^k with kk about half the length, both halves are converted recursively, and the result is alo+ahi⋅Bka_{\mathrm{lo}} + a_{\mathrm{hi}} \cdot B^k, evaluated with binary arithmetic and a precomputed binary power BkB^k. To convert from binary to radix BB, the binary input is read as a number in radix c=2sc = 2^s with c<Bc < B (cutting it into ss-bit chunks, which is free), and the same recursion is run in reverse: the halves are converted recursively and combined with radix-BB arithmetic (radix_mul, which uses fft_small) and a precomputed radix-BB power ckc^k. No division by a large power is needed, unlike in the classical subquadratic conversion.

AlgorithmRadix conversionConversion between binary and decimal (or any radix beb^e) in quasi-linear time by divide and conquer with multiplications only, carrying out the arithmetic in the target radix.

Sizes and thresholds#

  • radix_get_mpn uses Horner's rule (radix_get_mpn_basecase) below 50 limbs, also at the leaves of the recursion.
  • radix_set_mpn uses repeated division by BB (radix_set_mpn_basecase) below 40 input limbs, and the recursion switches to it on pieces of fewer than 25 chunks.
  • The tables of powers (ck0,ck1,…c^{k_0}, c^{k_1}, \ldots with ki+1=⌈ki/2⌉k_{i+1} = \lceil k_i / 2 \rceil) are built by repeated squaring, with one exact division by cc whenever kik_i is odd. Trailing zero limbs of the powers (the powers of B=1019=219519B = 10^{19} = 2^{19} 5^{19} have many zero bits) are skipped in the multiplications. radix_set_mpn caches the most recent table per thread.
  • Above 500 limbs, the two recursive halves are converted in parallel when threads are available (see Threads).

Example#

Convert 32003^{200} from binary to radix 101910^{19}, print it, and convert it back:

Exampleradix_conversion.cchecked by make checkdoc
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/radix.h>

int main(void)
{
    radix_t radix;
    fmpz_t x;
    nn_ptr d, t;
    slong xn, dn, tn;
    char * s;

    radix_init(radix, 10, 0);   /* B = 10^19 on 64-bit machines */

    fmpz_init(x);
    fmpz_ui_pow_ui(x, 3, 200);
    xn = fmpz_size(x);

    d = flint_malloc(radix_set_mpn_need_alloc(xn, radix) * sizeof(ulong));
    dn = radix_set_mpn(d, COEFF_TO_PTR(*x)->_mp_d, xn, radix);

    s = radix_get_str_decimal(NULL, d, dn, 0, radix);
    flint_printf("%s\n", s);
    flint_printf("%wd digits, %wd decimal limbs\n",
        (slong) _radix_size_digits(d, dn, radix), dn);

    t = flint_malloc((xn + 1) * sizeof(ulong));
    tn = radix_get_mpn(t, d, dn, radix);
    flint_printf("round trip: %d\n",
        tn == xn && mpn_cmp(t, COEFF_TO_PTR(*x)->_mp_d, xn) == 0);

    flint_free(s);
    flint_free(d);
    flint_free(t);
    fmpz_clear(x);
    radix_clear(radix);
    return 0;
}
Output
265613988875874769338781322035779626829233452653394495974574961739092490901302182994384699044001
96 digits, 6 decimal limbs
round trip: 1
Cite this page

The FLINT team, “Converting between radix B and binary (radix.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/radix/conversion.html (generated 2026-11-02).