429 lines
16 KiB
Plaintext
429 lines
16 KiB
Plaintext
|
/*=============================================================================
|
||
|
|
||
|
This file is part of FLINT.
|
||
|
|
||
|
FLINT is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
FLINT is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with FLINT; if not, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
|
||
|
=============================================================================*/
|
||
|
/******************************************************************************
|
||
|
|
||
|
Copyright (C) 2011 Fredrik Johansson
|
||
|
|
||
|
******************************************************************************/
|
||
|
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Memory management
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_init(fmpq_mat_t mat, slong rows, slong cols)
|
||
|
|
||
|
Initialises a matrix with the given number of rows and columns for use.
|
||
|
|
||
|
void fmpq_mat_clear(fmpq_mat_t mat)
|
||
|
|
||
|
Frees all memory associated with the matrix. The matrix must be
|
||
|
reinitialised if it is to be used again.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Entry access
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
MACRO fmpq_mat_entry(mat,i,j)
|
||
|
|
||
|
Gives a reference to the entry at row \code{i} and column \code{j}.
|
||
|
The reference can be passed as an input or output variable to any
|
||
|
\code{fmpq} function for direct manipulation of the matrix element.
|
||
|
No bounds checking is performed.
|
||
|
|
||
|
MACRO fmpq_mat_entry_num(mat,i,j)
|
||
|
|
||
|
Gives a reference to the numerator of the entry at row \code{i} and
|
||
|
column \code{j}. The reference can be passed as an input or output
|
||
|
variable to any \code{fmpz} function for direct manipulation of the
|
||
|
matrix element. No bounds checking is performed.
|
||
|
|
||
|
MACRO fmpq_mat_entry_den(mat,i,j)
|
||
|
|
||
|
Gives a reference to the denominator of the entry at row \code{i} and
|
||
|
column \code{j}. The reference can be passed as an input or output
|
||
|
variable to any \code{fmpz} function for direct manipulation of the
|
||
|
matrix element. No bounds checking is performed.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Basic assignment
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_set(fmpq_mat_t dest, const fmpq_mat_t src)
|
||
|
|
||
|
Sets the entries in \code{dest} to the same values as in \code{src},
|
||
|
assuming the two matrices have the same dimensions.
|
||
|
|
||
|
void fmpq_mat_zero(fmpq_mat_t mat)
|
||
|
|
||
|
Sets \code{mat} to the zero matrix.
|
||
|
|
||
|
void fmpq_mat_one(fmpq_mat_t mat)
|
||
|
|
||
|
Let $m$ be the minimum of the number of rows and columns
|
||
|
in the matrix \code{mat}. This function sets the first
|
||
|
$m \times m$ block to the identity matrix, and the remaining
|
||
|
block to zero.
|
||
|
|
||
|
void fmpq_mat_transpose(fmpq_mat_t rop, const fmpq_mat_t op)
|
||
|
|
||
|
Sets the matrix \code{rop} to the tranpose of the matrix \code{op},
|
||
|
assuming that their dimensios are compatible.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Addition, scalar multiplication
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_add(fmpq_mat_t mat,
|
||
|
const fmpq_mat_t mat1, const fmpq_mat_t mat2)
|
||
|
|
||
|
Sets \code{mat} to the sum of \code{mat1} and \code{mat2},
|
||
|
assuming that all three matrices have the same dimensions.
|
||
|
|
||
|
void fmpq_mat_sub(fmpq_mat_t mat,
|
||
|
const fmpq_mat_t mat1, const fmpq_mat_t mat2)
|
||
|
|
||
|
Sets \code{mat} to the difference of \code{mat1} and \code{mat2},
|
||
|
assuming that all three matrices have the same dimensions.
|
||
|
|
||
|
void fmpq_mat_neg(fmpq_mat_t rop, const fmpq_mat_t op)
|
||
|
|
||
|
Sets \code{rop} to the negative of \code{op}, assuming that
|
||
|
the two matrices have the same dimensions.
|
||
|
|
||
|
void fmpq_mat_scalar_mul_fmpz(fmpq_mat_t rop,
|
||
|
const fmpq_mat_t op, const fmpz_t x)
|
||
|
|
||
|
Sets \code{rop} to \code{op} multiplied by the integer $x$,
|
||
|
assuming that the two matrices have the same dimensions.
|
||
|
|
||
|
Note that the integer $x$ may not be aliased with any part of
|
||
|
the entries of \code{rop}.
|
||
|
|
||
|
void fmpq_mat_scalar_div_fmpz(fmpq_mat_t rop,
|
||
|
const fmpq_mat_t op, const fmpz_t x)
|
||
|
|
||
|
Sets \code{rop} to \code{op} divided by the integer $x$,
|
||
|
assuming that the two matrices have the same dimensions
|
||
|
and that $x$ is non-zero.
|
||
|
|
||
|
Note that the integer $x$ may not be aliased with any part of
|
||
|
the entries of \code{rop}.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Input and output
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_print(const fmpq_mat_t mat)
|
||
|
|
||
|
Prints the matrix \code{mat} to standard output.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Random matrix generation
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_randbits(fmpq_mat_t mat, flint_rand_t state, mp_bitcnt_t bits)
|
||
|
|
||
|
This is equivalent to applying \code{fmpq_randbits} to all entries
|
||
|
in the matrix.
|
||
|
|
||
|
void fmpq_mat_randtest(fmpq_mat_t mat, flint_rand_t state, mp_bitcnt_t bits)
|
||
|
|
||
|
This is equivalent to applying \code{fmpq_randtest} to all entries
|
||
|
in the matrix.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Special matrices
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_hilbert_matrix(fmpq_mat_t mat)
|
||
|
|
||
|
Sets \code{mat} to a Hilbert matrix of the given size. That is,
|
||
|
the entry at row $i$ and column $j$ is set to $1/(i+j+1)$.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Basic comparison and properties
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
int fmpq_mat_equal(const fmpq_mat_t mat1, const fmpq_mat_t mat2)
|
||
|
|
||
|
Returns nonzero if \code{mat1} and \code{mat2} have the same shape and
|
||
|
all their entries agree, and returns zero otherwise. Assumes the
|
||
|
entries in both \code{mat1} and \code{mat2} are in canonical form.
|
||
|
|
||
|
int fmpq_mat_is_integral(const fmpq_mat_t mat)
|
||
|
|
||
|
Returns nonzero if all entries in \code{mat} are integer-valued, and
|
||
|
returns zero otherwise. Assumes that the entries in \code{mat}
|
||
|
are in canonical form.
|
||
|
|
||
|
int fmpq_mat_is_zero(const fmpq_mat_t mat)
|
||
|
|
||
|
Returns nonzero if all entries in \code{mat} are zero, and returns
|
||
|
zero otherwise.
|
||
|
|
||
|
int fmpq_mat_is_empty(const fmpq_mat_t mat)
|
||
|
|
||
|
Returns a non-zero value if the number of rows or the number of
|
||
|
columns in \code{mat} is zero, and otherwise returns
|
||
|
zero.
|
||
|
|
||
|
int fmpq_mat_is_square(const fmpq_mat_t mat)
|
||
|
|
||
|
Returns a non-zero value if the number of rows is equal to the
|
||
|
number of columns in \code{mat}, and otherwise returns zero.
|
||
|
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Integer matrix conversion
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
int fmpq_mat_get_fmpz_mat(fmpz_mat_t dest, const fmpq_mat_t mat)
|
||
|
|
||
|
Sets \code{dest} to \code{mat} and returns nonzero if all entries
|
||
|
in \code{mat} are integer-valued. If not all entries in \code{mat}
|
||
|
are integer-valued, sets \code{dest} to an undefined matrix
|
||
|
and returns zero. Assumes that the entries in \code{mat} are
|
||
|
in canonical form.
|
||
|
|
||
|
void fmpq_mat_get_fmpz_mat_entrywise(fmpz_mat_t num, fmpz_mat_t den,
|
||
|
const fmpq_mat_t mat)
|
||
|
|
||
|
Sets the integer matrices \code{num} and \code{den} respectively
|
||
|
to the numerators and denominators of the entries in \code{mat}.
|
||
|
|
||
|
void fmpq_mat_get_fmpz_mat_matwise(fmpz_mat_t num, fmpz_t den,
|
||
|
const fmpq_mat_t mat)
|
||
|
|
||
|
Converts all entries in \code{mat} to a common denominator,
|
||
|
storing the rescaled numerators in \code{num} and the
|
||
|
denominator in \code{den}. The denominator will be minimal
|
||
|
if the entries in \code{mat} are in canonical form.
|
||
|
|
||
|
void fmpq_mat_get_fmpz_mat_rowwise(fmpz_mat_t num, fmpz * den,
|
||
|
const fmpq_mat_t mat)
|
||
|
|
||
|
Clears denominators in \code{mat} row by row. The rescaled
|
||
|
numerators are written to \code{num}, and the denominator
|
||
|
of row \code{i} is written to position \code{i} in \code{den}
|
||
|
which can be a preinitialised \code{fmpz} vector. Alternatively,
|
||
|
\code{NULL} can be passed as the \code{den} variable, in which
|
||
|
case the denominators will not be stored.
|
||
|
|
||
|
void fmpq_mat_get_fmpz_mat_rowwise_2(fmpz_mat_t num, fmpz_mat_t num2,
|
||
|
fmpz * den, const fmpq_mat_t mat, const fmpq_mat_t mat2)
|
||
|
|
||
|
Clears denominators row by row of both \code{mat} and \code{mat2},
|
||
|
writing the respective numerators to \code{num} and \code{num2}.
|
||
|
This is equivalent to concatenating \code{mat} and \code{mat2}
|
||
|
horizontally, calling \code{fmpq_mat_get_fmpz_mat_rowwise},
|
||
|
and extracting the two submatrices in the result.
|
||
|
|
||
|
void fmpq_mat_get_fmpz_mat_colwise(fmpz_mat_t num, fmpz * den,
|
||
|
const fmpq_mat_t mat)
|
||
|
|
||
|
Clears denominators in \code{mat} column by column. The rescaled
|
||
|
numerators are written to \code{num}, and the denominator
|
||
|
of column \code{i} is written to position \code{i} in \code{den}
|
||
|
which can be a preinitialised \code{fmpz} vector. Alternatively,
|
||
|
\code{NULL} can be passed as the \code{den} variable, in which
|
||
|
case the denominators will not be stored.
|
||
|
|
||
|
void fmpq_mat_set_fmpz_mat(fmpq_mat_t dest, const fmpz_mat_t src)
|
||
|
|
||
|
Sets \code{dest} to \code{src}.
|
||
|
|
||
|
void fmpq_mat_set_fmpz_mat_div_fmpz(fmpq_mat_t mat, const fmpz_mat_t num,
|
||
|
const fmpz_t den)
|
||
|
|
||
|
Sets \code{mat} to the integer matrix \code{num} divided by the
|
||
|
common denominator \code{den}.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Modular reduction and rational reconstruction
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_get_fmpz_mat_mod_fmpz(fmpz_mat_t dest, const fmpq_mat_t mat,
|
||
|
const fmpz_t mod)
|
||
|
|
||
|
Sets each entry in \code{dest} to the corresponding entry in \code{mat},
|
||
|
reduced modulo \code{mod}.
|
||
|
|
||
|
int fmpq_mat_set_fmpz_mat_mod_fmpz(fmpq_mat_t X, const fmpz_mat_t Xmod,
|
||
|
const fmpz_t mod)
|
||
|
|
||
|
Set \code{X} to the entrywise rational reconstruction integer matrix
|
||
|
\code{Xmod} modulo \code{mod}, and returns nonzero if the reconstruction
|
||
|
is successful. If rational reconstruction fails for any element,
|
||
|
returns zero and sets the entries in \code{X} to undefined values.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Matrix multiplication
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_mul_direct(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B)
|
||
|
|
||
|
Sets \code{C} to the matrix product \code{AB}, computed
|
||
|
naively using rational arithmetic. This is typically very slow and
|
||
|
should only be used in circumstances where clearing denominators
|
||
|
would consume too much memory.
|
||
|
|
||
|
void fmpq_mat_mul_cleared(fmpq_mat_t C, const fmpq_mat_t A,
|
||
|
const fmpq_mat_t B)
|
||
|
|
||
|
Sets \code{C} to the matrix product \code{AB}, computed
|
||
|
by clearing denominators and multiplying over the integers.
|
||
|
|
||
|
void fmpq_mat_mul(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B)
|
||
|
|
||
|
Sets \code{C} to the matrix product \code{AB}. This
|
||
|
simply calls \code{fmpq_mat_mul_cleared}.
|
||
|
|
||
|
void fmpq_mat_mul_fmpz_mat(fmpq_mat_t C, const fmpq_mat_t A,
|
||
|
const fmpz_mat_t B)
|
||
|
|
||
|
Sets \code{C} to the matrix product \code{AB}, with \code{B}
|
||
|
an integer matrix. This function works efficiently by clearing
|
||
|
denominators of \code{A}.
|
||
|
|
||
|
void fmpq_mat_mul_r_fmpz_mat(fmpq_mat_t C, const fmpz_mat_t A,
|
||
|
const fmpq_mat_t B)
|
||
|
|
||
|
Sets \code{C} to the matrix product \code{AB}, with \code{A}
|
||
|
an integer matrix. This function works efficiently by clearing
|
||
|
denominators of \code{B}.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Trace
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_trace(fmpq_t trace, const fmpq_mat_t mat)
|
||
|
|
||
|
Computes the trace of the matrix, i.e. the sum of the entries on
|
||
|
the main diagonal. The matrix is required to be square.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Determinant
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
void fmpq_mat_det(fmpq_t det, const fmpq_mat_t mat)
|
||
|
|
||
|
Sets \code{det} to the determinant of \code{mat}. In the general case,
|
||
|
the determinant is computed by clearing denominators and computing a
|
||
|
determinant over the integers. Matrices of size 0, 1 or 2 are handled
|
||
|
directly.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Nonsingular solving
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
int fmpq_mat_solve_fraction_free(fmpq_mat_t X, const fmpq_mat_t A,
|
||
|
const fmpq_mat_t B)
|
||
|
|
||
|
Solves \code{AX = B} for nonsingular \code{A} by clearing denominators
|
||
|
and solving the rescaled system over the integers using a fraction-free
|
||
|
algorithm. This is usually the fastest algorithm for small systems.
|
||
|
Returns nonzero if \code{X} is nonsingular or if the right hand side
|
||
|
is empty, and zero otherwise.
|
||
|
|
||
|
int fmpq_mat_solve_dixon(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B)
|
||
|
|
||
|
Solves \code{AX = B} for nonsingular \code{A} by clearing denominators
|
||
|
and solving the rescaled system over the integers using Dixon's algorithm.
|
||
|
The rational solution matrix is generated using rational reconstruction.
|
||
|
This is usually the fastest algorithm for large systems.
|
||
|
Returns nonzero if \code{X} is nonsingular or if the right hand side
|
||
|
is empty, and zero otherwise.
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Inverse
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
int fmpq_mat_inv(fmpq_mat_t B, const fmpq_mat_t A)
|
||
|
|
||
|
Sets \code{B} to the inverse matrix of \code{A} and returns nonzero.
|
||
|
Returns zero if \code{A} is singular. \code{A} must be a square matrix.
|
||
|
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
Echelon form
|
||
|
|
||
|
*******************************************************************************
|
||
|
|
||
|
int fmpq_mat_pivot(slong * perm, fmpq_mat_t mat, slong r, slong c)
|
||
|
|
||
|
Helper function for row reduction. Returns 1 if the entry of \code{mat}
|
||
|
at row $r$ and column $c$ is nonzero. Otherwise searches for a nonzero
|
||
|
entry in the same column among rows $r+1, r+2, \ldots$. If a nonzero
|
||
|
entry is found at row $s$, swaps rows $r$ and $s$ and the corresponding
|
||
|
entries in \code{perm} (unless \code{NULL}) and returns -1. If no
|
||
|
nonzero pivot entry is found, leaves the inputs unchanged and returns 0.
|
||
|
|
||
|
slong fmpq_mat_rref_classical(fmpq_mat_t B, const fmpq_mat_t A)
|
||
|
|
||
|
Sets \code{B} to the reduced row echelon form of \code{A} and returns
|
||
|
the rank. Performs Gauss-Jordan elimination directly over the rational
|
||
|
numbers. This algorithm is usually inefficient and is mainly intended
|
||
|
to be used for testing purposes.
|
||
|
|
||
|
slong fmpq_mat_rref_fraction_free(fmpq_mat_t B, const fmpq_mat_t A)
|
||
|
|
||
|
Sets \code{B} to the reduced row echelon form of \code{A} and returns
|
||
|
the rank. Clears denominators and performs fraction-free Gauss-Jordan
|
||
|
elimination using \code{fmpz_mat} functions.
|
||
|
|
||
|
slong fmpq_mat_rref(fmpq_mat_t B, const fmpq_mat_t A)
|
||
|
|
||
|
Sets \code{B} to the reduced row echelon form of \code{A} and returns
|
||
|
the rank. This function automatically chooses between the classical and
|
||
|
fraction-free algorithms depending on the size of the matrix.
|
||
|
|