FLINT3.7.0-dev
Module · 137 functions

nmod_mat.h

#include <flint/nmod_mat.h>

This module implements dense matrices over Z/nZ\mathbb{Z}/n\mathbb{Z} for a word-size modulus n≥1n \ge 1. An nmod_mat_t stores its entries as ulong values in [0,n)[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 2522^{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 nn to be prime. The multimodular algorithms for matrices over Z\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)[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≥1n \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 nn 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 nn with all entries zero. Requires n≥1n \ge 1. Throws an exception if rows⋅cols\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 AA to BB, which must have the same dimensions. The modulus of BB 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≥1n \ge 1. The entries are not changed, so they must be reduced afterwards if they may exceed n−1n - 1.

Entries and dimensions#

nmod_mat_entry(mat, i, j)

The entry in row ii and column jj 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 ii and column jj. 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 ii and column jj, respectively to the first entry of row ii. 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 r1r_1 to r2−1r_2 - 1 and columns c1c_1 to c2−1c_2 - 1, where 0≤r1≤r2≤0 \le r_1 \le r_2 \le mat->r and 0≤c1≤c2≤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×nm \times n matrix mat1, mat2 must be k×nk \times n and res (m+k)×n(m + k) \times n, respectively mat2 m×km \times k and res m×(n+k)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 ii 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)[0, n).

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

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

More

Sets mat to PDQP D Q where DD is the matrix with d0,…,dn−1d_0, \ldots, d_{n-1} (the entries of diag) on the main diagonal and zeros elsewhere, and PP and QQ are random permutation matrices. Requires n≤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)[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
void nmod_mat_randrank_profile(nmod_mat_t mat, flint_rand_t state, const slong * mrp_r, const slong * mrp_c, slong rank)

For a prime modulus, sets mat to a random matrix of rank rr = rank whose rank profile matrix has its rr nonzero entries at the positions (mrp_r[k], mrp_c[k]) for 0≤k<r0 \le k < r, given in any order. Throws an exception if rank is negative or exceeds a dimension, or if two positions share a row or a column or one lies outside the matrix.

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 nn. 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 BB to the transpose of AA. Throws an exception unless BB has as many rows as AA has columns and vice versa. BB may be aliased with AA if AA 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×nm \times n array AA (row stride Astride) to the n×mn \times m array BB (row stride Bstride). The words are copied as they are. The two arrays must not overlap.

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

Reverses the order of the rows (columns) of mat, that is, swaps rows (columns) ii and r−1−ir - 1 - i for 0≤i<r/20 \le i < r/2, where rr 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 ii of mat by the old row perm_act[i], for every ii, 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+BC = A + B, respectively C=A−BC = A - B. The three matrices must have the same dimensions.

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

Sets B=cAB = cA. Requires c<nc < n.

More

Sets B=cAB = cA for any integer cc, which is first reduced modulo nn.

Sets C=A+cBC = A + cB. Unlike nmod_mat_scalar_mul, cc may be any word; it is reduced modulo nn 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 CC, 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=ABC = AB, where AA is m×km \times k, BB is k×nk \times n and CC is m×nm \times n. CC may be aliased with AA or BB.

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+ABD = C + AB, respectively D=C−ABD = C - AB. DD may be aliased with CC but not with AA or BB. 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=ABC = AB by classical multiplication, computing each entry as a dot product with a single reduction. CC must not be aliased with AA or BB.

More

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

Sets C=ABC = 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. CC must not be aliased with AA or BB.

More

Sets C=ABC = 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. CC may be aliased with AA or BB.

More

Sets C=ABC = AB for a modulus n≤255n \le 255 (checked only by FLINT_ASSERT) using kernels for entries stored in bytes. CC may be aliased with AA or BB. 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×nm \times n array CC to ABAB, where AA is m×km \times k and BB is k×nk \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. CC may be equal to AA or BB (same pointer) but must not otherwise overlap them.

Sets C=ABC = AB for a modulus n<232n < 2^{32} with an integer SIMD kernel (AVX-512, AVX2, NEON, or portable C), and returns 1. Returns 0 if n≥232n \ge 2^{32} or on 32-bit machines. CC may be aliased with AA or BB. 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: AA is m×km \times k, BB is k×nk \times n and CC is m×nm \times n, each stored by rows with the given row strides, with entries reduced modulo mod.n. Returns 0 if mod.n ≥232\ge 2^{32} or on 32-bit machines and 1 otherwise. CC may be equal to AA or BB (same pointer and stride) but must not otherwise overlap them.

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

More

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

More

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

  1. Returns 0 if n≥250n \ge 2^{50}, on 32-bit machines, and for the portable C code compiled by MSVC. CC may be aliased with AA or BB. 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=Abc = Ab, where AA is m×km \times k and bb is the vector of length blen, truncated or extended by zeros to length kk. The mm entries of cc are written. In the _ptr version, entry ii of bb and cc is *b[i] and *c[i]. Each entry of cc is a dot product with one reduction. cc must not overlap bb, 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=aBc = aB, where BB is k×nk \times n and aa is the vector of length alen, truncated or extended by zeros to length kk. The nn entries of cc are written. In the _ptr version, entry ii of aa and cc is *a[i] and *c[i]. cc must not overlap aa, 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=BLX = B or UX=BUX = B for a square triangular matrix with rr rows and an r×cr \times c matrix BB, or, for the _right versions, XL=BXL = B or XU=BXU = B for a k×rk \times r matrix BB. Only the relevant triangular part and, if unit is 0, the diagonal of LL or UU 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 nn, or a FLINT_IMPINV exception is raised. XX may be aliased with BB, but no other aliasing is allowed.

AlgorithmGaussian elimination and LU decompositionLU decomposition with row pivoting over Z/pZ\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 Z/nZ\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−1BX = L^{-1} B for lower triangular LL, respectively X=U−1BX = U^{-1} B for upper triangular UU. Uses substitution if BB has fewer than 64 rows or fewer than 64 columns, and the recursive algorithm otherwise.

Forward, respectively back, substitution, for an r×rr \times r triangular matrix. If BB has at least max⁡(4,r/4)\max(4, r/4) columns (max⁡(4,r/2)\max(4, r/2) for n>231n > 2^{31}, or n>215n > 2^{15} with 32-bit words), the rows of XX are computed one after the other, each as the row of BB minus a linear combination of the rows already computed, with delayed reductions: the products are accumulated by vectors in one, two or three words and each entry is reduced once (or a few times, for some moduli below 2322^{32}). Otherwise each column of XX is computed entry by entry, each entry with one dot product and one reduction, which is faster with few long columns. The inverses of the diagonal entries are computed once.

Splits LL (or UU) into blocks of ⌊r/2⌋\lfloor r/2 \rfloor and ⌈r/2⌉\lceil r/2 \rceil rows and solves recursively, reducing the work to matrix multiplications.

More
void nmod_mat_solve_tril_right(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit)
void nmod_mat_solve_triu_right(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit)

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

Substitution, for an r×rr \times r triangular matrix, with three methods. If BB has at least max⁡(6,r/4)\max(6, r/4) rows (max⁡(6,r/2)\max(6, r/2) for n>231n > 2^{31}, or n>215n > 2^{15} with 32-bit words), as nmod_mat_solve_tril_classical (nmod_mat_solve_triu_classical) with delayed reductions on the transposed system, BB being transposed by blocks of 256 rows. Otherwise, if r≤128r \le 128 (r≤64r \le 64 for these larger moduli) or BB has at most 4 rows, each row xx of XX is computed from the last entry to the first for LL (from the first to the last for UU): once xjx_j is known, xjx_j times the row jj of the triangular matrix is added to the unreduced sums of the remaining entries, each reduced once. Otherwise (a large triangular matrix and a few rows), each entry is computed with one dot product and one reduction, the columns of the triangular matrix being copied to rows 64 at a time so that the dot products read contiguous memory. The inverses of the diagonal entries are computed once.

Splits LL (or UU) into blocks of ⌊r/2⌋\lfloor r/2 \rfloor and ⌈r/2⌉\lceil r/2 \rceil rows and columns and solves recursively, reducing the work to matrix multiplications.

More

LU decomposition#

AlgorithmGaussian elimination and LU decompositionLU decomposition with row pivoting over Z/pZ\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 Z/nZ\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×nm \times n matrix AA modulo a prime, overwriting AA with LL and UU, and returns the rank rr. On return, row ii of LULU is row P[i] of the original AA, where P is an array of length mm (it need not be initialised). UU is in row echelon form with rr nonzero rows, and LL is m×rm \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 nn, and then returns 0 and leaves AA 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 nn, the indices of the rr pivot columns of UU in increasing order followed by the indices of the n−rn - r other columns in increasing order.

Full documentation

PLE decomposition and rank profiles#

AlgorithmGaussian elimination and LU decompositionLU decomposition with row pivoting over Z/pZ\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 Z/nZ\mathbb{Z}/n\mathbb{Z}.
slong nmod_mat_ple(slong * P, slong * pivots_nonpivots, nmod_mat_t A, int flags)
slong nmod_mat_ple_classical(slong * P, slong * pivots_nonpivots, nmod_mat_t A, int flags)
slong nmod_mat_ple_classical_delayed(slong * P, slong * pivots_nonpivots, nmod_mat_t A, int flags)
slong nmod_mat_ple_crout(slong * P, slong * pivots_nonpivots, nmod_mat_t A, int flags)
slong nmod_mat_ple_recursive(slong * P, slong * pivots_nonpivots, nmod_mat_t A, int flags)

Computes the PLE decomposition of the m×nm \times n matrix AA modulo a prime that reveals its rank profile matrix, overwrites AA with LL and EE in the storage of nmod_mat_lu, and returns the rank rr. Row ii of LELE is row P[i] of the original AA (P has length mm). The array pivots_nonpivots, of length nn, receives the pivot columns of EE followed by the other columns, both in increasing order; it may be NULL. The rows P[r], ..., P[m-1] are also in increasing order, and the rank profile matrix of AA has its nonzero entries at (P[k], pivots_nonpivots[k]) for k<rk < r. If flags contains NMOD_MAT_PLE_RANK_CHECK and the rank is less than min⁡(m,n)\min(m, n), the function returns 0, possibly before the end, and leaves A, P and pivots_nonpivots undefined.

Full documentation
void nmod_mat_ple_nullspace(nmod_mat_t X, const nmod_mat_t LU, const slong * pivots_nonpivots, slong rank)
void nmod_mat_ple_left_nullspace(nmod_mat_t X, const nmod_mat_t LU, const slong * P, slong rank)

Given the output LU, P, pivots_nonpivots and rank =r= r of nmod_mat_ple for an m×nm \times n matrix AA, sets the n×(n−r)n \times (n - r) matrix XX to the basis of the right nullspace {x:Ax=0}\{x : Ax = 0\} computed by nmod_mat_nullspace, respectively the (m−r)×m(m - r) \times m matrix XX to the basis of the left nullspace {x:xA=0}\{x : xA = 0\} computed by nmod_mat_left_nullspace. XX must have exactly these dimensions.

Full documentation
void nmod_mat_ple_nullspace_compact(nmod_mat_t X, const nmod_mat_t LU, const slong * pivots_nonpivots, slong rank)
void nmod_mat_ple_left_nullspace_compact(nmod_mat_t X, slong * rows, const nmod_mat_t LU, const slong * P, slong rank)

The same bases without their identity matrix. For the right nullspace, XX is r×(n−r)r \times (n - r) and receives CC: its row jj gives the entries in position pivots_nonpivots[j] and its column kk corresponds to the vector with a 1 in position pivots_nonpivots[r+k]. For the left nullspace, XX is (m−r)×r(m - r) \times r, rows (length mm) receives the row rank profile of AA in increasing order followed by the other rows in increasing order, and XX receives the columns of DD sorted accordingly: its column jj gives the entries in position rows[j] and its row kk corresponds to the vector with a 1 in position rows[r+k].

Full documentation

Flag for nmod_mat_ple: return 0 as soon as the rank is known to be less than min⁡(m,n)\min(m, n).

Full documentation

Solving linear systems#

These functions require a prime modulus.

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

Full documentation

Solves Ax=bAx = b for a square m×mm \times m matrix AA and vectors xx, bb of length mm, as nmod_mat_solve. xx may be equal to bb.

Full documentation

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

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 AA in *rank, the row permutation of the LU decomposition of AA in perm (length mm), and the indices of the pivot columns in the first *rank entries of pivots (length at least min⁡(m,n)\min(m, n)).

Full documentation

Determinant, rank and inverse#

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

Full documentation

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

Full documentation

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

Full documentation

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

Full documentation

Row echelon form and nullspace#

These functions require a prime modulus.

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

Full documentation

Sets the first dd columns of XX to a basis of the right nullspace {x:Ax=0}\{x : Ax = 0\} of the m×nm \times n matrix AA, sets the other entries of XX to zero, and returns the nullity d=n−rank⁡(A)d = n - \operatorname{rank}(A). XX must have nn rows and at least dd columns; n×nn \times n always suffices. XX may be aliased with AA. The basis is the one with an identity matrix in the rows of the columns of AA without pivot, computed with nmod_mat_ple and nmod_mat_ple_nullspace.

Full documentation

Sets the first dd rows of XX to a basis of the left nullspace {v:vA=0}\{v : vA = 0\} of the m×nm \times n matrix AA, sets the other entries of XX to zero, and returns the nullity d=m−rank⁡(A)d = m - \operatorname{rank}(A). XX must have at least dd rows and mm columns; m×mm \times m always suffices. The basis is the one with an identity matrix in the columns of the rows of AA that are not in its row rank profile, computed with nmod_mat_ple and nmod_mat_ple_left_nullspace.

Full documentation

Reduces row mm of MM against rows that are already reduced, for incremental Gaussian elimination, and returns the column of its new pivot, or −1-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 AA in strong echelon form, using the algorithm of [FieHof2014]. AA must have at least as many rows as columns; add zero rows otherwise.

More

Puts AA in Howell form [StoMul1998] and returns the number kk of nonzero rows, which come first. AA 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 Z/nZ\mathbb{Z}/n\mathbb{Z}, and the Krylov method with least common multiples that FLINT uses for the minimal polynomial.

Sets pp to the characteristic polynomial det⁡(xI−M)\det(xI - M) of the square matrix MM. An exception is thrown if MM 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=1n = 1 the result is the zero polynomial.

Full documentation

Sets pp to the minimal polynomial of the square matrix MM, the monic polynomial of least degree with p(M)=0p(M) = 0, and throws an exception if MM 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 jj such that the unit vector eje_j was used as a Krylov generator, and leaves the other entries of the array (of length rr) unchanged.

Full documentation

Replaces the square matrix MM by P−1MPP^{-1} M P, where PP is the identity matrix with the entries in row rr and every column j∉{r−1,r}j \notin \{r-1, r\} replaced by dd. Requires d<nd < 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 BB 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=ABD = AB if op is 0, D=C+ABD = C + AB if op is 1 and D=C−ABD = C - AB if op is −1-1, by the classical algorithm of nmod_mat_mul_classical. DD may be aliased with CC but not with AA or BB. CC 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=0k = 0 or the modulus is 1, DD is not written.

Sets B=cAB = cA with nmod_mul, respectively with n_mulmod_shoup and c_pr = n_mulmod_precomp_shoup(c, n), which requires n<2FLINT_BITS−1n < 2^{\mathtt{FLINT\_BITS} - 1}. Both require c<nc < 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+cBC = A + cB, as the two functions above. Both require c<nc < n.

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

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

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

Puts AA in reduced row echelon form and returns the rank rr, 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+1r + 1 coefficients of the characteristic polynomial of the r×rr \times r matrix MM 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:NN : 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-11-02).