Fraction-free elimination and echelon forms
#include <flint/fmpz_mat.h>slong fmpz_mat_fflu(fmpz_mat_t B, fmpz_t den, slong * perm, const fmpz_mat_t A, int rank_check)sourceComputes a fraction-free LU decomposition of by Bareiss elimination, stored in , and returns the rank of . den is set to the last pivot, a nonzero minor of (1 if ). Row exchanges are applied to perm if it is not NULL. may be .
If rank_check is nonzero, the function stops as soon as a column without pivot is found, and then returns 0 with den set to 0. See Fraction-free elimination and echelon forms for the layout of and Fraction-free elimination.
slong fmpz_mat_rref(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A)sourceslong fmpz_mat_rref_fflu(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A)sourceslong fmpz_mat_rref_mul(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A)sourceSets (, den) to the reduced row echelon form of , so that is in reduced row echelon form, and returns the rank of . The pivot entries of equal den. may be .
fmpz_mat_rref_fflu uses fraction-free elimination followed by fraction-free back substitution, and den is a nonzero minor of . fmpz_mat_rref_mul computes the echelon structure modulo a prime, solves for the echelon form with the nonsingular pivot block and certifies the result exactly; it returns den = 1 if has full column rank. fmpz_mat_rref chooses between them from the dimensions. See Fraction-free elimination and echelon forms.
Gaussian elimination over applied to an integer matrix creates fractions whose numerators and denominators grow quickly. Fraction-free elimination avoids them: it multiplies rows by pivots instead of dividing by them, and divides out the previous pivot exactly, so that every intermediate entry is a minor of the input. fmpz_mat_fflu computes such a decomposition, from which determinants, ranks and solutions follow; fmpz_mat_rref computes the reduced row echelon form, either by fraction-free elimination or by a multimodular method with an exact certificate.
Fraction-free LU decomposition#
fmpz_mat_fflu(B, den, perm, A, rank_check) performs Bareiss' algorithm [Bar1968] on the matrix and returns its rank . Pivots are chosen with fmpz_mat_find_pivot_any: in each column, the first row at or below the current pivot row with a nonzero entry; rows are swapped to bring it into place, and the swaps are applied to perm if it is not NULL. When the -th pivot has been chosen, every entry of the remaining submatrix is updated as
with , where is the pivot column; the division is exact. After the elimination:
- the first rows of , from their pivot columns on, form the fraction-free echelon form: the pivot in row is , the determinant of the leading submatrix of the row-permuted restricted to the first pivot columns;
- below each pivot, keeps the entries of the pivot column as they were when the pivot was chosen (the multipliers of the fraction-free LU decomposition [NakTurWil1997]); the other entries of the rows below the rank are zero;
denis the last pivot , or 1 if .
For a nonsingular square , den is , where is the row permutation. With rank_check set, the function stops at the first column without pivot and returns 0 with den = 0, which is what the determinant and solving functions need. may be .
The entries of are minors of , so they have at most about bits for -bit entries, and the cost is multiplications and exact divisions of such integers. For small entries (at most 62 bits on a 64-bit machine) the updates use two-word arithmetic and division by a precomputed inverse of the previous pivot until an entry outgrows a word.
Reduced row echelon form#
fmpz_mat_rref(B, den, A) sets (, den) to the reduced row echelon form of : is in reduced row echelon form, so every pivot entry of equals den, the other entries of the pivot columns are zero, and the rows below the rank are zero. It returns the rank. The denominator is not normalised: it is a nonzero minor of for fmpz_mat_rref_fflu, and 1 or a divisor of such a minor for fmpz_mat_rref_mul, so the two can return different but equivalent results. Divide by the gcd of den and the entries for a canonical form, or use fmpq_mat_rref.
For an matrix, fmpz_mat_rref calls fmpz_mat_rref_fflu if , if , if and , or if and ; otherwise it calls fmpz_mat_rref_mul. Wide matrices thus go to fraction-free elimination, whose cost is dominated by the elimination of the first columns, and tall or square ones to the multimodular method.
Fraction-free back substitution#
fmpz_mat_rref_fflu computes the fraction-free echelon form with fmpz_mat_fflu. Writing its first rows, up to a permutation of the columns, as with upper triangular, the reduced form is , and is integral since up to sign. Its columns are computed by back substitution with exact divisions by the pivots, scaled to the common denominator den; only the non-pivot columns need to be updated. This is the fraction-free Gauss–Jordan elimination of [NakTurWil1997] restricted to the part .
Multimodular echelon form#
fmpz_mat_rref_mul follows [Stein2007]:
- Reduce modulo a prime of 17 bits and compute its rank , pivot rows and pivot columns modulo with
nmod_mat_lu_with_pivots. If , the reduced form is the identity matrix on top of zero rows, and . - Let be the submatrix of formed by the pivot rows and columns, which is nonsingular modulo and hence over , and the pivot rows restricted to the other columns. Solve with
fmpz_mat_solve; the candidate is on the pivot positions and in the other columns. - Certify: check that the candidate is in reduced row echelon form, and that every non-pivot row of is annihilated by the nullspace basis defined by the candidate (one matrix product). Both checks are exact, so if they pass, the rows of lie in the span of the pivot rows, the rank is and the candidate is the reduced row echelon form (
fmpz_mat_rref_upper_certify_lu_mod_p). - If a check fails, the rank modulo was below the rank of ; try the next prime.
The work is one solve with right-hand sides, done by the output-sensitive modular solvers, and one product, instead of an elimination with growing entries.
Example#
A fraction-free LU decomposition of a matrix, whose pivots are the leading principal minors , and the reduced row echelon form of a matrix of rank 2 computed in two ways:
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpz_mat.h>
int main(void)
{
fmpz_mat_t A, B;
fmpz_t den;
slong i, j, rank, perm[4] = { 0, 1, 2, 3 };
fmpz_init(den);
fmpz_mat_init(A, 4, 4);
fmpz_mat_init(B, 4, 4);
/* tridiagonal with i + 2 on the diagonal, plus A[0][3] = 3 */
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
fmpz_set_si(fmpz_mat_entry(A, i, j),
(i == j) ? i + 2 : (j == i + 1 || i == j + 1));
fmpz_set_si(fmpz_mat_entry(A, 0, 3), 3);
rank = fmpz_mat_fflu(B, den, perm, A, 0);
flint_printf("rank %wd, den %{fmpz}\n", rank, den);
fmpz_mat_print_pretty(B);
flint_printf("\n");
fmpz_mat_clear(A);
fmpz_mat_clear(B);
/* row 2 = row 0 + 2 row 1 */
fmpz_mat_init(A, 3, 5);
fmpz_mat_init(B, 3, 5);
for (j = 0; j < 5; j++)
{
fmpz_set_si(fmpz_mat_entry(A, 0, j), 2 * j + 2);
fmpz_set_si(fmpz_mat_entry(A, 1, j), j * j - 3);
fmpz_set_si(fmpz_mat_entry(A, 2, j), 2 * j + 2 + 2 * (j * j - 3));
}
rank = fmpz_mat_rref_fflu(B, den, A);
flint_printf("rref_fflu: rank %wd, den %{fmpz}\n", rank, den);
fmpz_mat_print_pretty(B);
flint_printf("\n");
rank = fmpz_mat_rref_mul(B, den, A);
flint_printf("rref_mul: rank %wd, den %{fmpz}\n", rank, den);
fmpz_mat_print_pretty(B);
flint_printf("\n");
fmpz_mat_clear(A);
fmpz_mat_clear(B);
fmpz_clear(den);
return 0;
}rank 4, den 82 [[2 1 0 3] [1 5 2 -3] [0 2 18 8] [0 0 5 82] ] rref_fflu: rank 2, den 8 [[8 0 -16 -40 -72] [0 8 20 36 56] [0 0 0 0 0] ] rref_mul: rank 2, den 8 [[8 0 -16 -40 -72] [0 8 20 36 56] [0 0 0 0 0] ]
Both echelon forms have the denominator 8, while the reduced fraction form has denominator 2 since all entries are divisible by 4. In the decomposition, the entries 1, 2 and 5 below the diagonal are the multipliers.
Guides#
References#
- [Bar1968] E. H. Bareiss, "Sylvester's identity and multistep integer-preserving Gaussian elimination", Mathematics of Computation 22 (1968), 565–578. https://doi.org/10.1090/S0025-5718-1968-0226829-0
- [NakTurWil1997] Nakos, George and Turner, Peter and Williams, Robert : Fraction-free algorithms for linear and polynomial equations, ACM SIGSAM Bull. 31 (1997) 3 11–19
- [Stein2007] Stein, William A.: Modular forms, a computational approach. American Mathematical Society. 2007
The FLINT team, “Fraction-free elimination and echelon forms (fmpz_mat.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz_mat/rref.html (generated 2026-11-02).
@misc{flint-doc-fmpz-mat-rref,
author = {{The FLINT team}},
title = {{Fraction-free elimination and echelon forms (fmpz\_mat.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/fmpz_mat/rref.html},
note = {Generated 2026-11-02}
}