FLINT3.7.0-dev
Module · 79 functions

fmpz_mod_mat.h

#include <flint/fmpz_mod_mat.h>

This module implements dense matrices over \mathbb{Z}/n\mathbb{Z} for an arbitrary modulus n \ge 1 given by an fmpz_mod_ctx_t. A matrix is an fmpz_mat_t whose entries are canonical residues in [0, n); it does not store the modulus, so every function takes the context. Many functions are thin wrappers: memory management, windows, comparison and printing are those of fmpz_mat; multiplication computes the exact integer product with fmpz_mat_mul (multimodular and BLAS-based methods) and reduces each entry once; and the Gaussian elimination functions (LU decomposition, solving, rank, reduced row echelon form, nullspace, determinant, characteristic and minimal polynomials) call the generic gr_mat algorithms over the fmpz_mod ring.

Most elimination functions require n to be prime, which is not checked; the guide Prime and composite moduli explains what happens for composite moduli and which functions work for every modulus (the determinant, the characteristic polynomial, Howell and strong echelon forms). For moduli of 2 to 16 limbs, generic gr_mat code over the mpn_mod ring is usually faster (Matrix multiplication over Z/nZ for multiword n).

AlgorithmGaussian elimination and LU decompositionLU decomposition with row pivoting over \mathbb{Z}/p\mathbb{Z} in its classical, delayed-reduction and recursive forms, and how FLINT derives triangular solving, linear system solving, inverses, determinants, ranks, echelon forms and nullspaces from it; plus division-free determinants and the Howell form over \mathbb{Z}/n\mathbb{Z}.

Guides#

Types and conventions#

fmpz_mod_mat_struct is the same type as fmpz_mat_struct, and fmpz_mod_mat_t an array of one of them, passed by reference. The fields entries, r, c and stride are those of fmpz_mat, so an fmpz_mod_mat_t can be passed to fmpz_mat functions (and to gr_mat functions over a gr_ctx_init_fmpz_mod ring) by a cast.

  • Entries must be canonical, in [0, n), unless stated otherwise, and results are canonical. Entries can be modified directly through fmpz_mod_mat_entry, but the caller must keep them canonical.
  • Dimensions must be compatible; this is not checked unless stated.
  • Unless stated otherwise, the output may alias the inputs.

Element access#

fmpz * fmpz_mod_mat_entry(const fmpz_mod_mat_t mat, slong i, slong j)

Return a pointer to the entry in row i and column j, respectively to the first entry of row i (the entries of a row are contiguous). Indices are 0-based and not checked.

void fmpz_mod_mat_set_entry(fmpz_mod_mat_t mat, slong i, slong j, const fmpz_t val, const fmpz_mod_ctx_t ctx)
void fmpz_mod_mat_get_entry(fmpz_t x, const fmpz_mod_mat_t mat, slong i, slong j, const fmpz_mod_ctx_t ctx)

Copy val into the entry in row i and column j (without reduction: val must be canonical), respectively copy that entry to x.

Memory management#

void fmpz_mod_mat_init(fmpz_mod_mat_t mat, slong rows, slong cols, const fmpz_mod_ctx_t ctx)

Initialises mat as a rows by cols zero matrix.

Initialises mat as a copy of src, with the same dimensions.

Frees the memory used by mat.

Basic properties and manipulation#

Return the number of rows and of columns of mat.

Return 1 if mat has zero rows or zero columns, respectively as many rows as columns, and 0 otherwise.

Set mat to the zero matrix, respectively to the matrix with ones on the main diagonal and zeros elsewhere (the zero matrix if n = 1). mat need not be square.

Sets B to a copy of A, which must have the same dimensions.

Swap two matrices. fmpz_mod_mat_swap swaps the structures in constant time; fmpz_mod_mat_swap_entrywise swaps the entries one by one, which also works for windows, and requires equal dimensions.

Sets B to the transpose of A. Aliasing is allowed for square matrices.

Conversions#

Sets A to the integer matrix B with every entry reduced modulo n. B may have any entries and the same dimensions as A. Large matrices are reduced in parallel.

Sets A to the integer matrix with the entries of B (in [0, n)).

Sets A to the matrix with the entries of B, read as unsigned integers. No reduction is done, so the modulus of B should be at most n (normally they are equal).

Reduces every entry of mat modulo n, in place; the entries may be any integers.

Random matrices#

Sets the entries of mat to uniformly random residues in [0, n).

Sets the entries to uniformly random nonzero residues in [1, n) (to zero if n = 1).

Sets mat to a random matrix for testing: fmpz_mat_randtest with the bit size of n (which favours special values and produces sparse matrices with probability 1/2), reduced modulo n.

Sets mat to a random sparse matrix of the given rank: rank random nonzero residues placed in distinct rows and columns, the other entries zero. For prime n the rank is exactly rank. Throws an exception if rank is negative or exceeds a dimension. fmpz_mod_mat_randops turns the result into a dense matrix of the same rank.

void fmpz_mod_mat_randtril(fmpz_mod_mat_t mat, flint_rand_t state, int unit, const fmpz_mod_ctx_t ctx)
void fmpz_mod_mat_randtriu(fmpz_mod_mat_t mat, flint_rand_t state, int unit, const fmpz_mod_ctx_t ctx)

Set mat to a random lower, respectively upper, triangular matrix with uniformly random entries below (above) the diagonal and nonzero diagonal entries, which are 1 if unit is nonzero.

Applies up to count random elementary operations (additions and subtractions of distinct rows or columns, fmpz_mat_randops) to mat and reduces the result. The rank and the determinant are unchanged.

Windows and concatenation#

void fmpz_mod_mat_window_init(fmpz_mod_mat_t window, const fmpz_mod_mat_t mat, slong r1, slong c1, slong r2, slong c2, const fmpz_mod_ctx_t ctx)

fmpz_mod_mat_window_init initialises window as the (r_2 - r_1) \times (c_2 - c_1) submatrix of mat with top left entry in row r_1 and column c_1, sharing its entries with mat. fmpz_mod_mat_window_clear releases the window without freeing the entries.

Set res to (\mathit{mat1} \; \mathit{mat2}), the m \times (k + l) matrix with mat1 (m \times k) on the left and mat2 (m \times l) on the right, respectively to the (m + k) \times l matrix with mat1 (m \times l) above mat2 (k \times l).

Input and output#

int fmpz_mod_mat_fprint(FILE * file, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx)

Print mat to file or to stdout in the format of fmpz_mat_fprint: the numbers of rows and columns, two spaces, and the entries in row-major order separated by spaces. Return a positive value on success and a nonpositive value if a write failed.

int fmpz_mod_mat_fprint_pretty(FILE * file, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx)

Print mat to file or to stdout in the format of fmpz_mat_fprint_pretty: rows in square brackets, one per line, inside an outer pair of brackets.

Comparison#

int fmpz_mod_mat_equal(const fmpz_mod_mat_t mat1, const fmpz_mod_mat_t mat2, const fmpz_mod_ctx_t ctx)

Returns 1 if the matrices have the same dimensions and entries, and 0 otherwise.

Return 1 if mat is the zero matrix, respectively has ones on the main diagonal and zeros elsewhere (always true for n = 1), and 0 otherwise.

Addition and scalar multiplication#

Set C = A + B, C = A - B and B = -A, row by row with the fmpz_mod_vec functions.

Set B = cA for any integer c. The products are computed exactly and reduced.

Matrix multiplication#

Set C = AB, respectively B = A^2 for square A. The number of columns of A must equal the number of rows of B.

More

Sets C = AB with the classical algorithm: each entry is an exact dot product (_fmpz_vec_dot on a transposed copy of B) reduced once. Blocks of entries are distributed over the available threads when all dimensions are at least 10. fmpz_mod_mat_mul does not call this function.

Sets D = AB + \mathit{op} \cdot C for \mathit{op} \in \{-1, 0, 1\} (C is not read for \mathit{op} = 0), with the classical algorithm on the calling thread and the num_threads threads of the pool given by threads. All dimensions must be positive.

Sets D = C - AB, using fmpz_mod_mat_mul and a temporary matrix.

Sets B = A^e for a square matrix A, with A^0 the identity. A wrapper of gr_mat_pow_ui (binary exponentiation). Aliasing is allowed.

void fmpz_mod_mat_mul_fmpz_vec(fmpz * c, const fmpz_mod_mat_t A, const fmpz * b, slong blen, const fmpz_mod_ctx_t ctx)
void fmpz_mod_mat_mul_fmpz_vec_ptr(fmpz * const * c, const fmpz_mod_mat_t A, const fmpz * const * b, slong blen, const fmpz_mod_ctx_t ctx)

Set the column vector c, of length the number of rows of A, to Ab modulo n, where b is truncated or zero-extended to the number of columns of A. The ptr variant takes arrays of pointers to the entries. b may contain any integers; c must not overlap b. The products are computed exactly with fmpz_mat_mul_fmpz_vec and reduced.

void fmpz_mod_mat_fmpz_vec_mul(fmpz * c, const fmpz * a, slong alen, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx)
void fmpz_mod_mat_fmpz_vec_mul_ptr(fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx)

Set the row vector c, of length the number of columns of B, to aB modulo n, where a is truncated or zero-extended to the number of rows of B. As above, a may contain any integers and c must not overlap a.

Trace#

void fmpz_mod_mat_trace(fmpz_t trace, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx)

Sets trace to the sum of the diagonal entries of the square matrix mat, modulo n.

Permutations#

Swap rows (columns) r and s of mat and, if perm is not NULL, entries r and s of the permutation array perm.

Reverse the order of the rows (columns) of mat and, if perm is not NULL, of the entries of perm.

Gaussian elimination#

These functions are wrappers of the generic gr_mat algorithms over the fmpz_mod ring, which in turn use fmpz_mod_mat_mul for the products in block recursive algorithms. Unless stated otherwise they require n to be prime, which is not checked. For a composite modulus they work as long as every pivot they meet is invertible; otherwise they throw an exception or, for the functions returning a success flag, return 0 even if the result exists. See Prime and composite moduli.

slong fmpz_mod_mat_lu(slong * P, fmpz_mod_mat_t A, int rank_check, const fmpz_mod_ctx_t ctx)

Computes a generalised LU decomposition PA = LU of A in place and returns the rank of A. P must have room for as many entries as A has rows; it receives the row permutation. A wrapper of gr_mat_lu.

More

Set X = L^{-1} B, respectively X = U^{-1} B, for a square lower (upper) triangular matrix whose diagonal entries are invertible; if unit is nonzero, the diagonal is taken to be 1 and not read. Only the lower (upper) triangle is read. X may alias B. Wrappers of gr_mat_nonsingular_solve_tril and gr_mat_nonsingular_solve_triu, which choose between substitution and a block recursive algorithm; they throw an exception if a diagonal entry is not invertible.

Solves AX = B for a square matrix A. Returns 1 if A is nonsingular; otherwise returns 0 and leaves X undefined. A wrapper of gr_mat_nonsingular_solve_lu.

Solves AX = B for a matrix A of any shape and rank. Returns 1 and sets X to one solution if a solution exists; otherwise returns 0 and leaves X undefined. A wrapper of gr_mat_solve_field.

Sets B = A^{-1} and returns 1 if the square matrix A is invertible; otherwise returns 0 and leaves B undefined. A and B must have the same dimensions. The inverse is computed by solving AB = I with fmpz_mod_mat_solve; a 1 \times 1 matrix is inverted with fmpz_mod_inv, which throws an exception for a nonzero non-unit.

Returns the rank of A, computed by LU decomposition (gr_mat_rank_lu).

Sets res to the reduced row echelon form of mat, which has the same dimensions, and returns the rank. A wrapper of gr_mat_rref_lu.

Computes a basis of the right nullspace \{x : Ax = 0\} of A and returns its dimension (the nullity) k. The basis vectors are written to the first k columns of X, and all other entries of X are set to zero. X is not resized: it must have as many rows as A has columns and at least k columns (allocate it square, with the number of columns of A, when k is not known).

void fmpz_mod_mat_det(fmpz_t res, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx)

Sets res to the determinant of the square matrix mat, and throws an exception if mat is not square. A wrapper of gr_mat_det; this works for every modulus, since a failed LU decomposition falls back to a division-free algorithm.

Reduces row m of A against the earlier rows, with the conventions of gr_mat_reduce_row: P[i] is the row with its pivot in column i, or -1; L[i] bounds the nonzero columns of row i. Sets *column to the pivot column of the reduced row (made monic and recorded in P), or to -1 if the row becomes zero. Returns GR_SUCCESS, or GR_DOMAIN if the new pivot is not invertible. The sums are accumulated exactly and each entry is reduced once, when it is reached.

Howell form and strong echelon form#

These functions work for every modulus. They are wrappers of fmpz_mat_strong_echelon_form_mod and fmpz_mat_howell_form_mod; see Hermite and Smith normal forms and Gaussian elimination and LU decomposition for the algorithms.

Transforms mat into its strong echelon form [FieHof2014], which equals the Howell form up to the order of the rows. mat must have at least as many rows as columns.

Transforms mat into its Howell form [How1986; StoMul1998] and returns the number of nonzero rows. mat must have at least as many rows as columns. Two matrices generate the same submodule of (\mathbb{Z}/n\mathbb{Z})^c if and only if their Howell forms are equal.

Similarity transforms and polynomials#

Applies a similarity transform to the square matrix A in place: with P the identity matrix whose row r (0-indexed) has its zero entries replaced by d, sets A = P^{-1} A P. d must be canonical. A wrapper of gr_mat_apply_row_similarity; it uses no divisions and works for every modulus. Similarity transforms preserve the determinant and the characteristic and minimal polynomials.

Set p to the characteristic polynomial \det(xI - M) of the square matrix M; the underscore version writes its m + 1 coefficients for an m \times m matrix. fmpz_mod_mat_charpoly throws an exception if M is not square. These work for every modulus: the generic fmpz_mod ring uses Danilevsky's algorithm for m \ge 16 and falls back to the division-free Berkowitz algorithm when it fails, and uses Berkowitz for smaller m.

Sets p to the minimal polynomial of the square matrix M, using gr_mat_minpoly_field. Throws an exception if M is not square. The modulus must be prime; the ring is declared a field without checking.

References#

  • [FieHof2014] Fieker C. and Hofmann T.: "Computing in quotients of rings of integers" LMS Journal of Computation and Mathematics, 17(A), 349-365
  • [How1986] J. A. Howell, "Spans in the module (\mathbb{Z}_m)^s", Linear and Multilinear Algebra 19 (1986), 67-77
  • [StoMul1998] Storjohann, Arne and Mulders, Thom : Fast algorithms for linear algebra modulo :math:N : Algorithms—{ESA} '98 (Venice), Lecture Notes in Comput. Sci. 1461 139–150
Cite this page

The FLINT team, “fmpz_mod_mat.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz_mod_mat/index.html (generated 2026-10-20).