Hermite normal form
#include <flint/fmpz_mat.h>void fmpz_mat_hnf(fmpz_mat_t H, const fmpz_mat_t A)sourcevoid fmpz_mat_hnf_classical(fmpz_mat_t H, const fmpz_mat_t A)sourcevoid fmpz_mat_hnf_xgcd(fmpz_mat_t H, const fmpz_mat_t A)sourcevoid fmpz_mat_hnf_minors(fmpz_mat_t H, const fmpz_mat_t A)sourcevoid fmpz_mat_hnf_pernet_stein(fmpz_mat_t H, const fmpz_mat_t A, flint_rand_t state)sourceSets , of the same dimensions as , to the Hermite normal form of . may be . fmpz_mat_hnf chooses the algorithm; the others force the classical algorithm, elimination with extended gcds, the algorithm of Kannan and Bachem, respectively that of Pernet and Stein.
fmpz_mat_hnf_minors requires to have full column rank; the others accept any matrix. fmpz_mat_hnf_pernet_stein uses randomness from state, but its result does not depend on it since the Hermite normal form is unique.
void fmpz_mat_hnf_modular(fmpz_mat_t H, const fmpz_mat_t A, const fmpz_t D)sourcevoid fmpz_mat_hnf_modular_eldiv(fmpz_mat_t A, const fmpz_t D)sourceComputes the Hermite normal form of an matrix with and full column rank by computing modulo . fmpz_mat_hnf_modular requires to be a positive multiple of the determinant of the lattice spanned by the rows of ; fmpz_mat_hnf_modular_eldiv works in place and only requires to be a positive multiple of the largest elementary divisor of . Neither condition is checked.
fmpz_mat_hnf_modular is the algorithm of Domich, Kannan and Trotter [DomKanTro1987]; fmpz_mat_hnf_modular_eldiv computes the strong echelon form modulo (with nmod_mat_strong_echelon_form when fits in a word) and replaces zero diagonal entries by . See Computing modulo a determinant.
void fmpz_mat_hnf_transform(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A)sourcevoid fmpz_mat_hnf_minors_transform(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A)sourceSets to the Hermite normal form of the matrix and to an unimodular matrix with . fmpz_mat_hnf_minors_transform requires full column rank.
fmpz_mat_hnf_transform uses fmpz_mat_hnf_minors_transform if and has full column rank modulo a random 59-bit prime, and otherwise computes the Hermite normal form of , whose right block is then . The transformation matrix is not unique when does not have full row rank.
The Hermite normal form is the canonical basis of a lattice in given by generators, and the integer analogue of the reduced row echelon form. Two integer matrices have the same Hermite normal form exactly when their rows generate the same lattice. FLINT computes it by several algorithms, from classical elimination with gcds to a randomised algorithm of Pernet and Stein that reduces most of the work to linear system solving; fmpz_mat_hnf chooses among them.
Definition#
An integer matrix is in (row-style) Hermite normal form if
- it is in row echelon form, with its nonzero rows first: the first nonzero entry (pivot) of row is in column , with ;
- the pivots are positive;
- the entries above each pivot are reduced: for .
For every integer matrix there is a unique in Hermite normal form with for some unimodular (). Its nonzero rows are a basis of the lattice spanned by the rows of , the product of its pivots is the determinant (covolume) of that lattice when has full column rank, and the pivot columns are the column rank profile of . fmpz_mat_is_in_hnf checks the definition.
Column-style Hermite normal forms, with the columns spanning the lattice, are obtained by transposing: the column form of is the transpose of fmpz_mat_hnf of .
Usage#
- must have the dimensions of and may be .
fmpz_mat_hnf_minorsand the modular functions require to have full column rank (in particular ), which is not checked; the other functions accept any matrix.fmpz_mat_hnf_modular(H, A, D)requires to be a positive multiple of the determinant of the lattice, for example the absolute value of a nonzero minor of when has full column rank, or for a nonsingular square .fmpz_mat_hnf_modular_eldiv(A, D)transforms in place and requires to be a positive multiple of the largest elementary divisor of .fmpz_mat_hnf_transform(H, U, A)also sets the unimodular with ; is not unique when the rank is less than .
Choice of algorithm#
fmpz_mat_hnf uses fmpz_mat_hnf_classical when the number of rows is below a cutoff that decreases with the bit size of the largest entry:
| larger | ||||||||
|---|---|---|---|---|---|---|---|---|
| cutoff | 52 | 38 | 30 | 11 | 5 | 4 | 3 | 2 |
Otherwise it calls fmpz_mat_hnf_pernet_stein. That function in turn uses fmpz_mat_hnf_minors for matrices of full column rank with fewer than about 35 to 52 columns (depending on ), and falls back to fmpz_mat_hnf_minors or fmpz_mat_hnf_classical when the rank is too small for its decomposition.
Algorithms#
fmpz_mat_hnf_classicaleliminates column by column with the entry of smallest absolute value as pivot, by integer division with remainder, until the pivot divides the other entries of its column [Coh1996, Algorithm 2.4.4]. Entries can grow exponentially in the worst case.fmpz_mat_hnf_xgcdcombines pairs of rows with the cofactors of an extended gcd, which clears an entry in one step [Coh1996, Algorithm 2.4.5].fmpz_mat_hnf_minorsis the algorithm of Kannan and Bachem [KanBac1979]: it brings the leading principal submatrix into Hermite normal form for , reducing the entries above the diagonal at each step, which keeps all entries polynomially bounded. It requires full column rank.fmpz_mat_hnf_modularis the algorithm of Domich, Kannan and Trotter [DomKanTro1987; Coh1996, Algorithm 2.4.8]: since is contained in the lattice, all computations can be done modulo , which bounds the entries by .fmpz_mat_hnf_modular_eldivcomputes the strong echelon form of modulo and puts on zero diagonal entries; the lattice contains when is a multiple of the largest elementary divisor [FieHof2014].fmpz_mat_hnf_pernet_steinimplements [PernetStein2010]. It chooses rows forming, together with one of two further rows, a nonsingular submatrix modulo a random prime, computes the two determinants obtained with each of the two further rows by solving one linear system over , and combines the two rows with the cofactors of the gcd of these determinants. The Hermite normal form of the resulting block is computed modulo , which is small for random matrices; then the remaining columns are added by solving a linear system, and the remaining rows are added one at a time by an incremental update. A random prime giving wrong pivots is detected and the computation restarted.
See Hermite and Smith normal forms for the mathematics and the complexities.
Transformation matrix#
fmpz_mat_hnf_transform uses fmpz_mat_hnf_minors_transform when and has full column rank modulo a random prime; that function performs the Kannan–Bachem elimination on and applies the same operations to the identity matrix. Otherwise it computes the Hermite normal form of the matrix , which has full row rank, and reads off from the first columns and from the last .
Example#
The lattice spanned by three vectors in , its Hermite normal form computed by three algorithms, the determinant of the lattice as the product of the pivots, and a transformation matrix:
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpz_mat.h>
int main(void)
{
fmpz_mat_t A, H, H2, U, UA;
fmpz_t d;
slong i, j;
slong rows[3][3] = { { 4, 6, 10 }, { 2, -2, 8 }, { 6, 14, -6 } };
fmpz_init(d);
fmpz_mat_init(A, 3, 3);
fmpz_mat_init(H, 3, 3);
fmpz_mat_init(H2, 3, 3);
fmpz_mat_init(U, 3, 3);
fmpz_mat_init(UA, 3, 3);
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
fmpz_set_si(fmpz_mat_entry(A, i, j), rows[i][j]);
fmpz_mat_hnf(H, A);
fmpz_mat_print_pretty(H);
flint_printf("\nin HNF: %d\n", fmpz_mat_is_in_hnf(H));
fmpz_mat_hnf_classical(H2, A);
flint_printf("classical agrees: %d\n", fmpz_mat_equal(H, H2));
/* the lattice contains |det A| Z^3 */
fmpz_mat_det(d, A);
fmpz_abs(d, d);
flint_printf("|det A| = %{fmpz}\n", d);
fmpz_mat_hnf_modular(H2, A, d);
flint_printf("modular agrees: %d\n", fmpz_mat_equal(H, H2));
fmpz_mat_hnf_transform(H2, U, A);
fmpz_mat_mul(UA, U, A);
flint_printf("U A = H: %d\n", fmpz_mat_equal(UA, H));
fmpz_mat_det(d, U);
flint_printf("det U = %{fmpz}\n", d);
fmpz_mat_clear(A);
fmpz_mat_clear(H);
fmpz_mat_clear(H2);
fmpz_mat_clear(U);
fmpz_mat_clear(UA);
fmpz_clear(d);
return 0;
}[[2 8 2] [0 10 12] [0 0 18] ] in HNF: 1 classical agrees: 1 |det A| = 360 modular agrees: 1 U A = H: 1 det U = 1
The product of the pivots, , is the index of the lattice in , which equals .
Guides#
References#
- [DomKanTro1987] Domich, P. D. and Kannan, R. and Trotter, L. E. Jr. : Hermite Normal Form Computation Using Modulo Determinant Arithmetic, Math. Operations Res. (12) 1987 50-59
- [Coh1996] Cohen, Henri : A course in computational algebraic number theory, Springer, 1996
- [KanBac1979] Kannan, R. and Bachem, A. : Polynomial algorithms for computing and the Smith and Hermite normal forms of an integer matrix, SIAM J. Computation vol. 9 (1979) 499–507
- [FieHof2014] Fieker C. and Hofmann T.: "Computing in quotients of rings of integers" LMS Journal of Computation and Mathematics, 17(A), 349-365
- [PernetStein2010] Pernet, C. and Stein, W. : Fast computation of Hermite normal forms of random integer matrices ,J. Number Theory 130:17 (2010) 1675–1683
The FLINT team, “Hermite normal form (fmpz_mat.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz_mat/hnf.html (generated 2026-11-02).
@misc{flint-doc-fmpz-mat-hnf,
author = {{The FLINT team}},
title = {{Hermite normal form (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/hnf.html},
note = {Generated 2026-11-02}
}