GCD, LCM and Bézout coefficients
#include <flint/fmpz.h>Set to , with .
Sets to . Faster than two calls to fmpz_gcd when one operand is small or the GCD of the two shortest operands is 1.
Sets to the least common multiple of and , which is nonnegative, and 0 if or is 0.
Sets and cofactors , with . The outputs must be distinct objects.
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.
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 with , 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.
Values and signs#
The GCD is always nonnegative, with and ; 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 , is a solution for every .
fmpz_xgcd_canonical_bezout returns the solution with the smallest cofactors, which is unique up to the cases below. Writing , the result satisfies
except in the following cases, where the result is fixed as listed (this is also the normalisation of GMP's mpz_gcdext [GMP]):
| Case | |
|---|---|
| , | |
In the last two cases the minimal solution is not unique, since or 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 , then is the cofactor computed by fmpz_gcdinv for and , and ; symmetrically if . For it returns . These cofactors can be larger than the canonical ones by a factor of up to about , and the extra exact division makes the function slower.
fmpz_gcdinv takes and returns and with , so that if . The condition is only checked in builds with assertions; for it returns and .
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 ) and a modular inverse with fmpz_gcdinv:
#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;
}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 the function fmpz_xgcd returns the cofactor of the smaller operand, while the canonical solution is , the special case . The pair shows the different conventions for .
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/
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).
@misc{flint-doc-fmpz-gcd,
author = {{The FLINT team}},
title = {{GCD, LCM and Bézout coefficients (fmpz.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/fmpz/gcd.html},
note = {Generated 2026-11-02}
}