Rational reconstruction
#include <flint/fmpq.h>If the denominator of is invertible modulo = mod, set res to the residue with and return 1; otherwise return 0 and leave an unspecified value in res. Requires .
int fmpq_reconstruct_fmpz_2(fmpq_t res, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D)sourceint _fmpq_reconstruct_fmpz_2(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D)sourceint _fmpq_reconstruct_fmpz_2_naive(fmpz_t n, fmpz_t d, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D)sourceGiven , and with , find the fraction with , , and , which is unique if it exists. Return 1 and set the result if it exists, otherwise return 0.
A multimodular or -adic algorithm whose answer is a rational number computes it as a residue modulo a large integer , a product of primes or a prime power. Rational reconstruction recovers the fraction from , provided that and are small compared with . fmpq_mod_fmpz computes the residue of a fraction, and the reconstruction functions invert it:
fmpq_reconstruct_fmpz_2takes explicit bounds and with and finds the unique with and , if it exists;fmpq_reconstruct_fmpzuses the balanced bounds .
The residue must be reduced, , and . The result is canonical: and .
AlgorithmRational reconstructionRecovers a fraction with and from its residue modulo by stopping the extended Euclidean algorithm at the first remainder below . Used to return rational results from multimodular and p-adic algorithms.Success and failure#
The bound makes the answer unique: two fractions within the bounds have different residues, because would otherwise divide , a nonzero number of absolute value at most . A return value of 0 therefore proves that no fraction within the bounds has residue .
A return value of 1 proves only that the fraction found is the unique one within the bounds. If the true answer of a computation is larger than the bounds, the function either fails or returns a different, small fraction with the same residue. About of all residues have a reconstruction with the balanced bounds, so a successful reconstruction of a residue that is not known to come from a small fraction is weak evidence. Multimodular algorithms therefore either use a priori bounds on the answer (Hadamard's bound for determinants and solutions of linear systems, for example) and choose larger than , or verify the reconstructed result, or add primes until the reconstruction stabilises.
When the shape of the answer is known, unbalanced bounds help. For a fraction whose denominator divides a known , take and : almost all of is then available for the numerator.
Algorithm#
The fraction is found among the remainders and cofactors of the extended Euclidean algorithm applied to and , stopping at the first remainder ; then where is the cofactor of , and the reconstruction succeeds if and (Wang's algorithm [WGD1982]). The implementation works in one or two words or on fixed arrays of up to 12 limbs for small , with Lehmer's method for larger , and with the half-GCD algorithm when the modulus has at least FMPQ_RECONSTRUCT_HGCD_CUTOFF (500) more limbs than , for a total cost of . Since the search stops at a remainder of the size of , its cost depends on the size of relative to , not only on the size of . _fmpq_reconstruct_fmpz_2_naive is the plain Euclidean algorithm on fmpz, used for testing.
Example#
The modulus is the prime , for which the balanced bound is . The fraction is recovered. The fraction has a numerator above the balanced bound; the balanced reconstruction fails, and unbalanced bounds , (with ) recover it. The residue of is reconstructed with the balanced bounds, but to a different fraction of small height, which shows that a successful reconstruction has to be checked when the answer is not known to be within the bounds.
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpq.h>
static void
show(const fmpq_t x, const fmpz_t m, const fmpz_t N, const fmpz_t D)
{
fmpz_t a;
fmpq_t y;
int ok;
fmpz_init(a);
fmpq_init(y);
fmpq_mod_fmpz(a, x, m);
if (N == NULL)
ok = fmpq_reconstruct_fmpz(y, a, m);
else
ok = fmpq_reconstruct_fmpz_2(y, a, m, N, D);
fmpq_print(x);
flint_printf(" -> ");
fmpz_print(a);
if (ok)
{
flint_printf(" -> ");
fmpq_print(y);
flint_printf("\n");
}
else
flint_printf(" -> no fraction within the bounds\n");
fmpz_clear(a);
fmpq_clear(y);
}
int main(void)
{
fmpz_t m, N, D;
fmpq_t x;
fmpz_init_set_ui(m, 1000000007);
fmpz_init_set_ui(N, 400000);
fmpz_init_set_ui(D, 1000);
fmpq_init(x);
fmpq_set_si(x, -355, 113);
show(x, m, NULL, NULL);
fmpq_set_si(x, 123456, 789);
show(x, m, NULL, NULL);
show(x, m, N, D);
fmpq_set_si(x, 1234567, 89);
show(x, m, NULL, NULL);
fmpz_clear(m);
fmpz_clear(N);
fmpz_clear(D);
fmpq_clear(x);
return 0;
}-355/113 -> 699115046 -> -355/113 41152/263 -> 726235903 -> no fraction within the bounds 41152/263 -> 726235903 -> 41152/263 1234567/89 -> 955070058 -> -14062/18629
Guides#
- Exact linear algebra over the integers (
fmpz_mat)
References#
- [WGD1982] P. S. Wang, M. J. T. Guy and J. H. Davenport, "P-adic reconstruction of rational numbers", ACM SIGSAM Bulletin 16:2 (1982), 2–3. https://doi.org/10.1145/1089292.1089293
The FLINT team, “Rational reconstruction (fmpq.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpq/reconstruct.html (generated 2026-11-02).
@misc{flint-doc-fmpq-reconstruct,
author = {{The FLINT team}},
title = {{Rational reconstruction (fmpq.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/fmpq/reconstruct.html},
note = {Generated 2026-11-02}
}