Gaussian elimination and LU decomposition
- Cost
- field operations for an matrix of rank , where is the exponent of the matrix multiplication used; for solving, inversion and determinants of matrices.
Throughout, is a prime and an matrix over the field ; for the last sections is an arbitrary modulus. Gaussian elimination brings to row echelon form by row operations, and recording the operations gives an LU decomposition, from which FLINT computes solutions of linear systems, inverses, determinants, ranks, reduced echelon forms and nullspaces. The recursive variant reduces all of this to matrix multiplication [BH1974; IMH1982; JPS2013], so that the fast methods of Multiplying matrices over Z/nZ apply.
Generic version#
gr_mat_lu computes the decomposition over any field, and over rings pretending to be fields, with the same two algorithms as below: the classical elimination (gr_mat_lu_classical) and the recursive one (gr_mat_lu_recursive), which splits the columns, recurses on the left half, updates the right half with gr_mat_nonsingular_solve_tril and gr_mat_mul, and recurses on the lower right block. The default uses the classical algorithm when the matrix has fewer than 5 rows or columns. Pivots are chosen by a ring method: the first provably nonzero entry by default (GR_UNABLE if none is provably nonzero but some cannot be decided, as for balls containing zero), and the entry of largest magnitude in floating-point rings. Over the generic decomposition is not nmod_mat_lu: it does without the delayed reductions of the classical kernel, but its recursive form uses nmod_mat_mul and therefore runs at the speed of matrix multiplication for large matrices. fmpz_mod, mpn_mod and nfloat override the decomposition. Over integral domains that are not fields, the generic functions use fraction-free elimination instead (Fraction-free elimination); the choice for each operation is tabulated in Gaussian elimination and LU decomposition.
The decomposition#
Definition 1. A PLE decomposition of is a factorisation where is an permutation matrix, is an lower triangular matrix with ones on the diagonal, and is an matrix in row echelon form whose rows are nonzero. The pivot of row of is its first nonzero entry, in column , with .
Then is the rank of , since has full column rank and full row rank. FLINT stores below the diagonal and on and above it, in the array of ; the permutation is returned as an array P with , see Output. Elimination chooses as pivot of column the first row, among the rows not yet used, whose entry in column is nonzero after the previous eliminations.
Proposition 2. With this pivoting rule, column receives a pivot if and only if it is not a linear combination of the columns to its left. The pivot columns are therefore the column rank profile of , the lexicographically smallest set of linearly independent columns.
Proof. After the eliminations for the pivots in columns before , the rows not yet used have zeros in all those columns, and their entries in column are zero exactly when column of lies in the span of the earlier pivot columns, which span all earlier columns.
The row permutation, in contrast, is not the row rank profile in general when the pivot rows are brought into place by swaps, as in nmod_mat_lu. Using upward rotations of rows instead reveals both profiles, and more [JPS2013; DPS2017]; see Rank profile matrix. Here a swap exchanges two rows and leaves the others in place, while an upward rotation moves a row up to a given position and the rows it passes over down by one position each, keeping their order; a downward rotation is the inverse move.
Classical elimination#
Input: .
Output: the rank , the permutation and , stored in .
. For while :
- find the first row with ; if there is none, continue with the next ;
- swap rows and and record the swap;
- for each row : , subtract times row from row in columns (nothing to do if ), and store in column of row ;
- .
For a nonsingular matrix this costs multiply-adds, inversions and, in nmod_mat_lu_classical, one reduction modulo per multiply-add.
Rank profile matrix#
Definition 3. The rank profile matrix of , of rank , is the matrix with entries equal to 1, no two in the same row or column, and zeros elsewhere, such that for all and the submatrices of and formed by their first rows and first columns have the same rank.
It exists and is unique [DPS2017]: writing for the rank of the leading submatrix of , the entry of is . Its rows with a nonzero entry form the row rank profile of , its columns with a nonzero entry the column rank profile, and the same holds for every leading submatrix of with the entries of that lie in it.
Theorem 4. Run Algorithm 1 with step 2 replaced by the upward rotation of rows : move row to position and the rows in positions down by one position. Let P[k] be the index in of the row in position at the end. Then P[r] P[m-1], and the nonzero entries of are at the positions (P[k], ) for .
Proof. An upward rotation keeps the relative order of the rows it passes over, hence preserves the following property: the rows that are not yet pivot rows are in increasing order of their indices in . This gives the first claim, and it shows that the pivot of column is in the row of smallest index, in , among the rows that are not yet pivot rows and have a nonzero entry in column . The rows of smaller index have a zero multiplier, so every row of is only modified by subtracting multiples of rows of smaller index: for every , the operations transform the first rows of by an invertible lower triangular matrix, which does not change the rank of the first columns of these rows. After the steps for the columns before , these columns are zero in the rows that are not pivot rows, and in the first columns the pivot rows form a matrix in row echelon form, with nonzero rows the pivot rows whose pivot column is before . The rank of the leading submatrix of is therefore the number of pairs (P[k], ) with P[k] and , which is the definition of .
nmod_mat_ple uses this rule. By the proof, the pivot of a column is the row of smallest index in with a nonzero entry among the rows that are not pivot rows yet, so that the order of the rows need not be kept in memory: nmod_mat_ple_classical keeps the rows in place and records their order in an array, an upward rotation costing operations on indices, and nmod_mat_ple_classical_delayed swaps the pivot row with the row in position ; both put the rows in their order at the end, and nmod_mat_ple_recursive does so once for each half at each level of the recursion. With swaps, as in nmod_mat_lu, the pivot columns are the same, but a row swapped downwards passes over rows of larger index, and the pivot rows need not be the row rank profile. The output of nmod_mat_ple is unique, since determines the pivot rows and columns, and the other rows are in increasing order: all its algorithms return the same decomposition. Pivoting rules that reveal in other search orders, and the corresponding recursive algorithms, are studied in [DPS2017].
Delayed reduction#
The reductions dominate the cost of step 3 for small dimensions. nmod_mat_lu_classical_delayed performs the same operations but lets the entries of the active submatrix grow: a nonzero multiplier is turned into , and times the pivot row is added without reduction, in one, two or three words. An entry is reduced only when it is about to be used: when its column becomes the pivot column, before the pivot is chosen, and when its row becomes the pivot row.
Proposition 5. Let . In Algorithm 1 with delayed reduction, every stored entry is congruent to the true entry modulo and is at most .
Proof. Adding times the pivot row, with , is congruent to subtracting times it, so the congruence is preserved. An entry is updated once for each pivot that is found while it is still active, in a row above and a column to the left of ; there are at most such pivots. Each update adds with and , a reduced entry of the pivot row, to an initial value at most .
FLINT chooses the number of words from the bound of How many words (_nmod_vec_dot_bound_limbs), which bounds every entry by Proposition 5. The reduction of a word uses the Lemire–Kaser–Kurz method when the bound is below and Barrett's otherwise (Barrett and Lemire reduction).
nmod_mat_ple_classical_delayed applies the same reductions to the elimination of Theorem 4, swapping the rows of the matrix and of the buffer as nmod_mat_lu_classical_delayed does; the pivot of a column is found while the column is reduced, as the row of smallest index in with a nonzero entry (see Rank profile matrix).
For moduli of several limbs, mpn_mod_mat_lu_classical_delayed applies the same idea with unreduced entries of limbs (delayed reduction for multiword moduli).
Crout elimination#
Algorithm 1 updates the whole active submatrix after each pivot. The Crout schedule performs the same operations in another order, computing each entry of and only when it is needed [DPS2017]. When column is processed, with pivots in the columns before it, the entry of a row without pivot is : one dot product of the multipliers of row with column of . When row becomes the pivot row , its entries to the right of column are : one vector-matrix product of its multipliers with the rows of . The other entries are not touched before their column is processed.
nmod_mat_ple_crout uses this schedule with the pivoting of Theorem 4, swapping rows as nmod_mat_ple_classical_delayed does. Its dot products and vector-matrix products delay their reductions, with SIMD code (Dot products modulo a word-size integer, Thin matrices), so that no buffer of unreduced entries is needed, whereas the delayed algorithm needs two or three words per entry with scalar updates when . On the other hand, the products only skip the zero multipliers before the first and after the last nonzero one of each row, while the classical and delayed algorithms skip every row whose multiplier is zero, which on some structured matrices saves most of the work.
Recursive decomposition#
Input: , .
Output: a PLE decomposition of in place, and its rank.
- If or , use Algorithm 1.
- Let and decompose the left block recursively: of rank .
- Apply to the rows of the right block. Write the first rows of the result as and the others as , and the first rows of as and the others as .
- (triangular solve with unit diagonal), and (matrix multiplication).
- Decompose recursively, of rank , apply its permutation to the rows of , and move its factor to columns .
- Return .
nmod_mat_lu_recursive calls nmod_mat_lu for the two halves, which switches to the classical or delayed algorithm below a crossover depending on the size of (see Algorithms).
The recursion performs the operations of Algorithm 1, with the same pivots, in another order: the pivots of the first columns depend only on these columns, step 4 applies the eliminations of the left half to the right half, and the row moves of step 5 act on the rows that are not pivot rows of the left half. nmod_mat_ple_recursive uses the upward rotations of Theorem 4 in both halves, so that it computes the decomposition of that theorem, the same as nmod_mat_ple_classical.
Theorem 6. If two matrices of dimensions and can be multiplied with operations for , with , then Algorithm 2 costs operations.
Proof. At depth of the recursion there are at most subproblems, each with at most rows and columns, with ranks summing to at most . Step 4 is skipped when the left half has rank 0; otherwise the triangular solve and the product cost . Let be the number of nonzero . Since is concave, . For the level therefore costs , and for , using , it costs . Both are geometric series in , with sums and . The row permutations of step 3 and 5 cost per level, and there are levels.
With classical multiplication () this is , the cost of Algorithm 1; with Strassen–Winograd it is . In practice the gain comes as much from the speed of the multiplication kernels as from the exponent.
Triangular systems#
nmod_mat_solve_tril and nmod_mat_solve_triu solve for a triangular and a matrix . For they use substitution, one dot product per entry of , operations. Otherwise they split into blocks of and rows and use
and its upper triangular analogue, which costs for . nmod_mat_solve_tril_right and nmod_mat_solve_triu_right solve for with columns in the same way: by substitution along the rows of , with the triangle of transposed for the dot products, or by the transposed block formulas.
Applications#
- Solving for nonsingular : a PLE decomposition with early exit on rank deficiency, a permutation of , and two triangular solves. For matrices and , .
- Inversion: solving , .
- Determinant: , the sign being that of the permutation; .
- Rank: the number of pivots.
- General systems : with the pivot columns , the solution with zero free variables is found by a triangular solve with , a consistency check of the rows beyond the rank (one matrix product), and a triangular solve with the matrix of pivot columns of .
- Reduced row echelon form: with up to a permutation of the columns, where is the upper triangular matrix of pivot columns, the reduced form is with the columns put back in place; one triangular solve.
- Nullspace: from the reduced form , one basis vector per free column , with a 1 in position and in the position of the pivot of row . These entries are those of , so the basis is computed from a PLE decomposition with one triangular solve, without forming .
- Left nullspace: from a PLE decomposition, the rows of with their columns put in the order of the rows of , where and are the first and the other rows of ; one triangular solve with on the right. With the decomposition of Theorem 4, the identity matrix is at the rows of outside its row rank profile, and the basis is the transpose of the basis of the nullspace of above.
Division-free determinants#
For an arbitrary modulus , elimination can meet nonzero pivots that are zero divisors. nmod_mat_det avoids this: it uses cofactor expansion for dimensions up to 4, the division-free algorithm of Berkowitz (Berkowitz's algorithm) up to 8, and above it PLE decomposition if is prime and the following triangularisation by Euclidean row operations otherwise.
Lemma 7. For , not both zero, let . There are integers with and .
Proof. Take any with . Then and satisfy for every integer , and since . By the Chinese remainder theorem there is a with modulo every prime factor of : for one value of modulo is excluded, and for none is, since then .
To clear an entry below a pivot in the same column, nmod_mat_det_howell subtracts a multiple of the pivot row if is a multiple of modulo . Otherwise it replaces the pivot row by times itself minus times row , with from Lemma 7 (found by increasing until ). The new pivot divides , so the entry can then be cleared. The second operation multiplies the determinant by the unit , and the product of these units is divided out at the end. The cost is operations and extended gcd computations.
Howell form#
Over for composite , the row echelon form of a matrix is not unique, and its rows need not generate all elements of the row span with leading zeros. The Howell form repairs both [How1986; StoMul1998].
Definition 8. A matrix over is in Howell form if it is in row echelon form with its zero rows last, every pivot is a divisor of , every entry above a pivot is reduced modulo that pivot, and, for every nonzero row , every element of the row span of whose entries vanish up to and including the pivot column of row is a combination of the rows below row .
Every matrix is row equivalent to a unique matrix in Howell form, so two matrices span the same submodule of if and only if their Howell forms are equal [How1986]. FLINT computes the strong echelon form of Fieker and Hofmann [FieHof2014], which is the Howell form with zero rows inserted so that each pivot lies on the diagonal, and nmod_mat_howell_form then moves the zero rows to the bottom. The algorithm:
- Triangularise with Euclidean row operations, as for the determinant but with a unimodular transformation of the pivot row and the other row, so that the row span is preserved.
- For each diagonal entry from top to bottom: multiply its row by a unit such that divides , and reduce the entries above it modulo it. If is a zero divisor, the row multiplied by is a new element of the span with a zero in this column; it is reduced into the rows below with the same Euclidean operations, which is what establishes the Howell property. If the diagonal entry is zero, the row itself is reduced in this way.
The matrix must have at least as many rows as columns, so that each column has a row to hold its pivot. The cost is operations plus extended gcd computations for an matrix. Fast algorithms based on matrix multiplication exist [StoMul1998; Sto2000] but are not implemented.
Referenced from#
- Arithmetic in finite fields (overview)
- Dot products modulo a word-size integer (algorithm)
- Hermite and Smith normal forms (algorithm)
- Linear algebra over generic rings and its specialisations (overview)
fmpz_mat_howell_form_mod- fmpz_mod_mat.h (module)
- fq_default_mat.h (module)
- fq_mat.h (module)
- fq_nmod_mat.h (module)
- fq_zech_mat.h (module)
- LU decompositions and linear systems
- Computing determinants, ranks and inverses
- nmod_mat.h (module)
- Computing an LU decomposition
- Computing a PLE decomposition revealing the rank profile matrix
- Computing echelon forms and nullspaces
- Solving systems of linear equations
References#
- [BH1974] J. R. Bunch and J. E. Hopcroft, "Triangular factorization and inversion by fast matrix multiplication", Mathematics of Computation 28 (1974), 231-236, https://doi.org/10.1090/S0025-5718-1974-0331751-8
- [IMH1982] O. H. Ibarra, S. Moran and R. Hui, "A generalization of the fast LUP matrix decomposition algorithm and applications", Journal of Algorithms 3 (1982), 45-56
- [JPS2013] C.-P. Jeannerod, C. Pernet and A. Storjohann, "Rank-profile revealing Gaussian elimination and the CUP matrix decomposition", Journal of Symbolic Computation 56 (2013), 46-68, https://doi.org/10.1016/j.jsc.2013.04.004
- [DPS2017] J.-G. Dumas, C. Pernet and Z. Sultan, "Fast computation of the rank profile matrix and the generalized Bruhat decomposition", Journal of Symbolic Computation 83 (2017), 187-210
- [How1986] J. A. Howell, "Spans in the module ", Linear and Multilinear Algebra 19 (1986), 67-77
- [StoMul1998] Storjohann, Arne and Mulders, Thom : Fast algorithms for linear algebra modulo :math: : Algorithms—{ESA} '98 (Venice), Lecture Notes in Comput. Sci. 1461 139–150
- [FieHof2014] Fieker C. and Hofmann T.: "Computing in quotients of rings of integers" LMS Journal of Computation and Mathematics, 17(A), 349-365
- [Sto2000] A. Storjohann, Algorithms for Matrix Canonical Forms, PhD thesis, ETH Zürich (2000), https://doi.org/10.3929/ethz-a-004141007
The FLINT team, “Gaussian elimination and LU decomposition,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/linear-algebra/gaussian-elimination.html (generated 2026-11-02).
@misc{flint-doc-algorithms-linear-algebra-gaussian-elimination,
author = {{The FLINT team}},
title = {{Gaussian elimination and LU decomposition}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/linear-algebra/gaussian-elimination.html},
note = {Generated 2026-11-02}
}