radix.h
#include <flint/radix.h>This module implements multiprecision natural number and integer arithmetic in a general radix , where is the machine word radix. The radix is a power of a digit radix , so that one limb holds digits; for decimal arithmetic one normally takes on 64-bit machines ( on 32-bit machines), the largest power of 10 below .
Arithmetic in radix is somewhat slower than in the radix , but everything related to the base becomes cheap: reduction modulo , truncation to digits, shifts by digits and conversion to a string in base take time instead of or . The two principal applications are decimal arithmetic (, see the decimal module) and -adic arithmetic ( a small prime, with Hensel division and -adic square roots; see the padic_radix module).
The module provides low-level functions on limb arrays (in the style of mpn_extras), conversion between radix and the binary radix in quasi-linear time, which flint_mpn_get_str uses for decimal output, and a memory-managed signed integer type radix_integer_t with a generic ring (gr) context. The functions are not optimised for a power of two, where binary arithmetic should be used. The guide Arithmetic in radix b^e shows how to use the module; Converting between radix B and binary describes the conversions to and from binary.
Guides#
Radix objects#
A radix context, holding the digit radix and the limb radix as nmod_t values (fields b and B), the exponent exp , and precomputed data: the powers for , data for division by these powers (n_div_precomp_t), data for division by (see radix_div_exp), the 2-adic valuation of , inverses of the powers of the odd part of , and a function computing digit valuations. A radix_t is passed by reference to every function of the module.
ulong radix_div_exp(ulong x, const radix_t radix)ulong radix_divrem_exp(ulong * r, ulong x, const radix_t radix)Return (and set ), converting a number of digits to a number of limbs without a hardware division. For this is one multiplication by a precomputed , , and a shift, exact for ; larger use n_div_precomp.
void radix_init(radix_t radix, ulong b, unsigned int exp)Initialises radix with digit radix and limb radix where = exp. Requires , and , and throws an exception otherwise. With , the largest with is chosen.
void radix_clear(radix_t radix)Frees the memory used by radix.
void radix_init_randtest(radix_t radix, flint_rand_t state)void radix_init_randtest_prime(radix_t radix, flint_rand_t state)Initialise radix with a random digit radix (a random prime for the second function) and a random exponent, for testing.
ulong radix_digit_radix(const radix_t radix)ulong radix_limb_radix(const radix_t radix)ulong radix_limb_exponent(const radix_t radix)Return , and .
Natural numbers#
The low-level functions work on arrays of limbs (ulong), with the same notation as in mpn_extras: is the natural number in . Unless stated otherwise:
- input limbs must be reduced to , and output limbs are reduced;
- aliasing between outputs and inputs is allowed only if the aliased operands start at the same address;
- normalised means that the top limb is nonzero.
ulong _radix_size_digits_1(ulong c, const radix_t radix)ulong radix_size_digits_1(ulong c, const radix_t radix)Return the number of digits of the limb (the least with ). The underscore version requires ; the other returns 0 for .
ulong _radix_size_digits(nn_srcptr x, slong n, const radix_t radix)ulong radix_size_digits(nn_srcptr x, slong n, const radix_t radix)Return the number of digits of . The underscore version requires and ; the other allows and zero top limbs, which it skips, and returns 0 for zero.
ulong _radix_valuation_digits_1(ulong c, const radix_t radix)Returns the number of trailing zero digits of the limb , that is, the largest such that divides .
void radix_rand_limbs(nn_ptr res, flint_rand_t state, slong n, const radix_t radix)void radix_rand_digits(nn_ptr res, flint_rand_t state, slong n, const radix_t radix)Set to a uniformly random integer in , respectively to a uniformly random integer in .
void radix_randtest_limbs(nn_ptr res, flint_rand_t state, slong n, const radix_t radix)void radix_randtest_digits(nn_ptr res, flint_rand_t state, slong n, const radix_t radix)Like radix_rand_limbs and radix_rand_digits, but with a non-uniform distribution producing long runs of limbs equal to 0 or , for testing.
Addition and shifts#
Set to , respectively , modulo and return the carry, respectively the borrow (0 or 1). Requires .
Sets to the -complement and returns the borrow (1 if , 0 otherwise).
Shift by = e digits, for less than the limb exponent: the left shift sets to and returns the digits shifted out (as the low digits of the returned limb); the right shift sets to and returns the digits shifted out as the high digits of the returned limb, that is, . These are faster than radix_mul_1 and radix_divrem_1 with . Shifts by whole limbs are pointer offsets.
ulong radix_addlsh(nn_ptr res, nn_srcptr a, slong an, nn_srcptr b, slong bn, unsigned int sh, const radix_t radix)ulong radix_sublsh(nn_ptr res, nn_srcptr a, slong an, nn_srcptr b, slong bn, unsigned int sh, const radix_t radix)ulong radix_lshsub(nn_ptr res, nn_srcptr b, slong bn, unsigned int sh, nn_srcptr a, slong an, const radix_t radix)Fused addition and subtraction with a shift of by digits: set with to , and , and return the carry (0 or 1), respectively the borrow, which is 0 since the result must be nonnegative. Requires . res may alias but not . The shifted operand is never formed in memory.
int radix_cmplsh(nn_srcptr a, slong an, nn_srcptr b, slong bn, unsigned int sh, const radix_t radix)Returns the sign of for normalised and and .
Multiplication#
Sets to and returns the carry . Requires and .
Sets to and returns the carry.
Set to , respectively to . Requires ; res must not overlap the inputs. Both are calls to radix_mulmid with the full window (there is no special squaring code yet).
void radix_mulmid(nn_ptr res, nn_srcptr a, slong an, nn_srcptr b, slong bn, slong lo, slong hi, const radix_t radix)Windowed product: for and , sets to the limbs of the product, computed without the carries from the limbs below . res must not overlap the inputs.
void radix_mulmid_classical(nn_ptr res, nn_srcptr a, slong an, nn_srcptr b, slong bn, slong lo, slong hi, const radix_t radix)void radix_mulmid_fft_small(nn_ptr res, nn_srcptr a, slong an, nn_srcptr b, slong bn, slong lo, slong hi, const radix_t radix)void radix_mulmid_KS(nn_ptr res, nn_srcptr a, slong an, nn_srcptr b, slong bn, slong lo, slong hi, const radix_t radix)void radix_mulmid_naive(nn_ptr res, nn_srcptr a, slong an, nn_srcptr b, slong bn, slong lo, slong hi, const radix_t radix)The algorithms behind radix_mulmid, with its interface: the schoolbook algorithm with delayed reduction of the column sums, efficient when an operand or the window is short; multiplication of the limb sequences as polynomials with the small-prime FFT of fft_small (only available if FLINT is built with it), reconstructing only the coefficients that reach the window and propagating carries in radix ; Kronecker substitution into one product in the binary radix (each limb padded to two words); and an unoptimised reference implementation through fmpz_poly.
double _radix_mulmid_pairs_below(slong an, slong bn, slong k)Returns the number of pairs with , and , as a double (it may exceed the range of slong on 32-bit machines). It counts the limb products of the classical algorithm and is used for tuning decisions.
The tuning ratio of radix_mulmid. With fft_small it is FLINT_RADIX_MULMID_FFT_SMALL_CUTOFF_RATIO, which every flint-mparam.h must define: 50 on Zen 3 and Zen 4, 60 on Ice Lake and later Intel cores and in the generic files, 80 on Skylake and Broadwell, 85 on arm64 (measured on Apple M4). The measured crossover is the same for balanced full products, Newton middle products and short windows of a long operand; a balanced full product of limbs switches to the FFT at ratio, 100 to 170 limbs. Without fft_small the ratio is 175 (Kronecker substitution pads each limb to two words, so the crossover for a balanced full product is at about 350 limbs).
The length of the convolution that radix_mulmid_fft_small computes for the window , used by radix_mulmid to choose the algorithm: with and the numbers of limbs of the operands that reach the window, it is if the window (clipped to the product) is shorter than , and otherwise; 0 for an empty window.
void _radix_mulhigh_known_low(nn_ptr out, nn_srcptr x, slong xn, nn_srcptr y, slong yn, nn_srcptr kl, slong kl_len, slong klo, slong khi, nn_ptr scratch, const radix_t radix)The radix analogue of _flint_mpn_mulhigh_known_low: sets to the exact limbs of , given that its low limbs are (zero above kl_len), using a windowed product with guard limbs. scratch must have room for limbs. Used by the Hensel division and -adic square roots.
Division#
Division in radix follows the structure of the binary case: small divisors are handled directly, large ones by Newton iteration on fixed-point approximations of the reciprocal, and medium sizes by converting to binary and using flint_mpn_tdiv_qr.
Set to and return the remainder, for ; the same assuming that divides (the result is undefined otherwise); and division by 2.
Given with , read as a fixed-point number with fraction limbs, set to an approximation of with fraction limbs and two integral limbs (the top one may be zero). The absolute error is less than (relative error less than ). The general version uses Newton iteration from the basecase.
void radix_div_approx_invmul(nn_ptr Q, nn_srcptr B, slong Bn, nn_srcptr A, slong An, slong n, const radix_t radix)void radix_div_approx(nn_ptr Q, nn_srcptr B, slong Bn, nn_srcptr A, slong An, slong n, const radix_t radix)Given the divisor with nonzero top limb, read as a fixed-point number in with fraction limbs, and the dividend , read as a fixed-point number in with fraction limbs, set to an approximation of the quotient with fraction limbs and two integral limbs; the absolute error is less than divided by the divisor. Note the order of the arguments: the dividend comes first. The invmul version multiplies by an approximate reciprocal; the general version uses Karp–Markstein iteration [KM1997].
void radix_divrem(nn_ptr q, nn_ptr r, nn_srcptr a, slong an, nn_srcptr b, slong bn, const radix_t radix)Sets to and, if is not NULL, to the remainder. Requires and .
void radix_divrem_via_mpn(nn_ptr q, nn_ptr r, nn_srcptr a, slong an, nn_srcptr b, slong bn, const radix_t radix)void radix_divrem_newton(nn_ptr q, nn_ptr r, nn_srcptr a, slong an, nn_srcptr b, slong bn, const radix_t radix)void radix_divrem_newton_karp_markstein(nn_ptr Q, nn_ptr R, nn_srcptr A, slong An, nn_srcptr B, slong Bn, const radix_t radix)The algorithms behind radix_divrem, with its interface: conversion to binary, division by a Newton reciprocal, and Karp–Markstein division (quotient from a half-precision reciprocal and one correction step).
void radix_divrem_preinv(nn_ptr q, nn_ptr r, nn_srcptr a, slong an, nn_srcptr b, slong bn, nn_srcptr binv, slong binvn, const radix_t radix)radix_divrem with a precomputed inverse of given as with fraction limbs, as computed by radix_inv_approx. Requires ; a few extra limbs can improve performance. may be NULL.
If divides , sets to the quotient and returns 1; otherwise returns 0, the contents of being undefined.
Sets to , assuming that the division is exact; the result is undefined otherwise.
int radix_cmp_bn_half(nn_srcptr x, slong n, const radix_t radix)Returns , 0 or 1 according to whether is less than, equal to or greater than . Requires . Used for rounding to nearest and for symmetric remainders.
Square roots#
Sets to and, if is not NULL, to the remainder . Requires and . Inputs shorter than a cutoff depending on the size of (43 limbs for ) are converted to binary and use flint_mpn_sqrtrem; longer ones use the Newton square root.
int radix_sqrt(nn_ptr s, nn_srcptr a, slong an, const radix_t radix)Sets to and returns 1 if is a perfect square and 0 otherwise. Requires and .
void radix_sqrtrem_newton_karp_markstein(nn_ptr s, nn_ptr r, nn_srcptr a, slong an, const radix_t radix)The algorithms behind radix_sqrtrem, with its interface: conversion to binary, and the root from a reciprocal square root by one Karp–Markstein step, with a final correction.
void radix_rsqrt_1_approx_basecase(nn_ptr res, ulong a, slong n, const radix_t radix)void radix_rsqrt_1_approx(nn_ptr res, ulong a, slong n, const radix_t radix)Set to the fraction limbs of an approximation of for , with error less than .
Given read as a fixed-point number with fraction limbs (one of the top two limbs nonzero), set to an approximation of with fraction limbs and two integral limbs, with absolute error less than . The range of is wider than for radix_inv_approx so that inputs with an odd number of limbs can be handled, the scale factor not being a limb shift.
With as for radix_rsqrt_approx, set to an approximation of with fraction limbs and two integral limbs (normally zero, though the value can round up to 1), with absolute error less than . The error is proportional to rather than to , because the corrections of the last iteration are multiplied by an approximation of .
Hensel division and -adic square roots#
Arithmetic modulo , developing results from the least significant limb upwards. For prime this is arithmetic in with precision digits. mpn_extras has ports of these algorithms to the binary radix (Hensel division and 2-adic square roots).
If is invertible modulo (that is, is coprime to ), sets to its inverse and returns 1; otherwise returns 0. Newton iteration on windowed products.
int radix_divmod_bn(nn_ptr q, nn_ptr rem, nn_srcptr a, slong an, nn_srcptr b, slong bn, slong n, const radix_t radix)Given invertible modulo , sets to the -adic (Hensel) quotient with and returns 1; returns 0 if is not invertible. If rem is not NULL, the remainder is written to , so that .
int radix_divmod_bn_1(nn_ptr q, nn_ptr rem, nn_srcptr a, slong an, ulong b, slong n, const radix_t radix)int radix_divmod_bn_classical(nn_ptr q, nn_ptr rem, nn_srcptr a, slong an, nn_srcptr b, slong bn, slong n, const radix_t radix)int radix_divmod_bn_karp_markstein(nn_ptr q, nn_ptr rem, nn_srcptr a, slong an, nn_srcptr b, slong bn, slong n, const radix_t radix)The algorithms behind radix_divmod_bn, with its interface: a one-limb divisor (with rem of one limb), the blockwise algorithm (one low and one high product per block of limbs), and the Karp–Markstein form with a half-precision inverse.
For a prime digit radix (with if ): if is a unit and a square modulo (modulo 8 if ), set to a square root of modulo , respectively to the inverse of that square root, and return 1; otherwise return 0. The square root returned is the one whose residue modulo is the smallest nonnegative one.
Radix conversion#
Conversion between radix and the binary radix in time by divide and conquer, with multiplications only (no divisions). See Converting between radix B and binary and Radix conversion.
Convert from radix 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 limbs in radix , plus one extra limb, and must not overlap . The basecase is Horner's rule (used below 50 limbs).
Convert the binary to radix , 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 . The basecase is repeated division by (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.
slong radix_set_mpn_need_alloc(slong n, const radix_t radix)Returns a number of output limbs that is sufficient for radix_set_mpn with an input of limbs.
A table of the powers used by the divide and conquer conversions, with the top exponent and down to 1, together with their lengths and their numbers of trailing zero limbs.
void radix_powers_clear(radix_powers_t powers)Frees a table of powers.
String conversion#
char * radix_get_str_decimal(char * res, nn_srcptr x, slong n, int negative, const radix_t radix)Returns the decimal representation of as a null-terminated string, with a leading minus sign if negative is 1; for the string is 0. The top limb must be nonzero (if ). If res is NULL, a new string is allocated with flint_malloc; otherwise res must have room for the result and the terminating null. If , this takes time (each limb is printed with table lookups for pairs of digits); otherwise is converted to binary and then to decimal, in time .
char * radix_get_str_sum(char * res, nn_srcptr x, slong n, int negative, int ascending, const radix_t radix)Returns written as a sum over its limbs. For example, 12345678 in radix is printed as 12 * 10^6 + 345 * 10^3 + 678 with negative and ascending both 0, and as -(678 + 345 * 10^3 + 12 * 10^6) with both 1. Memory as for radix_get_str_decimal.
Integers#
A signed integer in radix , in a format similar to mpz_t: the fields are d (pointer to the limbs), alloc (the number of allocated limbs) and size, whose absolute value is the normalised number of limbs and whose sign is the sign of the integer. The radix is not stored and must be passed to every function.
void gr_ctx_init_radix_integer(gr_ctx_t ctx, ulong b, unsigned int exp)Initialises ctx as the generic ring of integers in radix (with selecting the largest admissible exponent), whose elements are radix_integer_t. The context owns its radix_t.
void radix_integer_init(radix_integer_t res, const radix_t radix)void radix_integer_clear(radix_integer_t res, const radix_t radix)nn_ptr radix_integer_fit_limbs(radix_integer_t res, slong nlimbs, const radix_t radix)Initialise to zero and free an integer, and make sure that it has room for nlimbs limbs, returning the pointer to its limbs (which the caller may then fill, setting size accordingly).
int radix_integer_is_normalised(const radix_integer_t x, const radix_t radix)Returns whether all limbs of are reduced modulo and the top limb is nonzero. Operations on a non-normalised integer have undefined behaviour.
void radix_integer_zero(radix_integer_t res, const radix_t radix)void radix_integer_one(radix_integer_t res, const radix_t radix)void radix_integer_neg_one(radix_integer_t res, const radix_t radix)void radix_integer_set(radix_integer_t res, const radix_integer_t x, const radix_t radix)void radix_integer_set_ui(radix_integer_t res, ulong x, const radix_t radix)void radix_integer_set_si(radix_integer_t res, slong x, const radix_t radix)void radix_integer_set_fmpz(radix_integer_t res, const fmpz_t x, const radix_t radix)void radix_integer_get_fmpz(fmpz_t res, const radix_integer_t x, const radix_t radix)Assignment and conversion; radix_integer_set_fmpz and radix_integer_get_fmpz use the radix conversion functions.
void radix_integer_rand_limbs(radix_integer_t res, flint_rand_t state, slong max_limbs, const radix_t radix)void radix_integer_randtest_limbs(radix_integer_t res, flint_rand_t state, slong max_limbs, const radix_t radix)Set res to a random signed integer of at most max_limbs limbs, with a uniform respectively a test distribution of the limbs.
int radix_integer_is_zero(const radix_integer_t x, const radix_t radix)int radix_integer_is_one(const radix_integer_t x, const radix_t radix)int radix_integer_is_neg_one(const radix_integer_t x, const radix_t radix)int radix_integer_equal(const radix_integer_t x, const radix_integer_t y, const radix_t radix)int radix_integer_cmp(const radix_integer_t x, const radix_integer_t y, const radix_t radix)int radix_integer_cmpabs(const radix_integer_t x, const radix_integer_t y, const radix_t radix)int radix_integer_sgn(const radix_integer_t x, const radix_t radix)Predicates and comparisons; cmp and cmpabs return the sign of and .
slong radix_integer_size_limbs(const radix_integer_t x, const radix_t radix)slong radix_integer_size_digits(const radix_integer_t x, const radix_t radix)slong radix_integer_ssize_limbs(const radix_integer_t x, const radix_t radix)slong radix_integer_ssize_digits(const radix_integer_t x, const radix_t radix)The number of limbs, respectively digits, of ; the ssize versions return it negated if is negative.
ulong radix_integer_get_limb(const radix_integer_t x, slong n, const radix_t radix)ulong radix_integer_get_digit(const radix_integer_t x, slong index, const radix_t radix)Return the limb, respectively the digit, of at the given nonnegative position (zero beyond the top).
void radix_integer_set_limb(radix_integer_t res, const radix_integer_t x, slong index, ulong c, const radix_t radix)void radix_integer_set_digit(radix_integer_t res, const radix_integer_t x, slong index, ulong c, const radix_t radix)Set res to with the limb (digit) at the nonnegative position index of replaced by (). The sign of is kept; if is zero and nonzero, the result is positive.
void radix_integer_neg(radix_integer_t res, const radix_integer_t x, const radix_t radix)void radix_integer_abs(radix_integer_t res, const radix_integer_t x, const radix_t radix)void radix_integer_add(radix_integer_t res, const radix_integer_t x, const radix_integer_t y, const radix_t radix)void radix_integer_sub(radix_integer_t res, const radix_integer_t x, const radix_integer_t y, const radix_t radix)void radix_integer_mul(radix_integer_t res, const radix_integer_t x, const radix_integer_t y, const radix_t radix)Negation, absolute value, sum, difference and product.
void radix_integer_lshift_limbs(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)void radix_integer_lshift_digits(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)void radix_integer_rshift_limbs(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)void radix_integer_rshift_digits(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)Set res to (), respectively to () truncated towards zero, for .
void radix_integer_addlsh(radix_integer_t res, const radix_integer_t x, const radix_integer_t y, slong v, const radix_t radix)void radix_integer_sublsh(radix_integer_t res, const radix_integer_t x, const radix_integer_t y, slong v, const radix_t radix)Set res to , respectively , for any digit shift , without forming the shifted operand: the shift is split into whole limbs (a pointer offset) and digits (the fused radix_addlsh family). Any aliasing is allowed.
slong radix_integer_valuation_limbs(const radix_integer_t x, const radix_t radix)slong radix_integer_valuation_digits(const radix_integer_t x, const radix_t radix)Return the largest such that (respectively ) divides , that is, the number of trailing zero limbs (digits); 0 for .
void radix_integer_trunc_limbs(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)void radix_integer_trunc_digits(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)void radix_integer_mod_limbs(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)void radix_integer_mod_digits(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)void radix_integer_smod_limbs(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)Reductions modulo (respectively ): trunc reduces and keeps the sign of ; mod returns the representative in (); smod returns the symmetric representative, in for odd and in for even . These take time plus the time to copy.
void radix_integer_mullow_limbs(radix_integer_t res, const radix_integer_t x, const radix_integer_t y, slong n, const radix_t radix)Sets res to with the absolute value reduced modulo , using a low product.
int radix_integer_invmod_limbs(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)int radix_integer_divmod_limbs(radix_integer_t res, const radix_integer_t a, const radix_integer_t b, slong n, const radix_t radix)int radix_integer_rsqrtmod_limbs(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)int radix_integer_sqrtmod_limbs(radix_integer_t res, const radix_integer_t x, slong n, const radix_t radix)Inverse, quotient , inverse square root and square root modulo , by radix_invmod_bn, radix_divmod_bn, radix_rsqrtmod_bn and radix_sqrtmod_bn applied to the absolute values; the sign of the inputs is carried over to the result. Return 1 on success and 0 if the operand is not invertible (respectively not a square).
int radix_integer_div(radix_integer_t q, const radix_integer_t a, const radix_integer_t b, const radix_t radix)void radix_integer_divexact(radix_integer_t q, const radix_integer_t a, const radix_integer_t b, const radix_t radix)If divides , radix_integer_div sets to and returns 1; otherwise it sets to zero and returns 0. radix_integer_divexact sets to assuming that the division is exact (the result is undefined otherwise).
void radix_integer_tdiv_qr(radix_integer_t q, radix_integer_t r, const radix_integer_t a, const radix_integer_t b, const radix_t radix)void radix_integer_fdiv_qr(radix_integer_t q, radix_integer_t r, const radix_integer_t a, const radix_integer_t b, const radix_t radix)void radix_integer_cdiv_qr(radix_integer_t q, radix_integer_t r, const radix_integer_t a, const radix_integer_t b, const radix_t radix)void radix_integer_tdiv_q(radix_integer_t q, const radix_integer_t a, const radix_integer_t b, const radix_t radix)void radix_integer_fdiv_q(radix_integer_t q, const radix_integer_t a, const radix_integer_t b, const radix_t radix)void radix_integer_cdiv_q(radix_integer_t q, const radix_integer_t a, const radix_integer_t b, const radix_t radix)void radix_integer_tdiv_r(radix_integer_t r, const radix_integer_t a, const radix_integer_t b, const radix_t radix)void radix_integer_fdiv_r(radix_integer_t r, const radix_integer_t a, const radix_integer_t b, const radix_t radix)void radix_integer_cdiv_r(radix_integer_t r, const radix_integer_t a, const radix_integer_t b, const radix_t radix)Division with remainder , where the quotient is rounded towards zero (tdiv), towards (fdiv) or towards (cdiv), as in GMP's mpz functions. must be nonzero.
int radix_integer_inv(radix_integer_t res, const radix_integer_t x, const radix_t radix)int radix_integer_is_invertible(const radix_integer_t x, const radix_t radix) is invertible in if and only if . radix_integer_inv sets res to and returns 1 in that case and returns 0 otherwise.
int radix_integer_sqrt(radix_integer_t s, const radix_integer_t x, const radix_t radix)void radix_integer_sqrtrem(radix_integer_t s, radix_integer_t r, const radix_integer_t x, const radix_t radix)int radix_integer_is_square(const radix_integer_t x, const radix_t radix)radix_integer_sqrt sets to and returns 1 if is a perfect square and 0 otherwise; for negative it returns 0 without modifying . radix_integer_sqrtrem sets and the remainder , and throws an exception for negative . radix_integer_is_square returns whether is a perfect square (0 for negative ).
Division by an invariant word#
The following inline functions divide words by a fixed word with a precomputed multiplier, by the method of Granlund and Montgomery [GraMon1994] in the variant of Robison [Rob2005] that needs no multiplier wider than a word. They are used for the digit shifts of this module, where is a power of .
Precomputed data for division by : the exponent (field e), a multiplier m and a flag c. If is a power of two, . Otherwise, with , either and (the round-up method, when it is exact for all words) or and (the round-down method with an increment).
A pair of words (fields a and b).
void n_div_precomp_init(n_div_precomp_t pre, ulong d)Computes the data for division by .
ulong n_div_precomp(ulong x, const n_div_precomp_t pre)ulong n_div_precomp_bounded(ulong x, const n_div_precomp_t pre)ulong n_div_precomp_m0(ulong x, const n_div_precomp_t pre)ulong n_div_precomp_c0(ulong x, const n_div_precomp_t pre)ulong n_div_precomp_c1(ulong x, const n_div_precomp_t pre)ulong n_div_precomp_c1_bounded(ulong x, const n_div_precomp_t pre)Return for any word : n_div_precomp selects the method from pre, and the other functions are the individual methods for callers that know the case: for a power of two (), for , and for , where saturates at . The bounded versions require and skip the saturation.
ulong n_rem_precomp(ulong x, ulong d, const n_div_precomp_t pre)ulong n_rem_precomp_bounded(ulong x, ulong d, const n_div_precomp_t pre)ulong n_rem_precomp_m0(ulong x, ulong d, const n_div_precomp_t pre)ulong n_rem_precomp_c0(ulong x, ulong d, const n_div_precomp_t pre)ulong n_rem_precomp_c1(ulong x, ulong d, const n_div_precomp_t pre)ulong n_rem_precomp_c1_bounded(ulong x, ulong d, const n_div_precomp_t pre)ulong n_divrem_precomp(ulong * r, ulong x, ulong d, const n_div_precomp_t pre)ulong n_divrem_precomp_bounded(ulong * r, ulong x, ulong d, const n_div_precomp_t pre)ulong n_divrem_precomp_m0(ulong * r, ulong x, ulong d, const n_div_precomp_t pre)ulong n_divrem_precomp_c0(ulong * r, ulong x, ulong d, const n_div_precomp_t pre)ulong n_divrem_precomp_c1(ulong * r, ulong x, ulong d, const n_div_precomp_t pre)ulong n_divrem_precomp_c1_bounded(ulong * r, ulong x, ulong d, const n_div_precomp_t pre)The remainder , and the quotient with the remainder stored in *r, with the same variants as the quotient functions.
References#
- [KM1997] A. H. Karp and P. Markstein, "High-precision division and square root", ACM Transactions on Mathematical Software 23:4 (1997), 561–589
- [GraMon1994] Törbjorn Granlund and Peter L. Montgomery : Division by Invariant Integers using Multiplication https://gmplib.org/~tege/divcnst-pldi94.pdf
- [Rob2005] A. D. Robison. N-bit unsigned division via N-bit multiply-add. Proceedings of the 17th IEEE Symposium on Computer Arithmetic (ARITH-17), 2005, 131–139.
The FLINT team, “radix.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/radix/index.html (generated 2026-11-02).
@misc{flint-doc-radix-index,
author = {{The FLINT team}},
title = {{radix.h (module overview)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/radix/index.html},
note = {Generated 2026-11-02}
}