Macaulay2 Engine
Loading...
Searching...
No Matches
mat-linalg.hpp
Go to the documentation of this file.
1// Copyright 2013 Michael E. Stillman
2
3#ifndef _mat_linalg_hpp_
4#define _mat_linalg_hpp_
5
46
47
51
52#include "util.hpp"
53#include "exceptions.hpp"
54#include "dmat.hpp"
55
56#include "aring-RR.hpp"
57#include "aring-CC.hpp"
58#include "aring-RRR.hpp"
59#include "aring-CCC.hpp"
60#include "aring-zzp.hpp"
61#include "aring-m2-gf.hpp"
64
65#include "aring-zzp-ffpack.hpp"
67#define DMatZZpFFPACK DMat<ZZpFFPACK>
68
69#include "aring-zz-gmp.hpp"
70#include "aring-qq.hpp"
71#include "aring-zz-flint.hpp"
72#include "aring-zzp-flint.hpp"
74#include "aring-gf-flint.hpp"
75
77typedef DMat<M2::ARingZZ> DMatZZ; // flint
83
88
89#include "lapack.hpp"
90#include "mat-arith.hpp"
91#include "dmat-lu.hpp"
93
94#include "eigen.hpp"
95
96// The following needs to be included before any flint files are included.
97#include <M2/gc-include.h>
98
99#pragma GCC diagnostic push
100#pragma GCC diagnostic ignored "-Wconversion"
101#include <flint/flint.h> // for fmpq_numref, fmpz_t
102#include <flint/fmpq_mat.h> // for fmpq_mat_mul, fmpq_mat_add
103#include <flint/fmpz.h> // for fmpz_is_pm1, fmpz_clear, fmpz...
104#include <flint/fmpz_mat.h> // for fmpz_mat_t, fmpz_mat_mul, fmpz_mat_clear
105#include <flint/fq_nmod_mat.h> // for fq_nmod_mat_mul, fq_zech_mat_mul
106#include <flint/nmod_mat.h> // for nmod_mat_mul, nmod_mat_add
107#pragma GCC diagnostic pop
108
109#include <iostream>
110#include <algorithm>
111
112namespace MatrixOps {
118template <typename Mat>
119size_t rank(const Mat& A)
120{
121 (void) A;
122 throw exc::engine_error(
123 "'rank' not implemented for this kind of matrix over this ring");
124 return 0;
125}
126
132template <typename Mat>
133void determinant(const Mat& A, typename Mat::ElementType& result_det)
134{
135 (void) A;
136 (void) result_det;
137 throw exc::engine_error(
138 "'determinant' not implemented for this kind of matrix over this ring");
139}
140
155template <typename Mat>
156bool inverse(const Mat& A, Mat& result_inv)
157{
158 (void) A;
159 (void) result_inv;
160 throw exc::engine_error(
161 "'invert' not implemented for this kind of matrix over this ring");
162}
163
173template <typename Mat>
174size_t rowReducedEchelonForm(const Mat& A, Mat& result_rref)
175{
176 (void) A;
177 (void) result_rref;
178 throw exc::engine_error(
179 "'rowReducedEchelonForm' not implemented for this kind of matrix over "
180 "this ring");
181}
182
196template <typename Mat>
197void mult(const Mat& A, const Mat& B, Mat& result_product)
198{
199 (void) A;
200 (void) B;
201 (void) result_product;
202 throw exc::engine_error(
203 "'mult matrices' not implemented for this kind of matrix over this ring");
204}
205
219template <typename Mat>
220size_t nullSpace(const Mat& A, Mat& result_nullspace)
221{
222 (void) A;
223 (void) result_nullspace;
224 throw exc::engine_error(
225 "'nullSpace' not implemented for this kind of matrix over this ring");
226}
227
229template <typename Mat>
230bool solveLinear(const Mat& A, const Mat& B, Mat& X)
231{
232 (void) A;
233 (void) B;
234 (void) X;
235 throw exc::engine_error(
236 "'solveLinear' not implemented for this kind of matrix over this ring");
237}
238
244template <typename Mat>
245bool solveInvertible(const Mat& A, const Mat& B, Mat& X)
246{
247 (void) A;
248 (void) B;
249 (void) X;
250 throw exc::engine_error(
251 "'solveInvertible' not implemented for this kind of matrix over this "
252 "ring");
253}
254
267template <typename Mat>
268M2_arrayintOrNull rankProfile(const Mat& A, bool row_profile)
269{
270 (void) A;
271 (void) row_profile;
272 throw exc::engine_error(
273 "'rankProfile' not implemented for this kind of matrix over this ring");
274}
275
281template <typename Mat>
282void addMultipleTo(Mat& C, const Mat& A, const Mat& B)
283// C = C + A*B
284{
285 (void) C;
286 (void) A;
287 (void) B;
288 throw exc::engine_error(
289 "'addMultipleTo' not implemented for this kind of matrix over this ring");
290}
291
297template <typename Mat>
298void subtractMultipleTo(Mat& C, const Mat& A, const Mat& B)
299// C = C - A*B
300{
301 (void) C;
302 (void) A;
303 (void) B;
304 throw exc::engine_error(
305 "'subtractMultipleTo' not implemented for this kind of matrix over this "
306 "ring");
307}
308
309template <typename Mat>
310M2_arrayintOrNull LU(const Mat& A, Mat& L, Mat& U)
311{
312 (void) A;
313 (void) L;
314 (void) U;
315 throw exc::engine_error(
316 "'LU' not implemented for this kind of matrix over this ring");
317}
318
319template <typename Mat>
320M2_arrayintOrNull LUincremental(std::vector<size_t>& P, Mat& LU, const Mat& v, int i)
321{
322 (void) P;
323 (void) LU;
324 (void) v;
325 (void) i;
326 throw exc::engine_error(
327 "'LUincremental' not implemented for this kind of matrix over this ring");
328}
329
330template <typename Mat>
331void triangularSolve(Mat& Lv, Mat& x, int m, int strategy)
332{
333 (void) Lv;
334 (void) x;
335 (void) m;
336 (void) strategy;
337 throw exc::engine_error(
338 "'triangularSolve' not implemented for this kind of matrix over this "
339 "ring");
340}
341
342template <typename Mat, typename Mat2>
343bool eigenvalues(const Mat& A, Mat2& eigenvals)
344{
345 (void) A;
346 (void) eigenvals;
347 throw exc::engine_error(
348 "'eigenvalues' not implemented for this kind of matrix over this ring");
349}
350
351template <typename Mat, typename Mat2>
352bool eigenvaluesHermitian(const Mat& A, Mat2& eigenvals)
353{
354 (void) A;
355 (void) eigenvals;
356 throw exc::engine_error(
357 "'eigenvalues' not implemented for this kind of matrix over this ring");
358}
359
360template <typename Mat, typename Mat2, typename Mat3>
361bool eigenvectors(const Mat& A, Mat2& eigenvals, Mat3& eigenvecs)
362{
363 (void) A;
364 (void) eigenvals;
365 (void) eigenvecs;
366 throw exc::engine_error(
367 "'eigenvectors' not implemented for this kind of matrix over this ring");
368}
369
370template <typename Mat, typename Mat2, typename Mat3>
371bool eigenvectorsHermitian(const Mat& A, Mat2& eigenvals, Mat3& eigenvecs)
372{
373 (void) A;
374 (void) eigenvals;
375 (void) eigenvecs;
376 throw exc::engine_error(
377 "'eigenvectors' not implemented for this kind of matrix over this ring");
378}
379
380template <typename Mat>
381bool leastSquares(const Mat& A, const Mat& B, Mat& X, bool assume_full_rank)
382{
383 (void) A;
384 (void) B;
385 (void) X;
386 (void) assume_full_rank;
387 throw exc::engine_error(
388 "'leastSquares' not implemented for this kind of matrix over this ring");
389}
390
391template <typename Mat, typename Mat2>
392bool SVD(const Mat& A, Mat2& Sigma, Mat& U, Mat& Vt, int strategy)
393{
394 (void) A;
395 (void) Sigma;
396 (void) U;
397 (void) Vt;
398 (void) strategy;
399 throw exc::engine_error(
400 "'SVD' not implemented for this kind of matrix over this ring");
401}
402
403template <typename Mat, typename Mat2, typename Mat3>
404bool QR(const Mat& A, Mat2& Q, Mat3& R, bool return_QR)
405{
406 (void) A;
407 (void) Q;
408 (void) R;
409 (void) return_QR;
410 throw exc::engine_error(
411 "'QR' not implemented for this kind of matrix over this ring");
412}
413
414template <typename T>
415void clean(gmp_RR epsilon, T& mat)
416{
417 (void) epsilon;
418 (void) mat;
419 throw exc::engine_error(
420 "'clean' not implemented for this kind of matrix over this ring");
421}
422
423template <typename T>
424void increase_norm(gmp_RRmutable nm, const T& mat)
425{
426 (void) nm;
427 (void) mat;
428 throw exc::engine_error(
429 "'norm' not implemented for this kind of matrix over this ring");
430}
431
433// Generic functions for DMat ///
435
436template <typename RT>
437void mult(const DMat<RT>& A, const DMat<RT>& B, DMat<RT>& result_product)
438{
439 // printf("entering dmat mult\n");
440 assert(A.numColumns() == B.numRows());
441 assert(A.numRows() == result_product.numRows());
442 assert(B.numColumns() == result_product.numColumns());
443
444 typename RT::Element tmp(A.ring());
445 for (size_t i = 0; i < A.numRows(); i++)
446 for (size_t j = 0; j < B.numColumns(); j++)
447 {
448 auto& val = result_product.entry(i,j);
449 for (size_t k = 0; k < A.numColumns(); ++k)
450 {
451 A.ring().mult(tmp, A.entry(i,k), B.entry(k,j));
452 A.ring().add(val, val, tmp);
453 }
454 }
455}
456
457template <typename RT>
458void addMultipleTo(DMat<RT>& C, const DMat<RT>& A, const DMat<RT>& B)
459// C = C + A*B
460{
461 mult(A, B, C);
462}
463
464template <typename RT>
465void subtractMultipleTo(DMat<RT>& C, const DMat<RT>& A, const DMat<RT>& B)
466// C = C - A*B
467{
468 assert(A.numColumns() == B.numRows());
469 assert(A.numRows() == C.numRows());
470 assert(B.numColumns() == C.numColumns());
471
472 typename RT::Element tmp(A.ring());
473 for (size_t i = 0; i < A.numRows(); i++)
474 for (size_t j = 0; j < B.numColumns(); j++)
475 {
476 auto& val = C.entry(i,j);
477 for (size_t k = 0; k < A.numColumns(); ++k)
478 {
479 A.ring().mult(tmp, A.entry(i,k), B.entry(k,j));
480 A.ring().subtract(val, val, tmp);
481 }
482 }
483}
484
485// Note: this default version only works for fields. Any other rings
486// MUST redefine these functions
487template <typename RT>
488inline void determinant(const DMat<RT>& A, typename RT::ElementType& result)
489{
490 DMatLinAlg<RT> LUdecomp(A);
491 LUdecomp.determinant(result);
492}
493
494template <typename RT>
496{
497 std::vector<size_t> perm;
498 DMatLinAlg<RT> LUdecomp(A);
499 LUdecomp.matrixPLU(perm, L, U);
500 return stdvector_to_M2_arrayint(perm);
501}
502
503/*
504 Cases for strategy:
505 00 lower triangular (forward substitution)
506 01 lower triangular, assume 1 on diagonal
507 10 upper triangular (backward substitution)
508 11 upper triangular, assume 1 on diagonal
509 Note: the rest of the matrix need not be 0 filled.
510*/
511template <typename RT>
512void triangularSolve(DMat<RT>& Lv, DMat<RT>& x, int m, int strategy)
513{
514 // TODO: check rings match
515 // TODO: no divide by zero
516 // TODO: size of matrices
517 // TODO: add tests
518 // TODO: for size 0 also
519 switch (strategy)
520 {
521 case 0:
522 // TODO: change to iter
523 for (size_t i = 0; i < m; i++)
524 {
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);
528 MatElementaryOps<DMat<RT>>::column_op(Lv, m, a, i);
529 x.ring().negate(a, a);
530 }
531 break;
532 case 1:
533 // TODO: change to iter
534 for (size_t i = 0; i < m; i++)
535 {
536 auto& a = x.entry(i, 0);
537 x.ring().negate(a, Lv.entry(i, m));
538 MatElementaryOps<DMat<RT>>::column_op(Lv, m, a, i);
539 x.ring().negate(a, a);
540 }
541 break;
542 case 2:
543 // TODO: change to iter
544 for (size_t i = 1; i < m + 1; i++)
545 {
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);
549 MatElementaryOps<DMat<RT>>::column_op(Lv, m, a, m - i);
550 x.ring().negate(a, a);
551 }
552 break;
553 case 3:
554 // TODO: change to iter
555 for (size_t i = 1; i < m + 1; i++)
556 {
557 auto& a = x.entry(m - i, 0);
558 x.ring().negate(a, Lv.entry(m - i, m));
559 MatElementaryOps<DMat<RT>>::column_op(Lv, m, a, m - i);
560 x.ring().negate(a, a);
561 }
562 break;
563 }
564}
565
566template <typename RT>
567M2_arrayintOrNull LUincremental(std::vector<size_t>& P, DMat<RT>& LU, const DMat<RT>& v, int m)
568{
569 size_t n = LU.numRows();
570
571 // copy permuted v to m-th column of LU
572 // TODO: change to iter
573 for (size_t j = 0; j < n; j++)
574 LU.ring().set(LU.entry(j, m), v.entry(P[j], 0));
575
576 // reduce the m-th column of LU and forward solve
577 DMat<RT> x{LU.ring(), n, 1};
578 triangularSolve(LU, x, m, 1);
579 // place solution of forward solve in U
580 // TODO: change to iter
581 for (size_t i = 0; i < m; i++)
582 LU.ring().set(LU.entry(i, m), x.entry(i, 0));
583
584 // look for a pivot in L
585 int pivotPosition = -1;
586 // TODO: change to iter
587 for (size_t j = m; j < n; j++)
588 if (!LU.ring().is_zero(LU.entry(j, m)))
589 {
590 pivotPosition = j;
591 break;
592 }
593 // if no pivot found, return
594 if (pivotPosition == -1) return stdvector_to_M2_arrayint(P);
595 // otherwise swap rows and update P
596 MatElementaryOps<DMat<RT>>::interchange_rows(LU, pivotPosition, m);
597 std::swap(P[pivotPosition], P[m]);
598
599 // scale column of L
600 // TODO: change to iter
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));
603
604 return stdvector_to_M2_arrayint(P);
605}
606
607template <typename RT>
608inline size_t rank(const DMat<RT>& A)
609{
610 DMatLinAlg<RT> LUdecomp(A);
611 return LUdecomp.rank();
612}
613
614template <typename RT>
615inline M2_arrayintOrNull rankProfile(const DMat<RT>& A, bool row_profile)
616{
617 std::vector<size_t> profile;
618 if (row_profile)
619 {
620 // First transpose A
621 DMat<RT> B(A.ring(), A.numColumns(), A.numRows());
623 DMatLinAlg<RT> LUdecomp(B);
624 LUdecomp.columnRankProfile(profile);
625 return stdvector_to_M2_arrayint(profile);
626 }
627 else
628 {
629 DMatLinAlg<RT> LUdecomp(A);
630 LUdecomp.columnRankProfile(profile);
631 return stdvector_to_M2_arrayint(profile);
632 }
633}
634
635template <typename RT>
636inline bool inverse(const DMat<RT>& A, DMat<RT>& result_inv)
637{
638 DMatLinAlg<RT> LUdecomp(A);
639 return LUdecomp.inverse(result_inv);
640}
641
642template <typename RT>
643inline size_t nullSpace(const DMat<RT>& A, DMat<RT>& result_nullspace)
644{
645 DMatLinAlg<RT> LUdecomp(A);
646 return LUdecomp.kernel(result_nullspace);
647}
648
649template <typename RT>
650inline bool solveLinear(const DMat<RT>& A, const DMat<RT>& B, DMat<RT>& X)
651{
652 DMatLinAlg<RT> LUdecomp(A);
653 return LUdecomp.solve(B, X);
654}
655
656template <typename RT>
657inline bool solveInvertible(const DMat<RT>& A, const DMat<RT>& B, DMat<RT>& X)
658{
659 DMatLinAlg<RT> LUdecomp(A);
660 return LUdecomp.solveInvertible(B, X);
661}
662
664// ZZpFFPACK ///////////
666// namespace MatrixOps
667void mult(const DMatZZpFFPACK& A,
668 const DMatZZpFFPACK& B,
669 DMatZZpFFPACK& result_product);
670
672 const DMatZZpFFPACK& A,
673 const DMatZZpFFPACK& B);
674
676 const DMatZZpFFPACK& A,
677 const DMatZZpFFPACK& B);
678
680// ZZ (ARingZZGMP) ///
682
684{
685 (void) A;
686 (void) L;
687 (void) U;
688 throw exc::engine_error(
689 "'LU' not implemented for this kind of matrix over this ring");
690}
691
692inline M2_arrayintOrNull rankProfile(const DMatZZGMP& A, bool row_profile)
693{
694 (void) A;
695 (void) row_profile;
696 throw exc::engine_error(
697 "'rankProfile' not implemented for this kind of matrix over this ring");
698}
699
700inline bool inverse(const DMatZZGMP& A, DMatZZGMP& result_inv)
701{
702 (void) A;
703 (void) result_inv;
704 throw exc::engine_error(
705 "'invert' not implemented for this kind of matrix over this ring");
706}
707
708inline size_t nullSpace(const DMatZZGMP& A, DMatZZGMP& result_nullspace)
709{
710 (void) A;
711 (void) result_nullspace;
712 throw exc::engine_error(
713 "'nullSpace' not implemented for this kind of matrix over this ring");
714}
715
716inline bool solveLinear(const DMatZZGMP& A, const DMatZZGMP& B, DMatZZGMP& X)
717{
718 (void) A;
719 (void) B;
720 (void) X;
721 throw exc::engine_error(
722 "'solveLinear' not implemented for this kind of matrix over this ring");
723}
724
725inline bool solveInvertible(const DMatZZGMP& A,
726 const DMatZZGMP& B,
727 DMatZZGMP& X)
728{
729 (void) A;
730 (void) B;
731 (void) X;
732 throw exc::engine_error(
733 "'solveInvertible' not implemented for this kind of matrix over this "
734 "ring");
735}
736
737inline void mult(const DMatZZGMP& A,
738 const DMatZZGMP& B,
739 DMatZZGMP& result_product)
740{
741 FlintZZMat A1(A);
742 FlintZZMat B1(B);
743 FlintZZMat result1(A.numRows(), B.numColumns());
744
745 fmpz_mat_mul(result1.value(), A1.value(), B1.value());
746
747 result1.toDMat(result_product);
748}
749
750inline void addMultipleTo(DMatZZGMP& C, const DMatZZGMP& A, const DMatZZGMP& B)
751{
752 FlintZZMat A1(A);
753 FlintZZMat B1(B);
754 FlintZZMat C1(C);
755 FlintZZMat result1(A.numRows(), B.numColumns());
756
757 FlintZZMat D1(A.numRows(), B.numColumns());
758 fmpz_mat_mul(D1.value(), A1.value(), B1.value());
759 fmpz_mat_add(C1.value(), C1.value(), D1.value());
760
761 C1.toDMat(C);
762}
763
765 const DMatZZGMP& A,
766 const DMatZZGMP& B)
767{
768 FlintZZMat A1(A);
769 FlintZZMat B1(B);
770 FlintZZMat C1(C);
771 FlintZZMat result1(A.numRows(), B.numColumns());
772
773 FlintZZMat D1(A.numRows(), B.numColumns());
774 fmpz_mat_mul(D1.value(), A1.value(), B1.value());
775 fmpz_mat_sub(C1.value(), C1.value(), D1.value());
776
777 C1.toDMat(C);
778}
779
780inline size_t rank(const DMatZZGMP& A)
781{
782 FlintZZMat A1(A);
783 return fmpz_mat_rank(A1.value());
784}
785
786inline void determinant(const DMatZZGMP& A,
787 M2::ARingZZGMP::ElementType& result_det)
788{
789 FlintZZMat A1(A);
790 fmpz_t det;
791 fmpz_init(det);
792 fmpz_mat_det(det, A1.value());
793 fmpz_get_mpz(&result_det, det);
794 fmpz_clear(det);
795}
796
798// ZZFlint ///////////
800// Warning: nullSpace is WRONG, and needs to be rewritten,
801// using an algorithm that will compute kernel over ZZ.
802
803// Functions for DMatZZ
804
805inline size_t rank(const DMatZZ& A) { return fmpz_mat_rank(A.fmpz_mat()); }
806inline void determinant(const DMatZZ& A, M2::ARingZZ::ElementType& result_det)
807{
808 fmpz_mat_det(&result_det, A.fmpz_mat());
809}
810
811inline bool inverse(const DMatZZ& A, DMatZZ& result_inv)
812{
813 M2::ARingZZ::Element den(A.ring());
814 bool result = fmpz_mat_inv(result_inv.fmpz_mat(), &den.value(), A.fmpz_mat());
815 if (!fmpz_is_pm1(&den.value())) result = false;
816 return result;
817}
818
819inline void mult(const DMatZZ& A, const DMatZZ& B, DMatZZ& result_product)
820{
821 // The A1 and B1 on the next line are switched because the memory layout
822 // expected
823 // is the transpose of what we have for DMat.
824 fmpz_mat_mul(result_product.fmpz_mat(), A.fmpz_mat(), B.fmpz_mat());
825}
826
827inline size_t nullSpace(const DMatZZ& A, DMatZZ& result_nullspace)
828{
829 long nullity = fmpz_mat_nullspace(result_nullspace.fmpz_mat(), A.fmpz_mat());
830 return nullity;
831}
832
833inline bool solveLinear(const DMatZZ& A, const DMatZZ& B, DMatZZ& X)
834{
835 M2::ARingZZ::Element den(A.ring());
836 bool result = fmpz_mat_solve(X.fmpz_mat(), &den.value(), B.fmpz_mat(), A.fmpz_mat());
837 if (!fmpz_is_pm1(&den.value())) result = false;
838 return result;
839}
840
841inline M2_arrayintOrNull rankProfile(const DMatZZ& A, bool row_profile)
842{
843 (void) A;
844 (void) row_profile;
845 throw exc::engine_error(
846 "'rankProfile' not implemented for this kind of matrix over this ring");
847}
848
849inline void addMultipleTo(DMatZZ& C, const DMatZZ& A, const DMatZZ& B)
850{
851 DMatZZ D(C.ring(), A.numRows(), B.numColumns());
852 fmpz_mat_mul(D.fmpz_mat(), A.fmpz_mat(), B.fmpz_mat());
853 fmpz_mat_add(C.fmpz_mat(), C.fmpz_mat(), D.fmpz_mat());
854}
855
856inline void subtractMultipleTo(DMatZZ& C, const DMatZZ& A, const DMatZZ& B)
857{
858 DMatZZ D(C.ring(), A.numRows(), B.numColumns());
859 fmpz_mat_mul(D.fmpz_mat(), A.fmpz_mat(), B.fmpz_mat());
860 fmpz_mat_sub(C.fmpz_mat(), C.fmpz_mat(), D.fmpz_mat());
861}
862
864// ZZpFlint //////////
866
867// Functions for DMatZZpFlint
868
870 const DMatZZpFlint& A,
871 const DMatZZpFlint& B)
872{
873 DMatZZpFlint D(C.ring(), A.numRows(), B.numColumns());
874 nmod_mat_mul(D.nmod_mat(), A.nmod_mat(), B.nmod_mat());
875 nmod_mat_add(C.nmod_mat(), C.nmod_mat(), D.nmod_mat());
876}
877
879 const DMatZZpFlint& A,
880 const DMatZZpFlint& B)
881{
882 DMatZZpFlint D(C.ring(), A.numRows(), B.numColumns());
883 nmod_mat_mul(D.nmod_mat(), A.nmod_mat(), B.nmod_mat());
884 nmod_mat_sub(C.nmod_mat(), C.nmod_mat(), D.nmod_mat());
885}
886
887inline void mult(const DMatZZpFlint& A,
888 const DMatZZpFlint& B,
889 DMatZZpFlint& result_product)
890{
891 // DMatZZpFlint& A1 = const_cast<DMatZZpFlint&>(A); // needed because
892 // nmod_mat_mul doesn't declare params const
893 // DMatZZpFlint& B1 = const_cast<DMatZZpFlint&>(B);
894 // The A1 and B1 on the next line are switched because the memory layout
895 // expected
896 // is the transpose of what we have for DMat.
897 nmod_mat_mul(result_product.nmod_mat(), A.nmod_mat(), B.nmod_mat());
898}
899
900inline size_t rowReducedEchelonForm(const DMatZZpFlint& A,
901 DMatZZpFlint& result_rref)
902{
903 DMatZZpFlint A1(A);
904 long rank = nmod_mat_rref(A1.nmod_mat());
905 result_rref.swap(A1);
906 return rank;
907}
908
910// GFFlintBig //////////
912
913// Functions for DMatGFFlintBig, linear algebra is sent out to LU
914
916 const DMatGFFlintBig& A,
917 const DMatGFFlintBig& B)
918{
919 DMatGFFlintBig D(C.ring(), A.numRows(), B.numColumns());
920 fq_nmod_mat_mul(D.fq_nmod_mat(),
921 A.fq_nmod_mat(),
922 B.fq_nmod_mat(),
923 A.ring().flintContext());
924 fq_nmod_mat_add(C.fq_nmod_mat(),
925 C.fq_nmod_mat(),
926 D.fq_nmod_mat(),
927 A.ring().flintContext());
928}
929
931 const DMatGFFlintBig& A,
932 const DMatGFFlintBig& B)
933{
934 DMatGFFlintBig D(C.ring(), A.numRows(), B.numColumns());
935 fq_nmod_mat_mul(D.fq_nmod_mat(),
936 A.fq_nmod_mat(),
937 B.fq_nmod_mat(),
938 A.ring().flintContext());
939 fq_nmod_mat_sub(C.fq_nmod_mat(),
940 C.fq_nmod_mat(),
941 D.fq_nmod_mat(),
942 A.ring().flintContext());
943}
944
945inline void mult(const DMatGFFlintBig& A,
946 const DMatGFFlintBig& B,
947 DMatGFFlintBig& result_product)
948{
949 // DMatGFFlintBig& A1 = const_cast<DMatGFFlintBig&>(A); // needed because
950 // nmod_mat_mul doesn't declare params const
951 // DMatGFFlintBig& B1 = const_cast<DMatGFFlintBig&>(B);
952 // The A1 and B1 on the next line are switched because the memory layout
953 // expected
954 // is the transpose of what we have for DMat.
955 fq_nmod_mat_mul(result_product.fq_nmod_mat(),
956 A.fq_nmod_mat(),
957 B.fq_nmod_mat(),
958 A.ring().flintContext());
959}
960
962 DMatGFFlintBig& result_rref)
963{
964 DMatGFFlintBig A1(A);
965#if __FLINT_RELEASE >= 30100
966 long rank = fq_nmod_mat_rref(A1.fq_nmod_mat(), A1.fq_nmod_mat(), A.ring().flintContext());
967#else
968 long rank = fq_nmod_mat_rref(A1.fq_nmod_mat(), A.ring().flintContext());
969#endif
970 result_rref.swap(A1);
971 return rank;
972}
973
975// GFFlint /////////////
977
978// Functions for DMatGFFlint, linear algebra is sent out to LU
979
981 const DMatGFFlint& A,
982 const DMatGFFlint& B)
983{
984 DMatGFFlint D(C.ring(), A.numRows(), B.numColumns());
985 fq_zech_mat_mul(D.fq_zech_mat(),
986 A.fq_zech_mat(),
987 B.fq_zech_mat(),
988 A.ring().flintContext());
989 fq_zech_mat_add(C.fq_zech_mat(),
990 C.fq_zech_mat(),
991 D.fq_zech_mat(),
992 A.ring().flintContext());
993}
994
996 const DMatGFFlint& A,
997 const DMatGFFlint& B)
998{
999 DMatGFFlint D(C.ring(), A.numRows(), B.numColumns());
1000 fq_zech_mat_mul(D.fq_zech_mat(),
1001 A.fq_zech_mat(),
1002 B.fq_zech_mat(),
1003 A.ring().flintContext());
1004 fq_zech_mat_sub(C.fq_zech_mat(),
1005 C.fq_zech_mat(),
1006 D.fq_zech_mat(),
1007 A.ring().flintContext());
1008}
1009
1010inline void mult(const DMatGFFlint& A,
1011 const DMatGFFlint& B,
1012 DMatGFFlint& result_product)
1013{
1014 // DMatGFFlint& A1 = const_cast<DMatGFFlint&>(A); // needed because
1015 // nmod_mat_mul doesn't declare params const
1016 // DMatGFFlint& B1 = const_cast<DMatGFFlint&>(B);
1017 // The A1 and B1 on the next line are switched because the memory layout
1018 // expected
1019 // is the transpose of what we have for DMat.
1020 fq_zech_mat_mul(result_product.fq_zech_mat(),
1021 A.fq_zech_mat(),
1022 B.fq_zech_mat(),
1023 A.ring().flintContext());
1024}
1025
1026inline size_t rowReducedEchelonForm(const DMatGFFlint& A,
1027 DMatGFFlint& result_rref)
1028{
1029 DMatGFFlint A1(A);
1030#if __FLINT_RELEASE >= 30100
1031 long rank = fq_zech_mat_rref(A1.fq_zech_mat(), A1.fq_zech_mat(), A.ring().flintContext());
1032#else
1033 long rank = fq_zech_mat_rref(A1.fq_zech_mat(), A.ring().flintContext());
1034#endif
1035 result_rref.swap(A1);
1036 return rank;
1037}
1038
1040// QQ ////////////////
1042
1043inline void mult(const DMatQQ& A, const DMatQQ& B, DMatQQ& result_product)
1044{
1045 FlintQQMat A1(A);
1046 FlintQQMat B1(B);
1047 FlintQQMat result1(A.numRows(), B.numColumns());
1048
1049 fmpq_mat_mul(result1.value(), A1.value(), B1.value());
1050
1051 result1.toDMat(result_product);
1052}
1053
1054inline void addMultipleTo(DMatQQ& C, const DMatQQ& A, const DMatQQ& B)
1055{
1056 FlintQQMat A1(A);
1057 FlintQQMat B1(B);
1058 FlintQQMat C1(C);
1059 FlintQQMat result1(A.numRows(), B.numColumns());
1060
1061 FlintQQMat D1(A.numRows(), B.numColumns());
1062 fmpq_mat_mul(D1.value(), A1.value(), B1.value());
1063 fmpq_mat_add(C1.value(), C1.value(), D1.value());
1064
1065 C1.toDMat(C);
1066}
1067
1068inline void subtractMultipleTo(DMatQQ& C, const DMatQQ& A, const DMatQQ& B)
1069{
1070 FlintQQMat A1(A);
1071 FlintQQMat B1(B);
1072 FlintQQMat C1(C);
1073 FlintQQMat result1(A.numRows(), B.numColumns());
1074
1075 FlintQQMat D1(A.numRows(), B.numColumns());
1076 fmpq_mat_mul(D1.value(), A1.value(), B1.value());
1077 fmpq_mat_sub(C1.value(), C1.value(), D1.value());
1078
1079 C1.toDMat(C);
1080}
1081
1082inline size_t rowReducedEchelonForm(const DMatQQ& A, DMatQQ& result_rref)
1083{
1084 FlintQQMat A1(A);
1085 long rank = fmpq_mat_rref(A1.value(), A1.value());
1086 A1.toDMat(result_rref);
1087 return rank;
1088}
1089
1091// QQFlint ///////////
1093
1094// Functions for DMatQQFlint
1095
1096inline size_t rank(const DMatQQFlint& A)
1097{
1098 // fmpq_mat has no rank function.
1099 // So we clear denominators row-wise (or column-wise), and compute the rank of
1100 // that matrix.
1101 fmpz_mat_t m1;
1102 fmpz_mat_init(m1, A.numRows(), A.numColumns());
1103 fmpq_mat_get_fmpz_mat_rowwise(m1, nullptr, A.fmpq_mat());
1104 // fmpz_mat_print_pretty(m1);
1105 size_t rk = fmpz_mat_rank(m1);
1106 fmpz_mat_clear(m1);
1107 return rk;
1108}
1109
1110inline void determinant(const DMatQQFlint& A,
1112{
1113 fmpq_mat_det(&result_det, A.fmpq_mat());
1114}
1115
1116inline bool inverse(const DMatQQFlint& A, DMatQQFlint& result_inv)
1117{
1118 return fmpq_mat_inv(result_inv.fmpq_mat(), A.fmpq_mat());
1119}
1120
1121inline size_t rowReducedEchelonForm(const DMatQQFlint& A,
1122 DMatQQFlint& result_rref)
1123{
1124 return fmpq_mat_rref(result_rref.fmpq_mat(), A.fmpq_mat());
1125}
1126
1127inline size_t nullSpace(const DMatQQFlint& A, DMatQQFlint& result_nullspace)
1128{
1129 fmpz_mat_t m1;
1130 fmpz_mat_t m2;
1131 fmpz_mat_init(m1, A.numRows(), A.numColumns());
1132 fmpz_mat_init(m2, A.numColumns(), A.numColumns());
1133 fmpq_mat_get_fmpz_mat_rowwise(m1, nullptr, A.fmpq_mat());
1134 // fmpz_mat_print_pretty(m1);
1135 size_t nullity = fmpz_mat_nullspace(m2, m1);
1136 // now copy the first 'nullity' columns into result_nullspace
1137 result_nullspace.resize(A.numColumns(), nullity);
1138 for (size_t c = 0; c < nullity; c++)
1139 for (size_t r = 0; r < A.numColumns(); r++)
1140 fmpz_set(fmpq_numref(&result_nullspace.entry(r, c)),
1141 fmpz_mat_entry(m2, r, c));
1142 fmpz_mat_clear(m1);
1143 fmpz_mat_clear(m2);
1144 return nullity;
1145}
1146
1147inline bool solveLinear(const DMatQQFlint& A,
1148 const DMatQQFlint& B,
1149 DMatQQFlint& X)
1150{
1151 // TODO: WRITE ME
1152 // DMatQQFlint& A1 = const_cast<DMatQQFlint&>(A); // needed because
1153 // fmpq_mat_solve doesn't declare params const
1154 // DMatQQFlint& B1 = const_cast<DMatQQFlint&>(B);
1155 // return fmpq_mat_solve(X.fmpq_mat(), B1.fmpq_mat(), A1.fmpq_mat());
1156 (void) A;
1157 (void) B;
1158 (void) X;
1159 return false;
1160}
1161
1162inline M2_arrayintOrNull rankProfile(const DMatQQFlint& A, bool row_profile)
1163{
1164 // TODO: WRITE ME
1165 (void) A;
1166 (void) row_profile;
1167 throw exc::engine_error(
1168 "'rankProfile' not implemented for this kind of matrix over this ring");
1169}
1170
1172 const DMatQQFlint& A,
1173 const DMatQQFlint& B)
1174{
1175 DMatQQFlint D(C.ring(), A.numRows(), B.numColumns());
1176 fmpq_mat_mul(D.fmpq_mat(), A.fmpq_mat(), B.fmpq_mat());
1177 fmpq_mat_add(C.fmpq_mat(), C.fmpq_mat(), D.fmpq_mat());
1178}
1179
1181 const DMatQQFlint& A,
1182 const DMatQQFlint& B)
1183{
1184 DMatQQFlint D(C.ring(), A.numRows(), B.numColumns());
1185 fmpq_mat_mul(D.fmpq_mat(), A.fmpq_mat(), B.fmpq_mat());
1186 fmpq_mat_sub(C.fmpq_mat(), C.fmpq_mat(), D.fmpq_mat());
1187}
1188
1189inline void mult(const DMatQQFlint& A,
1190 const DMatQQFlint& B,
1191 DMatQQFlint& result_product)
1192{
1193 // The A and B on the next line are switched because the memory layout
1194 // expected
1195 // is the transpose of what we have for DMat.
1196 fmpq_mat_mul(result_product.fmpq_mat(), A.fmpq_mat(), B.fmpq_mat());
1197}
1198
1200// RR //
1202inline bool eigenvaluesHermitian(const DMatRR& A, DMatRR& eigenvals)
1203{
1204#ifndef NO_LAPACK
1205 return Lapack::eigenvalues_symmetric(&A, &eigenvals);
1206#else
1207 return EigenM2::eigenvalues_hermitian(&A, &eigenvals);
1208#endif
1209}
1210
1211inline bool eigenvalues(const DMatRR& A, DMatCC& eigenvals)
1212{
1213#ifndef NO_LAPACK
1214 return Lapack::eigenvalues(&A, &eigenvals);
1215#else
1216 return EigenM2::eigenvalues(&A, &eigenvals);
1217#endif
1218}
1219
1220inline bool eigenvectorsHermitian(const DMatRR& A,
1221 DMatRR& eigenvals,
1222 DMatRR& eigenvecs)
1223{
1224#ifndef NO_LAPACK
1225 return Lapack::eigenvectors_symmetric(&A, &eigenvals, &eigenvecs);
1226#else
1227 return EigenM2::eigenvectors_hermitian(&A, &eigenvals, &eigenvecs);
1228#endif
1229}
1230
1231inline bool eigenvectors(const DMatRR& A, DMatCC& eigenvals, DMatCC& eigenvecs)
1232{
1233#ifndef NO_LAPACK
1234 return Lapack::eigenvectors(&A, &eigenvals, &eigenvecs);
1235#else
1236 return EigenM2::eigenvectors(&A, &eigenvals, &eigenvecs);
1237#endif
1238}
1239
1240inline bool leastSquares(const DMatRR& A,
1241 const DMatRR& B,
1242 DMatRR& X,
1243 bool assume_full_rank)
1244{
1245#ifndef NO_LAPACK
1246 if (assume_full_rank)
1247 return Lapack::least_squares(&A, &B, &X);
1248 else
1249 return Lapack::least_squares_deficient(&A, &B, &X);
1250#else
1251 // place eigen code here
1252 return EigenM2::least_squares(&A, &B, &X);
1253 // throw exc::engine_error( "not implemented!!!");
1254 // return false; // indicates error
1255#endif
1256}
1257
1258inline bool SVD(const DMatRR& A,
1259 DMatRR& Sigma,
1260 DMatRR& U,
1261 DMatRR& Vt,
1262 int strategy)
1263{
1264#ifndef NO_LAPACK
1265 if (strategy == 1) return Lapack::SVD_divide_conquer(&A, &Sigma, &U, &Vt);
1266 return Lapack::SVD(&A, &Sigma, &U, &Vt);
1267#else
1268 if (strategy == 1) return EigenM2::SVD_divide_conquer(&A, &Sigma, &U, &Vt);
1269 return EigenM2::SVD(&A, &Sigma, &U, &Vt);
1270#endif
1271}
1272
1273inline bool QR(const DMatRR& A, DMatRR& Q, DMatRR& R, bool return_QR)
1274{
1275 return Lapack::QR(&A, &Q, &R, return_QR);
1276}
1277
1278inline bool QR(const DMatCC& A, DMatCC& Q, DMatCC& R, bool return_QR)
1279{
1280 return Lapack::QR(&A, &Q, &R, return_QR);
1281}
1282
1283inline void clean(gmp_RR epsilon, DMatRR& mat)
1284{
1285 for (size_t r = 0; r < mat.numRows(); ++r)
1286 for (size_t c = 0; c < mat.numColumns(); ++c)
1287 {
1288 mat.ring().zeroize_tiny(epsilon, mat.entry(r,c));
1289 }
1290}
1291
1292inline void increase_norm(gmp_RRmutable norm, const DMatRR& mat)
1293{
1294 for (size_t r = 0; r < mat.numRows(); ++r)
1295 for (size_t c = 0; c < mat.numColumns(); ++c)
1296 {
1297 mat.ring().increase_norm(norm, mat.entry(r,c));
1298 }
1299}
1300
1302// CC //
1304inline bool eigenvaluesHermitian(const DMatCC& A, DMatRR& eigenvals)
1305{
1306#ifndef NO_LAPACK
1307 return Lapack::eigenvalues_hermitian(&A, &eigenvals);
1308#else
1309 return EigenM2::eigenvalues_hermitian(&A, &eigenvals);
1310#endif
1311}
1312
1313inline bool eigenvalues(const DMatCC& A, DMatCC& eigenvals)
1314{
1315#ifndef NO_LAPACK
1316 return Lapack::eigenvalues(&A, &eigenvals);
1317#else
1318 return EigenM2::eigenvalues(&A, &eigenvals);
1319#endif
1320}
1321
1322inline bool eigenvectorsHermitian(const DMatCC& A,
1323 DMatRR& eigenvals,
1324 DMatCC& eigenvecs)
1325{
1326#ifndef NO_LAPACK
1327 return Lapack::eigenvectors_hermitian(&A, &eigenvals, &eigenvecs);
1328#else
1329 return EigenM2::eigenvectors_hermitian(&A, &eigenvals, &eigenvecs);
1330#endif
1331}
1332
1333inline bool eigenvectors(const DMatCC& A, DMatCC& eigenvals, DMatCC& eigenvecs)
1334{
1335#ifndef NO_LAPACK
1336 return Lapack::eigenvectors(&A, &eigenvals, &eigenvecs);
1337#else
1338 return EigenM2::eigenvectors(&A, &eigenvals, &eigenvecs);
1339#endif
1340}
1341
1342inline bool leastSquares(const DMatCC& A,
1343 const DMatCC& B,
1344 DMatCC& X,
1345 bool assume_full_rank)
1346{
1347#ifndef NO_LAPACK
1348 if (assume_full_rank)
1349 return Lapack::least_squares(&A, &B, &X);
1350 else
1351 return Lapack::least_squares_deficient(&A, &B, &X);
1352#else
1353 return EigenM2::least_squares(&A, &B, &X);
1354#endif
1355}
1356
1357inline bool SVD(const DMatCC& A,
1358 DMatRR& Sigma,
1359 DMatCC& U,
1360 DMatCC& Vt,
1361 int strategy)
1362{
1363#ifndef NO_LAPACK
1364 if (strategy == 1) return Lapack::SVD_divide_conquer(&A, &Sigma, &U, &Vt);
1365 return Lapack::SVD(&A, &Sigma, &U, &Vt);
1366#else
1367 if (strategy == 1) return EigenM2::SVD_divide_conquer(&A, &Sigma, &U, &Vt);
1368 return EigenM2::SVD(&A, &Sigma, &U, &Vt);
1369#endif
1370}
1371
1372inline void clean(gmp_RR epsilon, DMatCC& mat)
1373{
1374 for (size_t r = 0; r < mat.numRows(); ++r)
1375 for (size_t c = 0; c < mat.numColumns(); ++c)
1376 {
1377 mat.ring().zeroize_tiny(epsilon, mat.entry(r,c));
1378 }
1379}
1380
1381inline void increase_norm(gmp_RRmutable norm, const DMatCC& mat)
1382{
1383 for (size_t r = 0; r < mat.numRows(); ++r)
1384 for (size_t c = 0; c < mat.numColumns(); ++c)
1385 {
1386 mat.ring().increase_norm(norm, mat.entry(r,c));
1387 }
1388}
1389
1391// RRR //
1393
1394inline bool eigenvaluesHermitian(const DMatRRR& A, DMatRRR& eigenvals)
1395{
1396 return EigenM2::eigenvalues_hermitian(&A, &eigenvals);
1397}
1398
1399inline bool eigenvalues(const DMatRRR& A, DMatCCC& eigenvals)
1400{
1401 return EigenM2::eigenvalues(&A, &eigenvals);
1402}
1403
1404inline bool eigenvectorsHermitian(const DMatRRR& A,
1405 DMatRRR& eigenvals,
1406 DMatRRR& eigenvecs)
1407{
1408 return EigenM2::eigenvectors_hermitian(&A, &eigenvals, &eigenvecs);
1409}
1410
1411inline bool eigenvectors(const DMatRRR& A,
1412 DMatCCC& eigenvals,
1413 DMatCCC& eigenvecs)
1414{
1415 return EigenM2::eigenvectors(&A, &eigenvals, &eigenvecs);
1416}
1417
1418inline bool leastSquares(const DMatRRR& A,
1419 const DMatRRR& B,
1420 DMatRRR& X,
1421 bool assume_full_rank)
1422{
1423 (void) assume_full_rank;
1424 return EigenM2::least_squares(&A, &B, &X);
1425}
1426
1427inline bool SVD(const DMatRRR& A,
1428 DMatRRR& Sigma,
1429 DMatRRR& U,
1430 DMatRRR& Vt,
1431 int strategy)
1432{
1433 if (strategy == 1) return EigenM2::SVD_divide_conquer(&A, &Sigma, &U, &Vt);
1434 return EigenM2::SVD(&A, &Sigma, &U, &Vt);
1435}
1436
1437inline void clean(gmp_RR epsilon, DMatRRR& mat)
1438{
1439 for (size_t r = 0; r < mat.numRows(); ++r)
1440 for (size_t c = 0; c < mat.numColumns(); ++c)
1441 {
1442 mat.ring().zeroize_tiny(epsilon, mat.entry(r,c));
1443 }
1444}
1445
1446inline void increase_norm(gmp_RRmutable norm, const DMatRRR& mat)
1447{
1448 for (size_t r = 0; r < mat.numRows(); ++r)
1449 for (size_t c = 0; c < mat.numColumns(); ++c)
1450 {
1451 mat.ring().increase_norm(norm, mat.entry(r,c));
1452 }
1453}
1454
1456// CCC // TODO: rewrite not using lapack
1458
1459inline bool eigenvaluesHermitian(const DMatCCC& A, DMatRRR& eigenvals)
1460{
1461 return EigenM2::eigenvalues_hermitian(&A, &eigenvals);
1462}
1463
1464inline bool eigenvalues(const DMatCCC& A, DMatCCC& eigenvals)
1465{
1466 return EigenM2::eigenvalues(&A, &eigenvals);
1467}
1468
1469inline bool eigenvectorsHermitian(const DMatCCC& A,
1470 DMatRRR& eigenvals,
1471 DMatCCC& eigenvecs)
1472{
1473 return EigenM2::eigenvectors_hermitian(&A, &eigenvals, &eigenvecs);
1474}
1475
1476inline bool eigenvectors(const DMatCCC& A,
1477 DMatCCC& eigenvals,
1478 DMatCCC& eigenvecs)
1479{
1480 return EigenM2::eigenvectors(&A, &eigenvals, &eigenvecs);
1481}
1482
1483inline bool leastSquares(const DMatCCC& A,
1484 const DMatCCC& B,
1485 DMatCCC& X,
1486 bool assume_full_rank)
1487{
1488 (void) assume_full_rank;
1489 return EigenM2::least_squares(&A, &B, &X);
1490}
1491
1492inline bool SVD(const DMatCCC& A,
1493 DMatRRR& Sigma,
1494 DMatCCC& U,
1495 DMatCCC& Vt,
1496 int strategy)
1497{
1498 if (strategy == 1) return EigenM2::SVD_divide_conquer(&A, &Sigma, &U, &Vt);
1499 return EigenM2::SVD(&A, &Sigma, &U, &Vt);
1500}
1501
1502inline void clean(gmp_RR epsilon, DMatCCC& mat)
1503{
1504 for (size_t r = 0; r < mat.numRows(); ++r)
1505 for (size_t c = 0; c < mat.numColumns(); ++c)
1506 {
1507 mat.ring().zeroize_tiny(epsilon, mat.entry(r,c));
1508 }
1509}
1510
1511inline void increase_norm(gmp_RRmutable norm, const DMatCCC& mat)
1512{
1513 for (size_t r = 0; r < mat.numRows(); ++r)
1514 for (size_t c = 0; c < mat.numColumns(); ++c)
1515 {
1516 mat.ring().increase_norm(norm, mat.entry(r,c));
1517 }
1518}
1519
1520}; // namespace MatrixOps
1521
1522#endif
1523
1524// Local Variables:
1525// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1526// indent-tabs-mode: nil
1527// End:
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)
const ACoeffRing & ring() 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)
const fmpq_mat_t & fmpq_mat() const
size_t numRows() const
const ACoeffRing & ring() const
size_t numColumns() const
const fmpz_mat_t & fmpz_mat() const
void swap(DMat< ACoeffRing > &M)
const ACoeffRing & ring() const
const nmod_mat_t & nmod_mat() const
size_t numRows() const
Definition dmat.hpp:144
ElementType & entry(size_t row, size_t column)
Definition dmat.hpp:148
const ACoeffRing & ring() const
Definition dmat.hpp:143
size_t numColumns() const
Definition dmat.hpp:145
Definition dmat.hpp:62
size_t kernel(Mat &X)
Definition dmat-lu.hpp:580
size_t rank()
Output: returns the approximate rank of A (-1 if fails).
Definition dmat-lu.hpp:332
void determinant(ElementType &result)
Output: result, the determinant of A.
Definition dmat-lu.hpp:308
bool solveInvertible(const Mat &B, Mat &X)
Definition dmat-lu.hpp:535
bool matrixPLU(std::vector< size_t > &P, Mat &L, Mat &U)
Definition dmat-lu.hpp:297
bool inverse(Mat &X)
Definition dmat-lu.hpp:564
bool solve(const Mat &B, Mat &X)
Definition dmat-lu.hpp:340
void columnRankProfile(std::vector< size_t > &profile)
Definition dmat-lu.hpp:324
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)
Definition lapack.cpp:898
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
Definition aring-CC.hpp:461
void increase_norm(gmp_RRmutable norm, const ElementType &a) const
Definition aring-CC.hpp:467
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
Definition aring-RR.hpp:289
void zeroize_tiny(gmp_RR epsilon, ElementType &a) const
Definition aring-RR.hpp:284
void increase_norm(gmp_RRmutable norm, const ElementType &a) const
void zeroize_tiny(gmp_RR epsilon, ElementType &a) const
__mpz_struct ElementType
wrapper for the FFPACK::ModularBalanced<double> field implementation
DMat< M2::ARingGFFlintBig > DMatGFFlintBig
Definition dmat-lu.hpp:54
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
Definition lapack.hpp:51
DMat< M2::ARingCC > DMatCC
Definition lapack.hpp:53
DMat< M2::ARingRRR > DMatRRR
Definition lapack.hpp:50
DMat< M2::ARingRR > DMatRR
Definition lapack.hpp:52
Engine bridge into LAPACK for RR / CC dense linear algebra.
VALGRIND_MAKE_MEM_DEFINED & result(result)
mpfr_srcptr gmp_RR
Definition m2-types.h:148
M2_arrayint M2_arrayintOrNull
Definition m2-types.h:99
mpfr_ptr gmp_RRmutable
Definition m2-types.h:150
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
#define DMatZZpFFPACK
DMat< M2::ARingGFM2 > DMatGFM2
bool SVD(const LMatrixRRR *A, LMatrixRRR *Sigma, LMatrixRRR *U, LMatrixRRR *VT)
Definition eigen.cpp:349
bool least_squares(const LMatrixRRR *A, const LMatrixRRR *B, LMatrixRRR *X)
Definition eigen.cpp:558
bool eigenvectors(const LMatrixRRR *A, LMatrixCCC *eigenvals, LMatrixCCC *eigenvecs)
Definition eigen.cpp:498
bool eigenvectors_hermitian(const LMatrixRRR *A, LMatrixRRR *eigenvals, LMatrixRRR *eigenvecs)
Definition eigen.cpp:528
bool SVD_divide_conquer(const LMatrixRRR *A, LMatrixRRR *Sigma, LMatrixRRR *U, LMatrixRRR *VT)
Definition eigen.cpp:398
bool eigenvalues(const LMatrixRRR *A, LMatrixCCC *eigenvals)
Definition eigen.cpp:442
bool eigenvalues_hermitian(const LMatrixRRR *A, LMatrixRRR *eigenvals)
Definition eigen.cpp:470
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)
Definition dmat.cpp:63
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)
Definition dmat.cpp:13
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)
Definition dmat.cpp:72
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)
Definition mpreal.h:3244
volatile int x
#define T
Definition table.c:13
M2_arrayint stdvector_to_M2_arrayint(const std::vector< T > &v)
Definition util.hpp:79
Conversion helpers between M2 boundary types and standard C++ containers.