FLINT3.7.0-dev

Fraction-free elimination and echelon forms

Synopsis#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)source

Computes a fraction-free LU decomposition of AA by Bareiss elimination, stored in BB, and returns the rank rr of AA. den is set to the last pivot, a nonzero r×rr \times r minor of AA (1 if r=0r = 0). Row exchanges are applied to perm if it is not NULL. BB may be AA.

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 BB and Fraction-free elimination.

slong fmpz_mat_rref(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A)source
slong fmpz_mat_rref_fflu(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A)source
slong fmpz_mat_rref_mul(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A)source

Sets (BB, den) to the reduced row echelon form of AA, so that B/denB/\mathit{den} is in reduced row echelon form, and returns the rank of AA. The pivot entries of BB equal den. BB may be AA.

fmpz_mat_rref_fflu uses fraction-free elimination followed by fraction-free back substitution, and den is a nonzero r×rr \times r minor of AA. 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 AA has full column rank. fmpz_mat_rref chooses between them from the dimensions. See Fraction-free elimination and echelon forms.

Gaussian elimination over Q\mathbb{Q} 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.

AlgorithmFraction-free eliminationBareiss' fraction-free Gaussian elimination over integral domains, Sylvester's identity, the fraction-free LU decomposition and how FLINT uses it for determinants, ranks, linear systems and echelon forms over Z\mathbb{Z}, Z[x]\mathbb{Z}[x] and (Z/pZ)[x](\mathbb{Z}/p\mathbb{Z})[x].

Fraction-free LU decomposition#

fmpz_mat_fflu(B, den, perm, A, rank_check) performs Bareiss' algorithm [Bar1968] on the m×nm \times n matrix AA and returns its rank rr. 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 kk-th pivot pkp_k has been chosen, every entry of the remaining submatrix is updated as

bij←pkbij−bickbkjpk−1,b_{ij} \gets \frac{p_k b_{ij} - b_{i c_k} b_{k j}}{p_{k-1}},

with p−1=1p_{-1} = 1, where ckc_k is the pivot column; the division is exact. After the elimination:

  • the first rr rows of BB, from their pivot columns on, form the fraction-free echelon form: the pivot in row kk is pkp_k, the determinant of the leading (k+1)×(k+1)(k+1) \times (k+1) submatrix of the row-permuted AA restricted to the first k+1k + 1 pivot columns;
  • below each pivot, BB 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;
  • den is the last pivot pr−1p_{r-1}, or 1 if r=0r = 0.

For a nonsingular square AA, den is det⁡(PA)=±det⁡(A)\det(PA) = \pm \det(A), where PP 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. BB may be AA.

The entries of BB are minors of AA, so they have at most about n(b+12log⁡2n)n(b + \frac12 \log_2 n) bits for bb-bit entries, and the cost is O(mnr)O(mnr) 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 (BB, den) to the reduced row echelon form of AA: B/denB/\mathit{den} is in reduced row echelon form, so every pivot entry of BB 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 r×rr \times r minor of AA 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 m×nm \times n matrix, fmpz_mat_rref calls fmpz_mat_rref_fflu if m≤3m \le 3, if n≤2n \le 2, if m≤20m \le 20 and n>mn > m, or if 20<m≤10020 < m \le 100 and n>m+m−2080mn > m + \frac{m - 20}{80} m; 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 mm 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 rr rows, up to a permutation of the columns, as (U∣V)(U \mid V) with UU upper triangular, the reduced form is (I∣U−1V)(I \mid U^{-1} V), and den⋅U−1V\mathit{den} \cdot U^{-1} V is integral since den=det⁡U\mathit{den} = \det U 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 VV.

Multimodular echelon form#

fmpz_mat_rref_mul follows [Stein2007]:

  1. Reduce AA modulo a prime pp of 17 bits and compute its rank rr, pivot rows and pivot columns modulo pp with nmod_mat_lu_with_pivots. If r=nr = n, the reduced form is the identity matrix on top of zero rows, and den=1\mathit{den} = 1.
  2. Let B0B_0 be the r×rr \times r submatrix of AA formed by the pivot rows and columns, which is nonsingular modulo pp and hence over Q\mathbb{Q}, and CC the pivot rows restricted to the other columns. Solve B0E2=den⋅CB_0 E_2 = \mathit{den} \cdot C with fmpz_mat_solve; the candidate is den\mathit{den} on the pivot positions and E2E_2 in the other columns.
  3. Certify: check that the candidate is in reduced row echelon form, and that every non-pivot row of AA is annihilated by the nullspace basis defined by the candidate (one matrix product). Both checks are exact, so if they pass, the rows of AA lie in the span of the pivot rows, the rank is rr and the candidate is the reduced row echelon form (fmpz_mat_rref_upper_certify_lu_mod_p).
  4. If a check fails, the rank modulo pp was below the rank of AA; try the next prime.

The work is one solve with n−rn - r 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 4×44 \times 4 matrix, whose pivots are the leading principal minors 2,5,18,822, 5, 18, 82, and the reduced row echelon form of a 3×53 \times 5 matrix of rank 2 computed in two ways:

Examplefmpz_mat_fflu_rref.cchecked by make checkdoc
#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;
}
Output
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
Cite this page

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).