3#ifndef _mat_linalg_hpp_
4#define _mat_linalg_hpp_
67#define DMatZZpFFPACK DMat<ZZpFFPACK>
97#include <M2/gc-include.h>
99#pragma GCC diagnostic push
100#pragma GCC diagnostic ignored "-Wconversion"
101#include <flint/flint.h>
102#include <flint/fmpq_mat.h>
103#include <flint/fmpz.h>
104#include <flint/fmpz_mat.h>
105#include <flint/fq_nmod_mat.h>
106#include <flint/nmod_mat.h>
107#pragma GCC diagnostic pop
118template <
typename Mat>
123 "'rank' not implemented for this kind of matrix over this ring");
132template <
typename Mat>
133void determinant(
const Mat& A,
typename Mat::ElementType& result_det)
138 "'determinant' not implemented for this kind of matrix over this ring");
155template <
typename Mat>
161 "'invert' not implemented for this kind of matrix over this ring");
173template <
typename Mat>
179 "'rowReducedEchelonForm' not implemented for this kind of matrix over "
196template <
typename Mat>
197void mult(
const Mat& A,
const Mat& B, Mat& result_product)
201 (void) result_product;
203 "'mult matrices' not implemented for this kind of matrix over this ring");
219template <
typename Mat>
223 (void) result_nullspace;
225 "'nullSpace' not implemented for this kind of matrix over this ring");
229template <
typename Mat>
236 "'solveLinear' not implemented for this kind of matrix over this ring");
244template <
typename Mat>
251 "'solveInvertible' not implemented for this kind of matrix over this "
267template <
typename Mat>
273 "'rankProfile' not implemented for this kind of matrix over this ring");
281template <
typename Mat>
289 "'addMultipleTo' not implemented for this kind of matrix over this ring");
297template <
typename Mat>
305 "'subtractMultipleTo' not implemented for this kind of matrix over this "
309template <
typename Mat>
316 "'LU' not implemented for this kind of matrix over this ring");
319template <
typename Mat>
327 "'LUincremental' not implemented for this kind of matrix over this ring");
330template <
typename Mat>
338 "'triangularSolve' not implemented for this kind of matrix over this "
342template <
typename Mat,
typename Mat2>
348 "'eigenvalues' not implemented for this kind of matrix over this ring");
351template <
typename Mat,
typename Mat2>
357 "'eigenvalues' not implemented for this kind of matrix over this ring");
360template <
typename Mat,
typename Mat2,
typename Mat3>
367 "'eigenvectors' not implemented for this kind of matrix over this ring");
370template <
typename Mat,
typename Mat2,
typename Mat3>
377 "'eigenvectors' not implemented for this kind of matrix over this ring");
380template <
typename Mat>
381bool leastSquares(
const Mat& A,
const Mat& B, Mat& X,
bool assume_full_rank)
386 (void) assume_full_rank;
388 "'leastSquares' not implemented for this kind of matrix over this ring");
391template <
typename Mat,
typename Mat2>
392bool SVD(
const Mat& A, Mat2& Sigma, Mat& U, Mat& Vt,
int strategy)
400 "'SVD' not implemented for this kind of matrix over this ring");
403template <
typename Mat,
typename Mat2,
typename Mat3>
404bool QR(
const Mat& A, Mat2& Q, Mat3& R,
bool return_QR)
411 "'QR' not implemented for this kind of matrix over this ring");
420 "'clean' not implemented for this kind of matrix over this ring");
429 "'norm' not implemented for this kind of matrix over this ring");
436template <
typename RT>
444 typename RT::Element tmp(A.
ring());
445 for (
size_t i = 0; i < A.
numRows(); i++)
448 auto& val = result_product.
entry(i,j);
452 A.
ring().add(val, val, tmp);
457template <
typename RT>
464template <
typename RT>
472 typename RT::Element tmp(A.
ring());
473 for (
size_t i = 0; i < A.
numRows(); i++)
476 auto& val = C.
entry(i,j);
480 A.
ring().subtract(val, val, tmp);
487template <
typename RT>
494template <
typename RT>
497 std::vector<size_t> perm;
511template <
typename RT>
523 for (
size_t i = 0; i < m; i++)
525 auto& a =
x.entry(i, 0);
526 x.ring().divide(a, Lv.
entry(i, m), Lv.
entry(i, i));
527 x.ring().negate(a, a);
529 x.ring().negate(a, a);
534 for (
size_t i = 0; i < m; i++)
536 auto& a =
x.entry(i, 0);
537 x.ring().negate(a, Lv.
entry(i, m));
539 x.ring().negate(a, a);
544 for (
size_t i = 1; i < m + 1; i++)
546 auto& a =
x.entry(m - i, 0);
547 x.ring().divide(a, Lv.
entry(m - i, m), Lv.
entry(m - i, m - i));
548 x.ring().negate(a, a);
550 x.ring().negate(a, a);
555 for (
size_t i = 1; i < m + 1; i++)
557 auto& a =
x.entry(m - i, 0);
558 x.ring().negate(a, Lv.
entry(m - i, m));
560 x.ring().negate(a, a);
566template <
typename RT>
569 size_t n =
LU.numRows();
573 for (
size_t j = 0; j < n; j++)
574 LU.ring().set(
LU.entry(j, m), v.
entry(P[j], 0));
581 for (
size_t i = 0; i < m; i++)
582 LU.ring().set(
LU.entry(i, m),
x.entry(i, 0));
585 int pivotPosition = -1;
587 for (
size_t j = m; j < n; j++)
588 if (!
LU.ring().is_zero(
LU.entry(j, m)))
601 for (
int j = m + 1; j < n; j++)
602 LU.ring().divide(
LU.entry(j, m),
LU.entry(j, m),
LU.entry(m, m));
607template <
typename RT>
611 return LUdecomp.
rank();
614template <
typename RT>
617 std::vector<size_t> profile;
635template <
typename RT>
639 return LUdecomp.
inverse(result_inv);
642template <
typename RT>
646 return LUdecomp.
kernel(result_nullspace);
649template <
typename RT>
653 return LUdecomp.
solve(B, X);
656template <
typename RT>
689 "'LU' not implemented for this kind of matrix over this ring");
697 "'rankProfile' not implemented for this kind of matrix over this ring");
705 "'invert' not implemented for this kind of matrix over this ring");
711 (void) result_nullspace;
713 "'nullSpace' not implemented for this kind of matrix over this ring");
722 "'solveLinear' not implemented for this kind of matrix over this ring");
733 "'solveInvertible' not implemented for this kind of matrix over this "
747 result1.
toDMat(result_product);
783 return fmpz_mat_rank(A1.
value());
792 fmpz_mat_det(det, A1.
value());
793 fmpz_get_mpz(&result_det, det);
808 fmpz_mat_det(&result_det, A.
fmpz_mat());
813 M2::ARingZZ::Element den(A.
ring());
815 if (!fmpz_is_pm1(&den.value()))
result =
false;
829 long nullity = fmpz_mat_nullspace(result_nullspace.
fmpz_mat(), A.
fmpz_mat());
835 M2::ARingZZ::Element den(A.
ring());
837 if (!fmpz_is_pm1(&den.value()))
result =
false;
846 "'rankProfile' not implemented for this kind of matrix over this ring");
905 result_rref.
swap(A1);
965#if __FLINT_RELEASE >= 30100
970 result_rref.
swap(A1);
1030#if __FLINT_RELEASE >= 30100
1035 result_rref.
swap(A1);
1051 result1.
toDMat(result_product);
1103 fmpq_mat_get_fmpz_mat_rowwise(m1,
nullptr, A.
fmpq_mat());
1105 size_t rk = fmpz_mat_rank(m1);
1113 fmpq_mat_det(&result_det, A.
fmpq_mat());
1133 fmpq_mat_get_fmpz_mat_rowwise(m1,
nullptr, A.
fmpq_mat());
1135 size_t nullity = fmpz_mat_nullspace(m2, m1);
1138 for (
size_t c = 0; c < nullity; c++)
1140 fmpz_set(fmpq_numref(&result_nullspace.
entry(r, c)),
1141 fmpz_mat_entry(m2, r, c));
1168 "'rankProfile' not implemented for this kind of matrix over this ring");
1243 bool assume_full_rank)
1246 if (assume_full_rank)
1285 for (
size_t r = 0; r < mat.
numRows(); ++r)
1286 for (
size_t c = 0; c < mat.
numColumns(); ++c)
1294 for (
size_t r = 0; r < mat.
numRows(); ++r)
1295 for (
size_t c = 0; c < mat.
numColumns(); ++c)
1345 bool assume_full_rank)
1348 if (assume_full_rank)
1374 for (
size_t r = 0; r < mat.
numRows(); ++r)
1375 for (
size_t c = 0; c < mat.
numColumns(); ++c)
1383 for (
size_t r = 0; r < mat.
numRows(); ++r)
1384 for (
size_t c = 0; c < mat.
numColumns(); ++c)
1421 bool assume_full_rank)
1423 (void) assume_full_rank;
1439 for (
size_t r = 0; r < mat.
numRows(); ++r)
1440 for (
size_t c = 0; c < mat.
numColumns(); ++c)
1448 for (
size_t r = 0; r < mat.
numRows(); ++r)
1449 for (
size_t c = 0; c < mat.
numColumns(); ++c)
1486 bool assume_full_rank)
1488 (void) assume_full_rank;
1504 for (
size_t r = 0; r < mat.
numRows(); ++r)
1505 for (
size_t c = 0; c < mat.
numColumns(); ++c)
1513 for (
size_t r = 0; r < mat.
numRows(); ++r)
1514 for (
size_t c = 0; c < mat.
numColumns(); ++c)
M2::ARingCC — machine-precision complex numbers (pair of doubles).
M2::ARingCCC — arbitrary-precision complex numbers (pair of MPFR floats).
M2::ARingRR — machine-precision real numbers (IEEE 754 double).
M2::ARingRRR — arbitrary-precision real numbers backed by MPFR.
M2::ARingGFFlintBig — arbitrary-degree GF(p^k) via FLINT fq_nmod.
M2::ARingGFFlint — small GF(p^k) via FLINT Zech-logarithm tables.
M2::ARingGFM2 — native engine Galois field, no FLINT dependency.
Tiny dispatcher header that picks the default ARingQQ from among the QQ aring implementations.
M2::ARingZZ — FLINT-backed arbitrary-precision integers with small-value inlining.
M2::ARingZZGMP — aring integer ring backed straight by GMP mpz_t.
M2::ARingZZpFFPACK — Z/p via FFLAS-FFPACK's Givaro::Modular<double> field.
M2::ARingZZpFlint — Z/p via FLINT's nmod_t precomputed-reciprocal reduction.
M2::ARingZZp — portable Z/p for small primes via log / exp tables.
const fq_zech_mat_t & fq_zech_mat() const
const ACoeffRing & ring() const
void swap(DMat< ACoeffRing > &M)
size_t numColumns() const
const ACoeffRing & ring() const
size_t numColumns() const
const fq_nmod_mat_t & fq_nmod_mat() const
void swap(DMat< ACoeffRing > &M)
const ACoeffRing & ring() const
void resize(size_t new_nrows, size_t new_ncols)
ElementType & entry(size_t row, size_t column)
size_t numColumns() const
const fmpq_mat_t & fmpq_mat() const
const ACoeffRing & ring() const
size_t numColumns() const
const fmpz_mat_t & fmpz_mat() const
void swap(DMat< ACoeffRing > &M)
size_t numColumns() const
const ACoeffRing & ring() const
const nmod_mat_t & nmod_mat() const
ElementType & entry(size_t row, size_t column)
const ACoeffRing & ring() const
size_t numColumns() const
size_t rank()
Output: returns the approximate rank of A (-1 if fails).
void determinant(ElementType &result)
Output: result, the determinant of A.
bool solveInvertible(const Mat &B, Mat &X)
bool matrixPLU(std::vector< size_t > &P, Mat &L, Mat &U)
bool solve(const Mat &B, Mat &X)
void columnRankProfile(std::vector< size_t > &profile)
fmpq_mat_struct * value()
void toDMat(DMatQQ &result)
RAII wrapper around FLINT's fmpq_mat_t for translating dense QQ-coefficient matrices between the engi...
void toDMat(DMatZZGMP &result)
fmpz_mat_struct * value()
RAII wrapper around FLINT's fmpz_mat_t for translating dense ZZ-coefficient matrices between the engi...
static bool least_squares_deficient(const DMatRRR *A, const DMatRRR *b, DMatRRR *x)
static bool SVD_divide_conquer(const DMatRRR *A, DMatRRR *Sigma, DMatRRR *U, DMatRRR *VT)
static bool eigenvectors_symmetric(const DMatRRR *A, DMatRRR *eigenvals, DMatRRR *eigenvecs)
static bool eigenvalues_hermitian(const DMatCCC *A, DMatRRR *eigenvals)
static bool SVD(const DMatRRR *A, DMatRRR *Sigma, DMatRRR *U, DMatRRR *VT)
static bool QR(const DMatRR *A, DMatRR *Q, DMatRR *R, bool return_QR)
static bool eigenvalues_symmetric(const DMatRRR *A, DMatRRR *eigenvals)
static bool eigenvectors_hermitian(const DMatCCC *A, DMatRRR *eigenvals, DMatCCC *eigenvecs)
static bool least_squares(const DMatRRR *A, const DMatRRR *b, DMatRRR *x)
static bool eigenvectors(const DMatRRR *A, DMatCCC *eigenvals, DMatCCC *eigenvecs)
static bool eigenvalues(const DMatRRR *A, DMatCCC *eigenvals)
void zeroize_tiny(gmp_RR epsilon, ElementType &a) const
void increase_norm(gmp_RRmutable norm, const ElementType &a) const
void increase_norm(gmp_RRmutable norm, const ElementType &a) const
void zeroize_tiny(gmp_RR epsilon, ElementType &a) const
const fq_zech_ctx_struct * flintContext() const
const fq_nmod_ctx_struct * flintContext() const
void increase_norm(mpfr_ptr norm, const ElementType &a) const
void zeroize_tiny(gmp_RR epsilon, ElementType &a) const
void increase_norm(gmp_RRmutable norm, const ElementType &a) const
void zeroize_tiny(gmp_RR epsilon, ElementType &a) const
wrapper for the FFPACK::ModularBalanced<double> field implementation
DMat< M2::ARingGFFlintBig > DMatGFFlintBig
Umbrella header for DMat<R> LU — declares DMatLinAlg<RingType> and pulls in every back-end variant.
Translation bridge that lets GMP-backed DMat<ARingQQ> borrow FLINT matrix arithmetic.
DMat<ACoeffRing> — dense-matrix template plus the umbrella that wires in every per-ring specialisatio...
EigenM2 namespace — Eigen3-backed SVD / eigenvalues / eigenvectors / least-squares for DMat<R> over R...
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
DMat< M2::ARingZZp > DMatZZp
DMat< M2::ARingCCC > DMatCCC
DMat< M2::ARingCC > DMatCC
DMat< M2::ARingRRR > DMatRRR
DMat< M2::ARingRR > DMatRR
Engine bridge into LAPACK for RR / CC dense linear algebra.
VALGRIND_MAKE_MEM_DEFINED & result(result)
M2_arrayint M2_arrayintOrNull
Templated matrix arithmetic for DMat<R> / SMat<R> plus the MatrixWindow / SubMatrix view types.
M2::ARingZZpFFPACK ZZpFFPACK
DMat< M2::ARingZZGMP > DMatZZGMP
DMat< M2::ARingZZ > DMatZZ
DMat< M2::ARingGFFlint > DMatGFFlint
DMat< M2::ARingZZpFlint > DMatZZpFlint
DMat< M2::ARingQQ > DMatQQ
DMat< M2::ARingQQFlint > DMatQQFlint
DMat< M2::ARingGFM2 > DMatGFM2
bool SVD(const LMatrixRRR *A, LMatrixRRR *Sigma, LMatrixRRR *U, LMatrixRRR *VT)
bool least_squares(const LMatrixRRR *A, const LMatrixRRR *B, LMatrixRRR *X)
bool eigenvectors(const LMatrixRRR *A, LMatrixCCC *eigenvals, LMatrixCCC *eigenvecs)
bool eigenvectors_hermitian(const LMatrixRRR *A, LMatrixRRR *eigenvals, LMatrixRRR *eigenvecs)
bool SVD_divide_conquer(const LMatrixRRR *A, LMatrixRRR *Sigma, LMatrixRRR *U, LMatrixRRR *VT)
bool eigenvalues(const LMatrixRRR *A, LMatrixCCC *eigenvals)
bool eigenvalues_hermitian(const LMatrixRRR *A, LMatrixRRR *eigenvals)
bool QR(const Mat &A, Mat2 &Q, Mat3 &R, bool return_QR)
bool inverse(const Mat &A, Mat &result_inv)
the inverse of a square matrix
void determinant(const Mat &A, typename Mat::ElementType &result_det)
the determinant of a square matrix
bool eigenvaluesHermitian(const Mat &A, Mat2 &eigenvals)
size_t rowReducedEchelonForm(const Mat &A, Mat &result_rref)
the row reduced echelon form of a matrix over a field, or ZZ.
bool eigenvalues(const Mat &A, Mat2 &eigenvals)
M2_arrayintOrNull LUincremental(std::vector< size_t > &P, Mat &LU, const Mat &v, int i)
bool eigenvectors(const Mat &A, Mat2 &eigenvals, Mat3 &eigenvecs)
void subtractMultipleTo(DMatZZpFFPACK &C, const DMatZZpFFPACK &A, const DMatZZpFFPACK &B)
size_t rank(const Mat &A)
the rank of a matrix
void addMultipleTo(DMatZZpFFPACK &C, const DMatZZpFFPACK::ElementType &a, const DMatZZpFFPACK &A, const DMatZZpFFPACK &B)
M2_arrayintOrNull LU(const Mat &A, Mat &L, Mat &U)
bool SVD(const Mat &A, Mat2 &Sigma, Mat &U, Mat &Vt, int strategy)
size_t nullSpace(const Mat &A, Mat &result_nullspace)
the null space of a matrix
void mult(const DMatZZpFFPACK &A, const DMatZZpFFPACK &B, DMatZZpFFPACK &C)
void clean(gmp_RR epsilon, T &mat)
bool solveLinear(const Mat &A, const Mat &B, Mat &X)
solve AX=B, return true if the system has a solution.
bool leastSquares(const Mat &A, const Mat &B, Mat &X, bool assume_full_rank)
bool solveInvertible(const Mat &A, const Mat &B, Mat &X)
solve AX=B, where A is a square (invertible) matrix.
void increase_norm(gmp_RRmutable nm, const T &mat)
void transpose(const DMat< RT > &A, DMat< RT > &result)
M2_arrayintOrNull rankProfile(const Mat &A, bool row_profile)
Returns either the row or column rank profile of A.
bool eigenvectorsHermitian(const Mat &A, Mat2 &eigenvals, Mat3 &eigenvecs)
void triangularSolve(Mat &Lv, Mat &x, int m, int strategy)
void swap(mpfr::mpreal &x, mpfr::mpreal &y)
M2_arrayint stdvector_to_M2_arrayint(const std::vector< T > &v)
Conversion helpers between M2 boundary types and standard C++ containers.