FLINT3.7.0-dev

GCD, LCM and Bézout coefficients

Synopsis#include <flint/fmpz.h>
void fmpz_gcd(fmpz_t f, const fmpz_t g, const fmpz_t h)source
void fmpz_gcd_ui(fmpz_t res, const fmpz_t a, ulong b)source

Set ff to gcd⁡(g,h)≥0\gcd(g, h) \ge 0, with gcd⁡(0,0)=0\gcd(0, 0) = 0.

void fmpz_gcd3(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c)source

Sets ff to gcd⁡(a,b,c)≥0\gcd(a, b, c) \ge 0. Faster than two calls to fmpz_gcd when one operand is small or the GCD of the two shortest operands is 1.

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

Sets ff to the least common multiple of gg and hh, which is nonnegative, and 0 if gg or hh is 0.

void fmpz_xgcd(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g)source

Sets d=gcd⁡(f,g)≥0d = \gcd(f, g) \ge 0 and cofactors aa, bb with af+bg=daf + bg = d. The outputs must be distinct objects.

void fmpz_xgcd_canonical_bezout(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g)source

As fmpz_xgcd, but the cofactors are the canonical Bézout coefficients defined on GCD, LCM and Bézout coefficients: the minimal ones, with fixed choices in the degenerate cases. Usually faster than fmpz_xgcd.

void fmpz_gcdinv(fmpz_t d, fmpz_t a, const fmpz_t f, const fmpz_t g)source

For 0≤f<g0 \le f < g, sets d=gcd⁡(f,g)d = \gcd(f, g) and aa to a cofactor in [0,g)[0, g) with af≡d(modg)af \equiv d \pmod g, so that a=f−1 mod ga = f^{-1} \bmod g if d=1d = 1. For f=0f = 0 it sets d=gd = g and a=0a = 0. The outputs must be distinct objects.

fmpz_gcd computes the greatest common divisor of two integers, and fmpz_gcd3 and fmpz_lcm build on it. For the extended GCD, which also returns cofactors a,ba, b with af+bg=gcd⁡(f,g)af + bg = \gcd(f, g), there are three functions that differ in how the cofactors are normalised: fmpz_xgcd_canonical_bezout returns the canonical (minimal) cofactors and is the one to use in new code, fmpz_xgcd returns cofactors of another, older normalisation, and fmpz_gcdinv returns only the cofactor of the smaller operand, reduced modulo the larger, which is what a modular inverse needs. fmpz_invmod (Modular arithmetic with integers) is the direct way to invert modulo an integer.

AlgorithmInteger GCDGreatest common divisors of multiprecision integers by the binary algorithm, Lehmer's algorithm and the subquadratic half-GCD, in the matrix formulation shared with continued fractions; contents and least common multiples of vectors by divisibility tests; the port of GMP's implementation with transform-space matrix products behind fmpz_gcd and fmpz_xgcd, and FLINT's own half-GCD for continued fractions and rational reconstruction.

Values and signs#

The GCD is always nonnegative, with gcd⁡(f,0)=∣f∣\gcd(f, 0) = |f| and gcd⁡(0,0)=0\gcd(0, 0) = 0; the LCM is nonnegative and 0 if either operand is 0. All three functions accept any signs and allow aliasing.

Normalisation of the cofactors#

The cofactors of Bézout's identity are not unique: with d=gcd⁡(f,g)d = \gcd(f, g), (a+kg/d,b−kf/d)(a + kg/d, b - kf/d) is a solution for every kk.

fmpz_xgcd_canonical_bezout returns the solution with the smallest cofactors, which is unique up to the cases below. Writing d=gcd⁡(f,g)d = \gcd(f, g), the result satisfies

∣a∣<∣g∣2d,∣b∣<∣f∣2d,|a| < \frac{|g|}{2d}, \qquad |b| < \frac{|f|}{2d},

except in the following cases, where the result is fixed as listed (this is also the normalisation of GMP's mpz_gcdext [GMP]):

Case(d,a,b)(d, a, b)
∣f∣=∣g∣\lvert f \rvert = \lvert g \rvert(∣g∣,0,sgn⁡g)(\lvert g \rvert, 0, \operatorname{sgn} g)
g=0g = 0(∣f∣,sgn⁡f,0)(\lvert f \rvert, \operatorname{sgn} f, 0)
f=0f = 0(∣g∣,0,sgn⁡g)(\lvert g \rvert, 0, \operatorname{sgn} g)
g=±1g = \pm 1(1,0,g)(1, 0, g)
f=±1f = \pm 1, g≠0,±1g \ne 0, \pm 1(1,f,0)(1, f, 0)
∣f∣=2d\lvert f \rvert = 2d(d,(d−∣g∣)/f,sgn⁡g)(d, (d - \lvert g \rvert)/f, \operatorname{sgn} g)
∣g∣=2d\lvert g \rvert = 2d(d,sgn⁡f,(d−∣f∣)/g)(d, \operatorname{sgn} f, (d - \lvert f \rvert)/g)

In the last two cases the minimal solution is not unique, since ∣g∣/(2d)|g|/(2d) or ∣f∣/(2d)|f|/(2d) is then an integer or a half-integer that one cofactor attains.

fmpz_xgcd normalises the cofactor of the operand of smaller absolute value instead: if ∣f∣<∣g∣|f| < |g|, then asgn⁡f∈[0,∣g∣)a \operatorname{sgn} f \in [0, |g|) is the cofactor computed by fmpz_gcdinv for ∣f∣|f| and ∣g∣|g|, and b=(d−af)/gb = (d - af)/g; symmetrically if ∣g∣<∣f∣|g| < |f|. For ∣f∣=∣g∣|f| = |g| it returns (∣f∣,sgn⁡f,0)(|f|, \operatorname{sgn} f, 0). These cofactors can be larger than the canonical ones by a factor of up to about 2d2d, and the extra exact division makes the function slower.

fmpz_gcdinv takes 0≤f<g0 \le f < g and returns d=gcd⁡(f,g)d = \gcd(f, g) and a∈[0,g)a \in [0, g) with af≡d(modg)af \equiv d \pmod g, so that a=f−1 mod ga = f^{-1} \bmod g if d=1d = 1. The condition f<gf < g is only checked in builds with assertions; for f=0f = 0 it returns d=gd = g and a=0a = 0.

In all three functions the outputs must be distinct objects; the inputs may alias outputs.

Algorithms#

Two inline operands, or an inline and a large operand, are handled by GMP's single-limb GCD mpn_gcd_1 (a binary GCD, after one division of the large operand by the small one). Two large operands go to flint_mpz_gcd, which uses a Lehmer-type algorithm with double-limb steps for small sizes and the subquadratic half-GCD of Möller for large ones, ported from GMP and built on FLINT's multiplication with transform reuse in the matrix products; the extended GCD functions and fmpz_invmod use flint_mpz_gcdext and flint_mpz_invert, which are built from the same pieces and return the same cofactors as GMP's mpz_gcdext and mpz_invert. fmpz_gcd3 first computes the GCD of the inline operands, if any, and stops as soon as it reaches 1; for three large operands it starts with the two shortest. FLINT's own integer half-GCD, used for continued fractions and rational reconstruction in fmpq, and the partial extended GCD fmpz_xgcd_partial are described with the other algorithms in Integer GCD.

Example#

The cofactors returned by fmpz_xgcd and fmpz_xgcd_canonical_bezout for a few pairs, then a GCD and an LCM of Fibonacci numbers (which satisfy gcd⁡(Fm,Fn)=Fgcd⁡(m,n)\gcd(F_m, F_n) = F_{\gcd(m, n)}) and a modular inverse with fmpz_gcdinv:

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

int main(void)
{
    slong pairs[8][2] = { {240, 46}, {-240, 46}, {12, 18}, {4, 6},
                          {-6, 6}, {0, -5}, {9, -1}, {3, 5} };
    fmpz_t f, g, d, a, b, x;
    int i;

    fmpz_init(f); fmpz_init(g); fmpz_init(d); fmpz_init(a); fmpz_init(b);
    fmpz_init(x);

    flint_printf("   f    g |  xgcd: d   a   b | canonical: d   a   b\n");
    for (i = 0; i < 8; i++)
    {
        fmpz_set_si(f, pairs[i][0]);
        fmpz_set_si(g, pairs[i][1]);
        flint_printf("%4wd %4wd |", pairs[i][0], pairs[i][1]);
        fmpz_xgcd(d, a, b, f, g);
        flint_printf("  %5wd %3wd %3wd |", fmpz_get_si(d), fmpz_get_si(a), fmpz_get_si(b));
        fmpz_xgcd_canonical_bezout(d, a, b, f, g);
        flint_printf("  %5wd %3wd %3wd\n", fmpz_get_si(d), fmpz_get_si(a), fmpz_get_si(b));
    }

    /* gcd, lcm and a modular inverse of large numbers */
    fmpz_fib_ui(f, 300);
    fmpz_fib_ui(g, 200);
    fmpz_gcd(d, f, g);                  /* gcd(F_m, F_n) = F_gcd(m,n) */
    fmpz_lcm(x, f, g);
    flint_printf("gcd(F_300, F_200) = "); fmpz_print(d);
    flint_printf(", lcm has %wu bits\n", fmpz_bits(x));

    fmpz_fib_ui(f, 299);
    fmpz_gcdinv(d, a, g, f);            /* requires 0 <= g < f */
    fmpz_mul(x, a, g);
    fmpz_mod(x, x, f);
    flint_printf("gcd(F_200, F_299) = "); fmpz_print(d);
    flint_printf(", a F_200 mod F_299 = "); fmpz_print(x); flint_printf("\n");

    fmpz_clear(f); fmpz_clear(g); fmpz_clear(d); fmpz_clear(a); fmpz_clear(b);
    fmpz_clear(x);
    return 0;
}
Output
   f    g |  xgcd: d   a   b | canonical: d   a   b
 240   46 |      2  -9  47 |      2  -9  47
-240   46 |      2   9  47 |      2   9  47
  12   18 |      6  17 -11 |      6  -1   1
   4    6 |      2   5  -3 |      2  -1   1
  -6    6 |      6  -1   0 |      6   0   1
   0   -5 |      5   0  -1 |      5   0  -1
   9   -1 |      1   0  -1 |      1   0  -1
   3    5 |      1   2  -1 |      1   2  -1
gcd(F_300, F_200) = 354224848179261915075, lcm has 277 bits
gcd(F_200, F_299) = 1, a F_200 mod F_299 = 1

For (12,18)(12, 18) the function fmpz_xgcd returns the cofactor 17∈[0,18)17 \in [0, 18) of the smaller operand, while the canonical solution is (−1,1)(-1, 1), the special case ∣f∣=2d|f| = 2d. The pair (−6,6)(-6, 6) shows the different conventions for ∣f∣=∣g∣|f| = |g|.

References#

  • [GMP] T. Granlund and the GMP development team. GNU MP: The GNU Multiple Precision Arithmetic Library, version 6.3.0. Manual, 2023. https://gmplib.org/manual/
Cite this page

The FLINT team, “GCD, LCM and Bézout coefficients (fmpz.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz/gcd.html (generated 2026-11-02).