FLINT3.7.0-dev

Division and rounding conventions

Synopsis#include <flint/fmpz.h>
void fmpz_tdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h)source
void fmpz_fdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h)source
void fmpz_cdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h)source

Set f to the quotient q of g by h, rounded towards zero, -\infty and +\infty respectively, and s to the remainder g - qh. The remainder has the sign of g (tdiv), of h (fdiv) or of -h (cdiv), and |s| < |h|. Throw an exception if h = 0.

void fmpz_ndiv_qr(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b)source

Sets q to a/b rounded to the nearest integer, ties to even, and r to a - qb, so that |r| \le |b|/2. Throws an exception if b = 0.

void fmpz_tdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h)source
void fmpz_fdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h)source
void fmpz_cdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h)source
void fmpz_tdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h)source
void fmpz_fdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h)source
void fmpz_cdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h)source
void fmpz_tdiv_q_si(fmpz_t f, const fmpz_t g, slong h)source
void fmpz_fdiv_q_si(fmpz_t f, const fmpz_t g, slong h)source
void fmpz_cdiv_q_si(fmpz_t f, const fmpz_t g, slong h)source

Set f to the quotient of g by h, rounded towards zero, -\infty and +\infty respectively. Throw an exception if h = 0.

void fmpz_fdiv_r(fmpz_t f, const fmpz_t g, const fmpz_t h)source

Sets f to the remainder of fmpz_fdiv_qr, which has the sign of h. Throws an exception if h = 0.

void fmpz_tdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp)source
void fmpz_fdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp)source
void fmpz_cdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp)source
void fmpz_tdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp)source
void fmpz_fdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp)source
void fmpz_cdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp)source

Set f to the quotient, respectively the remainder, of g by 2^{\mathit{exp}} with the rounding of the prefix. fmpz_fdiv_q_2exp is an arithmetic right shift and fmpz_fdiv_r_2exp the reduction to [0, 2^{\mathit{exp}}).

ulong fmpz_tdiv_ui(const fmpz_t g, ulong h)source
ulong fmpz_fdiv_ui(const fmpz_t g, ulong h)source
ulong fmpz_cdiv_ui(const fmpz_t g, ulong h)source

Return the absolute value of the remainder of g by h with the rounding of the prefix. fmpz_fdiv_ui thus returns g \bmod h in [0, h). Throw an exception if h = 0.

void fmpz_divexact(fmpz_t f, const fmpz_t g, const fmpz_t h)source
void fmpz_divexact_ui(fmpz_t f, const fmpz_t g, ulong h)source
void fmpz_divexact_si(fmpz_t f, const fmpz_t g, slong h)source

Set f to g / h, assuming that h divides g. This is not checked; if the division is not exact the result is meaningless. Faster than the other divisions, since it uses 2-adic (Hensel) division. Throw an exception if h = 0.

void fmpz_divexact2_uiui(fmpz_t f, const fmpz_t g, ulong h1, ulong h2)source

Sets f to g / (h_1 h_2), assuming that h_1 h_2 divides g. Throws an exception if h_1 or h_2 is 0.

int fmpz_div(fmpz_t q, const fmpz_t g, const fmpz_t h)source
int fmpz_div_ui(fmpz_t q, const fmpz_t g, ulong h)source
int fmpz_div_si(fmpz_t q, const fmpz_t g, slong h)source

Checked exact division: if h divides g, set q = g/h and return 1; otherwise set q = 0 and return 0. Division by zero counts as exact only for g = 0 (with q = 0).

For integers g and h \ne 0 there are many pairs (q, r) with g = qh + r and |r| < |h|; a division function picks one by rounding the rational quotient g/h to an integer. The fmpz functions name the rounding in their prefix, following GMP: tdiv truncates (rounds towards zero), fdiv takes the floor, cdiv the ceiling, and ndiv rounds to the nearest integer. A suffix _qr returns quotient and remainder, _q the quotient only and _r the remainder only; _ui and _si take a word-size divisor and _2exp divides by a power of two. Exact division, when the remainder is known to be zero, is a separate and faster operation (fmpz_divexact), and fmpz_div checks exactness.

AlgorithmInteger division and Newton iterationEuclidean division of multiprecision integers by schoolbook division with a 3-by-2 inverse, Burnikel–Ziegler divide and conquer, and Newton iteration with the Karp–Markstein trick; exact division by 2-adic (Hensel) methods; division by a fixed divisor with a precomputed inverse; and square roots by the same techniques.

The four conventions#

PrefixQuotient qSign of the remainder r = g - qhRange of r
tdiv\operatorname{trunc}(g/h)that of g\lvert r \rvert < \lvert h \rvert
fdiv\lfloor g/h \rfloorthat of h0 \le r < h or h < r \le 0
cdiv\lceil g/h \rceilopposite to that of h-h < r \le 0 or 0 \le r < -h
ndivnearest integer to g/h, ties to eveneither\lvert r \rvert \le \lvert h \rvert / 2

A zero remainder satisfies every sign condition. Which to choose:

  • fdiv with h > 0 is reduction modulo h: the remainder lies in [0, h), as returned by fmpz_mod (which also accepts negative h, using |h|). fmpz_fdiv_q_2exp is the arithmetic right shift and fmpz_fdiv_r_2exp the reduction modulo 2^e.
  • tdiv matches C's / and % and is symmetric under g \mapsto -g.
  • cdiv gives the smallest q with qh \ge g for h > 0, as needed for rounding up sizes or bounds.
  • ndiv gives a remainder of minimal absolute value, as needed for balanced representations; fmpz_smod gives the corresponding symmetric residue, but with ties resolved to +|h|/2 instead of by the parity of the quotient.

The functions fmpz_tdiv_ui, fmpz_fdiv_ui and fmpz_cdiv_ui return the absolute value of the remainder as an ulong; only fmpz_fdiv_ui (for which it is the remainder itself) is a residue in [0, h).

The quotients by 2^e are shifts of the two's complement representation for fdiv and of the absolute value for tdiv, so fmpz_tdiv_q_2exp and fmpz_fdiv_q_2exp differ for negative g that are not multiples of 2^e.

Division by zero raises an exception, except in fmpz_mod and fmpz_smod, where it is an unchecked precondition, and in fmpz_div, which reports it as an inexact division unless g = 0.

Exact division#

fmpz_divexact divides g by a divisor h that is known to divide it. The quotient is then determined by the low limbs of g and h alone, and FLINT computes it by 2-adic (Hensel) division from the least significant limb upwards, avoiding the correction steps of Euclidean division. If h does not divide g the result is meaningless; nothing is checked. Typical uses are dividing out a known content or GCD, the last step of an LCM, binomial coefficients, and fraction-free elimination.

fmpz_div (also available under its older name fmpz_divides) is the checked version: it returns 1 and the quotient if h divides g, and 0 otherwise. fmpz_divisible only answers the question, which for large operands is decided from the low limbs by a 2-adic method without forming the whole quotient.

Algorithms#

Inline operands are divided with the C operators and a sign correction. A large dividend with a divisor of one word is divided by one or two hardware divisions if it has at most two limbs, and otherwise by GMP's mpz_tdiv_q_ui and its relatives, built on GMP's mpn_divrem_1 (division by a single limb with a precomputed inverse, Division by an invariant word). Two large operands are divided by _flint_mpn_tdiv_qr, FLINT's replacement of GMP's division. Depending on the sizes it uses schoolbook division with a 3-by-2 inverse, the divide-and-conquer division of Burnikel and Ziegler, block division with a shared approximate inverse for long quotients, or Newton iteration (Karp–Markstein division) once divisor and quotient have about 950 limbs. Exact division (fmpz_divexact, flint_mpn_divexact) uses the 2-adic analogues of the same algorithms. Integer division and Newton iteration describes them; fmpz_fdiv_qr_preinvn exposes the precomputed-inverse division for repeated divisions by the same divisor.

Example#

All four conventions for \pm 7 divided by \pm 2 (each pair is q, r), shifts of a negative number, and exact and checked division of 30!:

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

int main(void)
{
    slong g[4] = { 7, -7, 7, -7 }, h[4] = { 2, 2, -2, -2 };
    fmpz_t a, b, q, r;
    int i;

    fmpz_init(a); fmpz_init(b); fmpz_init(q); fmpz_init(r);

    flint_printf("  g   h |  tdiv   |  fdiv   |  cdiv   |  ndiv\n");
    for (i = 0; i < 4; i++)
    {
        fmpz_set_si(a, g[i]);
        fmpz_set_si(b, h[i]);
        flint_printf("%3wd %3wd |", g[i], h[i]);
        fmpz_tdiv_qr(q, r, a, b);
        flint_printf(" %2wd %2wd  |", fmpz_get_si(q), fmpz_get_si(r));
        fmpz_fdiv_qr(q, r, a, b);
        flint_printf(" %2wd %2wd  |", fmpz_get_si(q), fmpz_get_si(r));
        fmpz_cdiv_qr(q, r, a, b);
        flint_printf(" %2wd %2wd  |", fmpz_get_si(q), fmpz_get_si(r));
        fmpz_ndiv_qr(q, r, a, b);
        flint_printf(" %2wd %2wd\n", fmpz_get_si(q), fmpz_get_si(r));
    }

    /* shifts: division by 2^3 of -100 */
    fmpz_set_si(a, -100);
    fmpz_tdiv_q_2exp(q, a, 3);
    fmpz_fdiv_r_2exp(r, a, 3);
    flint_printf("tdiv_q_2exp(-100, 3) = %wd, fdiv_r_2exp(-100, 3) = %wd\n",
                 fmpz_get_si(q), fmpz_get_si(r));
    fmpz_fdiv_q_2exp(q, a, 3);
    flint_printf("fdiv_q_2exp(-100, 3) = %wd, tdiv_ui(-100, 8) = %wu\n",
                 fmpz_get_si(q), fmpz_tdiv_ui(a, 8));

    /* exact and checked division of 30! by 2^26 3^14 */
    fmpz_fac_ui(a, 30);
    fmpz_one_2exp(b, 26);
    fmpz_mul_ui(b, b, 4782969);         /* 3^14 */
    fmpz_divexact(q, a, b);
    flint_printf("30!/(2^26 3^14) = "); fmpz_print(q); flint_printf("\n");
    fmpz_mul_ui(b, b, 3);
    flint_printf("divisible by 3^15: %d\n", fmpz_div(q, a, b));

    fmpz_clear(a); fmpz_clear(b); fmpz_clear(q); fmpz_clear(r);
    return 0;
}
Output
  g   h |  tdiv   |  fdiv   |  cdiv   |  ndiv
  7   2 |  3  1  |  3  1  |  4 -1  |  4 -1
 -7   2 | -3 -1  | -4  1  | -3 -1  | -4  1
  7  -2 | -3  1  | -4 -1  | -3  1  | -4 -1
 -7  -2 |  3 -1  |  3 -1  |  4  1  |  4  1
tdiv_q_2exp(-100, 3) = -12, fdiv_r_2exp(-100, 3) = 4
fdiv_q_2exp(-100, 3) = -13, tdiv_ui(-100, 8) = 4
30!/(2^26 3^14) = 826385373016328125
divisible by 3^15: 0

For 7/2 = 3.5 the nearest-integer rounding has a tie and chooses the even quotient 4; for -7/2 it chooses -4. The exponents 26 and 14 are the 2-adic and 3-adic valuations of 30!, so the exact quotient is odd and not divisible by 3.

Guides#

Cite this page

The FLINT team, “Division and rounding conventions (fmpz.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz/division.html (generated 2026-10-20).