FLINT3.7.0-dev
Module · 120 functions

nmod_mat.h

#include <flint/nmod_mat.h>

This module implements dense matrices over \mathbb{Z}/n\mathbb{Z} for a word-size modulus n \ge 1. An nmod_mat_t stores its entries as ulong values in [0, n) in row-major order, together with its dimensions and the modulus as an nmod_t. Matrix multiplication, the operation on which everything else rests, chooses among classical multiplication with delayed reduction, Strassen–Winograd, vectorised kernels for moduli up to 2^{52}, bit- and byte-packed kernels for moduli up to 255 and floating-point gemm; see Multiplying matrices. On top of it the module provides LU decomposition, linear system solving, determinants, inverses, echelon forms, nullspaces and characteristic and minimal polynomials, most of which require n to be prime. The multimodular algorithms for matrices over \mathbb{Z} in fmpz_mat.h are built on this module.

The guide Linear algebra modulo n explains which functions work for which moduli and how they fit together.

OverviewMultiplying matrices over Z/nZThe methods FLINT uses to multiply matrices modulo a word-size integer, from classical multiplication with delayed reduction to Strassen–Winograd, SIMD kernels, floating-point gemm with Chinese remaindering and bit-packed kernels for tiny moduli, and how nmod_mat_mul chooses among them.

Guides#

Types and conventions#

An nmod_mat_struct has the fields entries (a pointer to the entry in row 0, column 0), r and c (the numbers of rows and columns), stride (the distance in words between the starts of consecutive rows) and mod (the modulus as an nmod_t). An nmod_mat_t is an array of one nmod_mat_struct, so that it is passed by reference.

More

The following conventions apply throughout the module.

  • Reduced entries. Unless stated otherwise, the entries of input matrices must lie in [0, n), and output entries do. Entries may be written directly with nmod_mat_entry; it is then the caller's responsibility to keep them reduced. Nothing is checked.
  • Dimensions. The output must be initialised with dimensions compatible with the operation; most functions do not check this (some check it with FLINT_ASSERT only). Matrices with zero rows or columns are allowed everywhere.
  • Modulus. All matrices passed to one function must have the same modulus. Any n \ge 1 is allowed for memory management, arithmetic, multiplication, determinants, characteristic polynomials and the Howell form. LU decomposition, solving, inversion, rank, echelon forms, nullspaces and minimal polynomials divide by pivots and assume that n is prime. This is not checked: a pivot that is not invertible raises a FLINT_IMPINV exception, and other results may be silently wrong. See Which functions need a prime modulus.
  • Aliasing. Each function states whether the output may be the same matrix as an input. Partially overlapping windows are never allowed.

Memory management#

void nmod_mat_init(nmod_mat_t mat, slong rows, slong cols, ulong n)

Initialises mat as a rows by cols matrix modulo n with all entries zero. Requires n \ge 1. Throws an exception if \mathit{rows} \cdot \mathit{cols} overflows an slong.

Initialises mat as a copy of src, with the same dimensions and modulus. The copy owns its entries even if src is a window.

Frees the memory used by mat. Must not be called on a window.

Copies the entries of A to B, which must have the same dimensions. The modulus of B is not changed.

Swaps mat1 and mat2 in constant time by swapping their structs. Must not be used with windows, whose entries belong to another matrix.

Swaps the entries of two matrices of the same dimensions one by one. This works for windows.

Returns the modulus of mat.

Sets the modulus of mat to n \ge 1. The entries are not changed, so they must be reduced afterwards if they may exceed n - 1.

Entries and dimensions#

nmod_mat_entry(mat, i, j)

The entry in row i and column j of mat (indexed from zero), as an lvalue that can be read and assigned. No bounds checking is performed.

ulong nmod_mat_get_entry(const nmod_mat_t mat, slong i, slong j)
void nmod_mat_set_entry(nmod_mat_t mat, slong i, slong j, ulong x)

Returns, respectively sets, the entry in row i and column j. x must be reduced.

ulong * nmod_mat_entry_ptr(const nmod_mat_t mat, slong i, slong j)

Returns 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; the next row starts mat->stride words later.

Returns the number of rows, respectively columns, of mat.

Returns 1 if mat has no rows or no columns, respectively if it has as many rows as columns, and 0 otherwise.

Windows#

void nmod_mat_window_init(nmod_mat_t window, const nmod_mat_t mat, slong r1, slong c1, slong r2, slong c2)

Initialises window as the submatrix of mat formed by rows r_1 to r_2 - 1 and columns c_1 to c_2 - 1, where 0 \le r_1 \le r_2 \le mat->r and 0 \le c_1 \le c_2 \le mat->c. The window shares its entries with mat, so writing to one changes the other.

More

Releases a window. This does nothing at present, but every window should be cleared for future compatibility.

Concatenation#

void nmod_mat_concat_vertical(nmod_mat_t res, const nmod_mat_t mat1, const nmod_mat_t mat2)

Sets res to mat1 placed above mat2, respectively to the left of mat2. For an m \times n matrix mat1, mat2 must be k \times n and res (m + k) \times n, respectively mat2 m \times k and res m \times (n + k). res must not be aliased with the inputs.

Special matrices and comparison#

Sets mat to the zero matrix, respectively to the matrix with ones on the main diagonal and zeros elsewhere. mat need not be square.

int nmod_mat_equal(const nmod_mat_t mat1, const nmod_mat_t mat2)

Returns 1 if the two matrices have the same dimensions and the same entries, and 0 otherwise. The moduli are not compared.

Returns 1 if mat is zero, if it has ones on the main diagonal and zeros elsewhere, or if its row i is zero, respectively, and 0 otherwise. Empty matrices are both zero and one.

More

Random matrices#

These functions are intended for testing.

Sets the entries to independent integers chosen uniformly at random in [0, n).

Sets each row with _nmod_vec_randtest: entries from n_randtest reduced modulo n, and with probability 1/2 a sparse row.

Sets the entries to independent integers chosen uniformly at random in [1, n), so that no entry is zero.

More

Sets mat to P D Q where D is the matrix with d_0, \ldots, d_{n-1} (the entries of diag) on the main diagonal and zeros elsewhere, and P and Q are random permutation matrices. Requires n \le the number of rows and of columns. Returns the parity (0 for even, 1 for odd) of the two permutations combined.

Sets mat to a random matrix of the given rank, with exactly rank nonzero entries, each uniform in [1, n) and no two in the same row or column. Throws an exception if rank is negative or exceeds a dimension. Follow with nmod_mat_randops to obtain a dense matrix of the same rank.

More

Performs count random elementary operations on mat, each adding or subtracting a row to or from another row, or a column to or from another column (operations whose two indices coincide are skipped). These operations have determinant 1, so the rank and, for square matrices, the determinant are preserved.

void nmod_mat_randtril(nmod_mat_t mat, flint_rand_t state, int unit)
void nmod_mat_randtriu(nmod_mat_t mat, flint_rand_t state, int unit)

Sets mat to a random lower, respectively upper, triangular matrix. The entries strictly below (above) the diagonal are random, the diagonal entries are 1 if unit is nonzero and random nonzero values otherwise. mat need not be square.

More

Printing#

int nmod_mat_fprint_pretty(FILE * file, const nmod_mat_t mat)

Prints a header line with the dimensions and modulus, then one line per row, with the entries in brackets and right-aligned to the number of decimal digits of n. nmod_mat_fprint_pretty returns a positive value on success and a nonpositive value on a write error. Functions with a FILE argument are declared only if <stdio.h> is included before nmod_mat.h.

More
int nmod_mat_print(const nmod_mat_t mat)
int nmod_mat_fprint(FILE * f, const nmod_mat_t mat)

The same as nmod_mat_fprint_pretty, writing to stdout and f respectively.

Transposition and permutations#

Sets B to the transpose of A. Throws an exception unless B has as many rows as A has columns and vice versa. B may be aliased with A if A is square.

More
void _nmod_mat_transpose(nn_ptr B, slong Bstride, nn_srcptr A, slong Astride, slong m, slong n)

Writes the transpose of the m \times n array A (row stride Astride) to the n \times m array B (row stride Bstride). The words are copied as they are. The two arrays must not overlap.

Swaps rows (columns) r and s of mat. If perm is not NULL, entries r and s of the array perm are swapped as well.

Reverses the order of the rows (columns) of mat, that is, swaps rows (columns) i and r - 1 - i for 0 \le i < r/2, where r is the number of rows (columns). If perm is not NULL, the same permutation is applied to it.

void nmod_mat_permute_rows(nmod_mat_t mat, const slong * perm_act, slong * perm_store)

Replaces row i of mat by the old row perm_act[i], for every i, where perm_act is a permutation of the row indices. If perm_store is not NULL, it is updated in the same way: perm_store[i] becomes the old perm_store[perm_act[i]].

Addition and scalar multiplication#

These functions allow the output to be aliased with any input.

void nmod_mat_add(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B)
void nmod_mat_sub(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B)

Sets C = A + B, respectively C = A - B. The three matrices must have the same dimensions.

Sets B = -A. The matrices must have the same dimensions.

Sets B = cA. Requires c < n.

More

Sets B = cA for any integer c, which is first reduced modulo n.

Sets C = A + cB. Unlike nmod_mat_scalar_mul, c may be any word; it is reduced modulo n first. Uses Shoup multiplication under the same conditions as nmod_mat_scalar_mul.

Matrix multiplication#

nmod_mat_mul is the function to use: it selects the fastest of the methods below for the dimensions, the modulus, the number of threads and the instruction set. The other functions are the individual methods, documented for testing, benchmarking and special needs. The kernels that return an int return 0, without touching C, when they do not apply. All methods work for any modulus within their range, prime or not.

OverviewMultiplying matrices over Z/nZThe methods FLINT uses to multiply matrices modulo a word-size integer, from classical multiplication with delayed reduction to Strassen–Winograd, SIMD kernels, floating-point gemm with Chinese remaindering and bit-packed kernels for tiny moduli, and how nmod_mat_mul chooses among them.
void nmod_mat_mul(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B)

Sets C = AB, where A is m \times k, B is k \times n and C is m \times n. C may be aliased with A or B.

Full documentation
void nmod_mat_addmul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B)
void nmod_mat_submul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B)

Sets D = C + AB, respectively D = C - AB. D may be aliased with C but not with A or B. The product is either computed by classical multiplication fused with the addition, or with nmod_mat_mul and then added; see Adding a product.

Full documentation

Sets C = AB by classical multiplication, computing each entry as a dot product with a single reduction. C must not be aliased with A or B.

More

The same as nmod_mat_mul_classical, with the rows of C distributed over the threads of FLINT's thread pool. Dimensions below 20 are handled by the serial code. C must not be aliased with A or B.

Sets C = AB by one level of the Strassen–Winograd algorithm: seven products of half-size blocks, each computed by nmod_mat_mul (which may recurse), and 15 block additions. C must not be aliased with A or B.

More

Sets C = AB by floating-point matrix multiplication with flint_sgemm or flint_dgemm, which use an external BLAS if FLINT was built with one and FLINT's own kernels otherwise. Returns 1 on success. Returns 0, and does nothing, if a dimension is 0 or exceeds INT_MAX, if the inner dimension is so large that no suitable set of at most 12 moduli exists, or on 32-bit machines. C may be aliased with A or B.

More

Sets C = AB for a modulus n \le 255 (checked only by FLINT_ASSERT) using kernels for entries stored in bytes. C may be aliased with A or B. Uses several threads when available.

More
void _nmod_mat_mul_u8(uint8_t * C, slong Cstride, const uint8_t * A, slong Astride, const uint8_t * B, slong Bstride, slong m, slong k, slong n, nmod_t mod)

The multiplication of nmod_mat_mul_u8 on byte arrays: sets the m \times n array C to AB, where A is m \times k and B is k \times n, each stored by rows with the given row strides (in bytes), with entries reduced modulo mod.n, which must be at most 255. C may be equal to A or B (same pointer) but must not otherwise overlap them.

Sets C = AB for a modulus n < 2^{32} with an integer SIMD kernel (AVX-512, AVX2, NEON, or portable C), and returns 1. Returns 0 if n \ge 2^{32} or on 32-bit machines. C may be aliased with A or B. Uses several threads when available.

More
int _nmod_mat_mul_u32(uint32_t * C, slong Cstride, const uint32_t * A, slong Astride, const uint32_t * B, slong Bstride, slong m, slong k, slong n, nmod_t mod)

The multiplication of nmod_mat_mul_u32 on arrays of 32-bit entries: A is m \times k, B is k \times n and C is m \times n, each stored by rows with the given row strides, with entries reduced modulo mod.n. Returns 0 if mod.n \ge 2^{32} or on 32-bit machines and 1 otherwise. C may be equal to A or B (same pointer and stride) but must not otherwise overlap them.

Sets C = AB for a modulus n \le 2^{52} with the AVX512-IFMA instructions, and returns 1. Returns 0 if n > 2^{52}, or if FLINT was not compiled for a processor with AVX512-IFMA (or on 32-bit machines). C may be aliased with A or B. Uses several threads when available.

More

Sets C = AB for a modulus n \le 2^{52} with integer SIMD instructions (AVX-512, AVX2, NEON, or portable C), and returns 1. Returns 0 if n > 2^{52}, on 32-bit machines, and for the portable C code compiled by MSVC. C may be aliased with A or B. Uses several threads when available.

More

Sets C = AB for a modulus n < 2^{50} in double precision, and returns

  1. Returns 0 if n \ge 2^{50}, on 32-bit machines, and for the portable C code compiled by MSVC. C may be aliased with A or B. Uses several threads when available.
More

Matrix-vector products#

void nmod_mat_mul_nmod_vec(ulong * c, const nmod_mat_t A, const ulong * b, slong blen)
void nmod_mat_mul_nmod_vec_ptr(ulong * const * c, const nmod_mat_t A, const ulong * const * b, slong blen)

Sets c = Ab, where A is m \times k and b is the vector of length blen, truncated or extended by zeros to length k. The m entries of c are written. In the _ptr version, entry i of b and c is *b[i] and *c[i]. Each entry of c is a dot product with one reduction. c must not overlap b, except in the _ptr version, which copies.

void nmod_mat_nmod_vec_mul(ulong * c, const ulong * a, slong alen, const nmod_mat_t B)
void nmod_mat_nmod_vec_mul_ptr(ulong * const * c, const ulong * const * a, slong alen, const nmod_mat_t B)

Sets c = aB, where B is k \times n and a is the vector of length alen, truncated or extended by zeros to length k. The n entries of c are written. In the _ptr version, entry i of a and c is *a[i] and *c[i]. c must not overlap a, except in the _ptr version, which copies.

More

Powers and trace#

void nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow)
void _nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow)

Sets dest to mat raised to the power pow, by binary exponentiation. The matrix must be square; the power 0 gives the identity matrix. nmod_mat_pow allows dest to be aliased with mat; _nmod_mat_pow does not.

Returns the sum of the diagonal entries of the square matrix mat.

Triangular solving#

These functions solve LX = B or UX = B for a square triangular matrix with r rows and an r \times c matrix B. Only the triangle and, if unit is 0, the diagonal of L or U are read, so they may be stored in a matrix holding other data, such as the output of nmod_mat_lu. If unit is nonzero the diagonal is taken to be 1. Otherwise every diagonal entry must be invertible modulo n, or a FLINT_IMPINV exception is raised. X may be aliased with B, but no other aliasing is allowed.

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}.
void nmod_mat_solve_tril(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit)
void nmod_mat_solve_triu(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit)

Sets X = L^{-1} B for lower triangular L, respectively X = U^{-1} B for upper triangular U. Uses substitution if B has fewer than 64 rows or fewer than 64 columns, and the recursive algorithm otherwise.

Forward, respectively back, substitution: each column of X is computed entry by entry, each entry with one dot product and one reduction. The inverses of the diagonal entries are computed once.

Splits L (or U) into blocks of \lfloor r/2 \rfloor and \lceil r/2 \rceil rows and solves recursively, reducing the work to matrix multiplications.

More

LU decomposition#

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}.
slong nmod_mat_lu(slong * P, nmod_mat_t A, int rank_check)

Computes an LU decomposition with row pivoting of the m \times n matrix A modulo a prime, overwriting A with L and U, and returns the rank r. On return, row i of LU is row P[i] of the original A, where P is an array of length m (it need not be initialised). U is in row echelon form with r nonzero rows, and L is m \times r unit lower triangular. If rank_check is nonzero, the function may stop as soon as it finds that the rank is less than n, and then returns 0 and leaves A undefined.

Full documentation
slong nmod_mat_lu_with_pivots(slong * P, slong * pivots_nonpivots, nmod_mat_t A)

The same as nmod_mat_lu with rank_check 0, and in addition writes to pivots_nonpivots, an array of length n, the indices of the r pivot columns of U in increasing order followed by the indices of the n - r other columns in increasing order.

Full documentation

Solving linear systems#

These functions require a prime modulus.

Solves AX = B for a square matrix A. If A is nonsingular, sets X to the unique solution and returns 1. Otherwise returns 0 and leaves X unchanged. X may be aliased with A or B.

Full documentation

Solves Ax = b for a square m \times m matrix A and vectors x, b of length m, as nmod_mat_solve. x may be equal to b.

Full documentation

Decides whether AX = B has a solution for an arbitrary m \times n matrix A and m \times c matrix B. If so, sets the n \times c matrix X to a solution and returns 1; otherwise sets X to zero and returns 0. Returns 0 if the dimensions are incompatible. X may be aliased with B but not with A.

Full documentation
int nmod_mat_can_solve_inner(slong * rank, slong * perm, slong * pivots, nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B)

The same as nmod_mat_can_solve, and in addition, for each pointer that is not NULL, stores the rank of A in *rank, the row permutation of the LU decomposition of A in perm (length m), and the indices of the pivot columns in the first *rank entries of pivots (length at least \min(m, n)).

Full documentation

Determinant, rank and inverse#

Returns the determinant of the square matrix A, for any modulus. Throws an exception if A is not square.

Full documentation

Returns the determinant of the square matrix A, for any modulus, by triangularising A with Euclidean row operations. Throws an exception if A is not square.

Full documentation

Returns the rank of A, which may have any shape. The modulus must be prime.

Full documentation

If the square matrix A is invertible, sets B = A^{-1} and returns 1. Otherwise returns 0, and the entries of B are unspecified. The modulus must be prime. B may be aliased with A.

Full documentation

Row echelon form and nullspace#

These functions require a prime modulus.

Puts A in reduced row echelon form and returns its rank.

Full documentation

Sets the first d columns of X to a basis of the right nullspace \{x : Ax = 0\} of the m \times n matrix A, sets the other entries of X to zero, and returns the nullity d = n - \operatorname{rank}(A). X must have n rows and at least d columns; n \times n always suffices. X may be aliased with A.

Full documentation

Sets the first d rows of X to a basis of the left nullspace \{v : vA = 0\} of the m \times n matrix A, sets the other entries of X to zero, and returns the nullity d = m - \operatorname{rank}(A). X must have at least d rows and m columns; m \times m always suffices.

Full documentation

Reduces row m of M against rows that are already reduced, for incremental Gaussian elimination, and returns the column of its new pivot, or -1 if it reduces to zero.

More

Howell form#

These functions work for any modulus. For a prime modulus they compute the reduced row echelon form, up to the position of zero rows.

The algorithms are described in Howell form.

Puts A in strong echelon form, using the algorithm of [FieHof2014]. A must have at least as many rows as columns; add zero rows otherwise.

More

Puts A in Howell form [StoMul1998] and returns the number k of nonzero rows, which come first. A must have at least as many rows as columns.

More

Characteristic and minimal polynomials#

These functions are declared in nmod_poly.h. The polynomial must be initialised with the same modulus as the matrix.

AlgorithmCharacteristic and minimal polynomialsBerkowitz's division-free algorithm and Danilevsky's reduction to companion form for the characteristic polynomial over \mathbb{Z}/n\mathbb{Z}, and the Krylov method with least common multiples that FLINT uses for the minimal polynomial.

Sets p to the characteristic polynomial \det(xI - M) of the square matrix M. An exception is thrown if M is not square. nmod_mat_charpoly and the division-free _berkowitz work for any modulus. _danilevsky returns 1 on success and 0 if it needs an inverse that does not exist, which cannot happen for a prime modulus. For n = 1 the result is the zero polynomial.

Full documentation

Sets p to the minimal polynomial of the square matrix M, the monic polynomial of least degree with p(M) = 0, and throws an exception if M is not square. The modulus must be prime. If P is not NULL, nmod_mat_minpoly_with_gens sets P[j] to 1 for each index j such that the unit vector e_j was used as a Krylov generator, and leaves the other entries of the array (of length r) unchanged.

Full documentation

Replaces the square matrix M by P^{-1} M P, where P is the identity matrix with the entries in row r and every column j \notin \{r-1, r\} replaced by d. Requires d < n.

More

Tuning parameters#

These macros are defined in nmod_mat.h. The parameters of nmod_mat_mul are in flint-mparam.h; see How the method is chosen.

The dimension (20) from which classical multiplication transposes B before forming dot products, and below which the threaded classical multiplication runs serially.

The triangular solving functions use substitution when the right-hand side has fewer than NMOD_MAT_SOLVE_TRI_ROWS_CUTOFF (64) rows or fewer than NMOD_MAT_SOLVE_TRI_COLS_CUTOFF (64) columns, and the recursive algorithm otherwise.

A suggested bit size, FLINT_BITS - 5, for the primes of multimodular algorithms that rely on matrix multiplication, used for example by fmpz_mat_mul_multi_mod and the Dixon solver of fmpz_mat. It was chosen when classical multiplication with two-word dot products was the fastest method; with the SIMD kernels, primes of at most 52 bits can be cheaper per bit of modulus.

Internal functions#

These functions are used by the functions above and by other modules.

void _nmod_mat_mul_classical_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op)

Sets D = AB if op is 0, D = C + AB if op is 1 and D = C - AB if op is -1, by the classical algorithm of nmod_mat_mul_classical. D may be aliased with C but not with A or B. C is not read if op is 0.

void _nmod_mat_mul_classical_threaded_pool_op(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, int op, thread_pool_handle * threads, slong num_threads)

The threaded version of _nmod_mat_mul_classical_op, using the num_threads threads in threads, obtained from flint_request_threads, in addition to the calling thread. If k = 0 or the modulus is 1, D is not written.

Sets B = cA with nmod_mul, respectively with n_mulmod_shoup and c_pr = n_mulmod_precomp_shoup(c, n), which requires n < 2^{\mathtt{FLINT\_BITS} - 1}. Both require c < n.

void _nmod_mat_scalar_addmul_ui_precomp(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B, const ulong c, const ulong c_pr)

Sets C = A + cB, as the two functions above. Both require c < n.

Returns the determinant of the square matrix A modulo a prime, computed by nmod_mat_lu, which destroys A.

Returns the determinant of the square matrix A for any modulus, as nmod_mat_det_howell, destroying A.

slong _nmod_mat_rref(nmod_mat_t A, slong * pivots_nonpivots, slong * P)

Puts A in reduced row echelon form and returns the rank r, as nmod_mat_rref, and in addition stores in pivots_nonpivots (length the number of columns) the pivot columns followed by the other columns, and in P (length the number of rows) the row permutation of the LU decomposition used.

Writes the r + 1 coefficients of the characteristic polynomial of the r \times r matrix M to p, by Berkowitz's algorithm. Works for any modulus.

References#

  • [FieHof2014] Fieker C. and Hofmann T.: "Computing in quotients of rings of integers" LMS Journal of Computation and Mathematics, 17(A), 349-365
  • [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, “nmod_mat.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/nmod_mat/index.html (generated 2026-10-20).