Macaulay2 Engine
Loading...
Searching...
No Matches
mutable-matrix.cpp
Go to the documentation of this file.
1// Copyright 2004 Michael E. Stillman
2
4
5#include <assert.h>
6#include <algorithm>
7#include <vector>
8
9#include "LLL.hpp"
10#include "aring-zzp-ffpack.hpp"
11#include "buffer.hpp"
12#include "error.h"
13#include "exceptions.hpp"
14#include "finalize.hpp"
15#include "fractionfreeLU.hpp"
16#include "interface/gmp-util.h"
17#include "interface/random.h"
18#include "mat.hpp"
19#include "matrix.hpp"
20#include "relem.hpp"
21#include "ring.hpp"
22#include "ringelem.hpp"
23#include "util.hpp"
24
26 int n,
27 M2_bool is_dense)
28{
29 if (n < 0)
30 {
31 ERROR("expected nonnegative integer");
32 return nullptr;
33 }
34 size_t nrows = static_cast<size_t>(n);
35 return internMutableMatrix(MutableMatrix::identity(R, nrows, is_dense));
36}
37
39 int nrows,
40 int ncols,
41 M2_bool is_dense)
42{
43 if (nrows < 0 || ncols < 0) {
44 ERROR("expected nonnegative integers");
45 return nullptr;
46 }
47
48 size_t nr = static_cast<size_t>(nrows);
49 size_t nc = static_cast<size_t>(ncols);
50 // return R->makeMutableMatrix(nr,nc,is_dense);
51 return internMutableMatrix(MutableMatrix::zero_matrix(R, nr, nc, is_dense));
52}
53
58
60{
61 return M->to_matrix();
62}
63
65{
66 buffer o;
67 M->text_out(o);
68 return o.to_string();
69}
70
71unsigned int rawMutableMatrixHash(const MutableMatrix *M) { return M->hash(); }
73 const MutableMatrix *f)
74{
75 (void) S;
76 (void) f;
77 // Given a natural map i : R --> S
78 // f is a matrix over R.
79 // returns a matrix over S.
80 ERROR("MutableMatrix promote not implemented yet");
81 return nullptr;
82#if 0
83 auto result = MutableMatrix::zero_matrix(S, f->n_rows(), f->n_cols(), f->is_dense());
84 return result;
85#endif
86}
87
88MutableMatrix /* or null */ *rawMutableMatrixLift(int *success_return,
89 const Ring *R,
90 const MutableMatrix *f)
91{
92 // Given a natural map i : R --> S
93 // f is a matrix over S.
94 // returns a matrix over R.
95
96 // ERROR("MutableMatrix lift not implemented yet");
97 (void) R;
98 (void) f;
99 *success_return = 0;
100 return nullptr;
101#if 0
102 auto result = MutableMatrix::zero_matrix(R, f->n_rows(), f->n_cols(), f->is_dense());
103 *success_return = 1;
104 return result;
105#endif
106}
107
109{
110 size_t nrows = M->n_rows();
111 return static_cast<int>(nrows);
112}
113
115{
116 size_t ncols = M->n_cols();
117 return static_cast<int>(ncols);
118}
119
121{
122 int nrows = static_cast<int>(M->n_rows());
123 int ncols = static_cast<int>(M->n_cols());
124 const Ring *R = M->get_ring();
125 for (long i = 0; i < nelems; i++)
126 {
127 int r = rawRandomInt(nrows);
128 int c = rawRandomInt(ncols);
129 ring_elem a = R->random();
130 if (!R->is_zero(a)) M->set_entry(r, c, R->random());
131 }
132}
133
135 double density,
136 int special_type)
137/* special_type: 0 is general, 1 is (strictly) upper triangular. */
138{
139 bool doing_fraction = false;
140 int threshold = 0;
141
142 int nrows = static_cast<int>(M->n_rows());
143 int ncols = static_cast<int>(M->n_cols());
144 const Ring *R = M->get_ring();
145
146 if (density != 1.0)
147 {
148 doing_fraction = true;
149 threshold = static_cast<int>(density * 10000);
150 }
151
152 if (special_type == 0)
153 {
154 for (int i = 0; i < ncols; i++)
155 for (int j = 0; j < nrows; j++)
156 {
157 if (doing_fraction)
158 {
159 int32_t u = rawRandomInt((int32_t)10000);
160 if (u > threshold) continue;
161 }
162 ring_elem a = R->random();
163 if (!R->is_zero(a)) M->set_entry(j, i, a);
164 }
165 }
166 else if (special_type == 1)
167 {
168 for (int i = 0; i < ncols; i++)
169 {
170 int top = (i >= nrows ? nrows : i);
171 for (int j = 0; j < top; j++)
172 {
173 if (doing_fraction)
174 {
175 int32_t u = rawRandomInt((int32_t)10000);
176 if (u > threshold) continue;
177 }
178 ring_elem a = R->random();
179 if (!R->is_zero(a)) M->set_entry(j, i, a);
180 }
181 }
182 }
183}
184
185const RingElement /* or null */ *
187{
188 if (r < 0 || r >= M->n_rows())
189 {
190 ERROR("matrix row index %d out of range 0 .. %d", r, M->n_rows() - 1);
191 return nullptr;
192 }
193 if (c < 0 || c >= M->n_cols())
194 {
195 ERROR("matrix column index %d out of range 0 .. %d", c, M->n_cols() - 1);
196 return nullptr;
197 }
199 M->get_entry(r, c, result);
201}
202
205{
206 try
207 {
208 int ncols = M->n_cols();
209 int nrows = M->n_rows();
210 if(nrows < 0 || ncols < 0)
211 {
212 ERROR("internal error: matrix has a negative size %d by %d",
213 nrows,
214 ncols);
215 return nullptr;
216 }
217 engine_RawRingElementArrayArray entries =
218 getmemarraytype(engine_RawRingElementArrayArray, nrows);
219 entries->len = nrows;
220 for(int r = 0; r < nrows; r++)
221 {
222 engine_RawRingElementArray currRow =
223 getmemarraytype(engine_RawRingElementArray, ncols);
224 currRow->len = ncols;
225 entries->array[r] = currRow;
226 }
227 for(int r = 0; r < nrows; r++)
228 {
229 for(int c = 0; c < ncols; c++)
230 {
232 M->get_entry(r, c, result);
233 entries->array[r]->array[c] =
235 }
236 }
237 return entries;
238 } catch (const exc::engine_error& e)
239 {
240 ERROR(e.what());
241 return nullptr;
242 }
243 return nullptr;
244}
245
246
248 int r,
249 int c,
250 const RingElement *a)
251{
252 const Ring *R = M->get_ring();
253 if (R != a->get_ring())
254 {
255 ERROR("expected same ring");
256 return 0;
257 }
258 if (r < 0 || r >= M->n_rows())
259 {
260 ERROR("row index %d out of range 0..%d", r, M->n_rows() - 1);
261 return 0;
262 }
263 if (c < 0 || c >= M->n_cols())
264 {
265 ERROR("column index %d out of range 0..%d", c, M->n_cols() - 1);
266 return 0;
267 }
268
269 M->set_entry(r, c, a->get_value());
270 return 1;
271}
272
274/* swap rows: row(i) <--> row(j) */
275{
276 if (i < 0 || j < 0 || i >= M->n_rows() || j >= M->n_rows())
277 {
278 ERROR("row index out of range");
279 return 0;
280 }
281
282 M->interchange_rows(i, j);
283 return 1;
284}
285
287/* swap columns: column(i) <--> column(j) */
288{
289 if (i < 0 || j < 0 || i >= M->n_cols() || j >= M->n_cols())
290 {
291 ERROR("column index out of range");
292 return 0;
293 }
294
295 M->interchange_columns(i, j);
296 return 1;
297}
298
300 int i,
301 const RingElement *r,
302 int j,
303 M2_bool opposite_mult)
304/* row(i) <- row(i) + r * row(j) */
305{
306 (void) opposite_mult;
307 const Ring *R = M->get_ring();
308 if (R != r->get_ring())
309 {
310 ERROR("expected same ring");
311 return 0;
312 }
313 if (i < 0 || j < 0 || i >= M->n_rows() || j >= M->n_rows())
314 {
315 ERROR("row index out of range");
316 return 0;
317 }
318
319 M->row_op(i, r->get_value(), j);
320 return 1;
321}
322
324 int i,
325 const RingElement *r,
326 int j,
327 M2_bool opposite_mult)
328/* column(i) <- column(i) + r * column(j) */
329{
330 (void) opposite_mult;
331 const Ring *R = M->get_ring();
332 if (R != r->get_ring())
333 {
334 ERROR("expected same ring");
335 return 0;
336 }
337 if (i < 0 || j < 0 || i >= M->n_cols() || j >= M->n_cols())
338 {
339 ERROR("column index out of range");
340 return 0;
341 }
342
343 M->column_op(i, r->get_value(), j);
344 return 1;
345}
346
348 const RingElement *r,
349 int i,
350 M2_bool opposite_mult)
351/* row(i) <- r * row(i) */
352{
353 (void) opposite_mult;
354 const Ring *R = M->get_ring();
355 if (R != r->get_ring())
356 {
357 ERROR("expected same ring");
358 return 0;
359 }
360 if (i < 0 || i >= M->n_rows())
361 {
362 ERROR("row index out of range");
363 return 0;
364 }
365 M->scale_row(i, r->get_value());
366 return 1;
367}
368
370 const RingElement *r,
371 int i,
372 M2_bool opposite_mult)
373/* column(i) <- r * column(i) */
374{
375 (void) opposite_mult;
376 const Ring *R = M->get_ring();
377 if (R != r->get_ring())
378 {
379 ERROR("expected same ring");
380 return 0;
381 }
382 if (i < 0 || i >= M->n_cols())
383 {
384 ERROR("column index out of range");
385 return 0;
386 }
387 M->scale_column(i, r->get_value());
388 return 1;
389}
390
392/* Insert n_to_add columns directly BEFORE column i. */
393{
394 return M->insert_columns(i, n_to_add);
395}
396
398/* Insert n_to_add rows directly BEFORE row i. */
399{
400 return M->insert_rows(i, n_to_add);
401}
402
404/* Delete columns i .. j from M */ { return M->delete_columns(i, j); }
406/* Delete rows i .. j from M */ { return M->delete_rows(i, j); }
408 int c1,
409 int c2,
410 const RingElement *a1,
411 const RingElement *a2,
412 const RingElement *b1,
413 const RingElement *b2,
414 M2_bool opposite_mult)
415/* column(c1) <- a1 * column(c1) + a2 * column(c2)
416 column(c2) <- b1 * column(c1) + b2 * column(c2)
417*/
418{
419 (void) opposite_mult;
420 const Ring *R = M->get_ring();
421 if (a1->get_ring() != R || a2->get_ring() != R || b1->get_ring() != R ||
422 b2->get_ring() != R)
423 {
424 ERROR("expected elements in the same ring");
425 return 0;
426 }
427 return M->column2by2(c1,
428 c2,
429 a1->get_value(),
430 a2->get_value(),
431 b1->get_value(),
432 b2->get_value());
433}
434
436 int r1,
437 int r2,
438 const RingElement *a1,
439 const RingElement *a2,
440 const RingElement *b1,
441 const RingElement *b2,
442 M2_bool opposite_mult)
443/* row(r1) <- a1 * row(r1) + a2 * row(r2)
444 row(r2) <- b1 * row(r1) + b2 * row(r2)
445*/
446{
447 (void) opposite_mult;
448 const Ring *R = M->get_ring();
449 if (a1->get_ring() != R || a2->get_ring() != R || b1->get_ring() != R ||
450 b2->get_ring() != R)
451 {
452 ERROR("expected elements in the same ring");
453 return 0;
454 }
455 return M->row2by2(r1,
456 r2,
457 a1->get_value(),
458 a2->get_value(),
459 b1->get_value(),
460 b2->get_value());
461}
462
464/* Returns false if M is not mutable, or lo, or hi are out of range */
465{
466 (void) M;
467 (void) lo;
468 (void) hi;
469 ERROR("not re-implemented yet");
470 return false;
471}
472
474 int start,
475 M2_arrayint perm)
476/* if perm = [p0 .. pr], then row(start + i) --> row(start + pi), and
477 all other rows are unchanged. p0 .. pr should be a permutation of 0..r */
478{
479 size_t nrows = M->n_rows();
480 if (start < 0 || start + perm->len > nrows)
481 {
482 ERROR("row indices out of range");
483 return false;
484 }
485 for (int i = 0; i < perm->len; i++)
486 {
487 int r = start + perm->array[i];
488 if (r < 0 || r >= nrows)
489 {
490 ERROR("row indices out of range");
491 return false;
492 }
493 }
494 return M->row_permute(start, perm);
495}
496
498 int start,
499 M2_arrayint perm)
500/* if perm = [p0 .. pr], then column(start + i) --> column(start + pi), and
501 all other rows are unchanged. p0 .. pr should be a permutation of 0..r */
502{
503 size_t ncols = M->n_cols();
504 if (start < 0 || start + perm->len > ncols)
505 {
506 ERROR("column indices out of range");
507 return false;
508 }
509 for (int i = 0; i < perm->len; i++)
510 {
511 int r = start + perm->array[i];
512 if (r < 0 || r >= ncols)
513 {
514 ERROR("column indices out of range");
515 return false;
516 }
517 }
518 return M->column_permute(start, perm);
519}
520
522 int c1,
523 int c2)
524{
525 ring_elem a;
526 M->dot_product(c1, c2, a);
527 return RingElement::make_raw(M->get_ring(), a);
528}
529
531{
532 return M->is_zero();
533}
534
536 const MutableMatrix *N)
537/* This checks that the entries of M,N are the same */
538{
539 return M->is_equal(N);
540}
541
543{
544 try
545 {
546 return internMutableMatrix(M->transpose());
547 } catch (const exc::engine_error& e)
548 {
549 ERROR(e.what());
550 return nullptr;
551 }
552}
553
555{
556 return M->is_dense();
557}
558
560{
561 return internMutableMatrix(M->copy(prefer_dense));
562}
563
565 M2_arrayint rows,
566 M2_arrayint cols,
567 engine_RawRingElementArray values)
568{
569 return M->set_values(rows, cols, values);
570}
571
573/* Using row and column operations, use unit pivots to reduce the matrix */
574{
575 M->reduce_by_pivots();
576 return true;
577}
578
580 M2_arrayint rows,
581 M2_arrayint cols)
582{
583 return internMutableMatrix(M->submatrix(rows, cols));
584}
585
587 const MutableMatrix *M,
588 M2_arrayint cols)
589{
590 return internMutableMatrix(M->submatrix(cols));
591}
592
593/*******************************
594 ** Computations ***************
595 *******************************/
596
601
602#include <fplll-interface.hpp>
603#include "ntl-interface.hpp"
604
606 MutableMatrix /* or null */ *U,
607 gmp_QQ threshold,
608 int strategy)
609{
610 if (strategy == 0)
611 {
612 return LLLoperations::LLL(M, U, threshold);
613 }
614
615 if (strategy == 4) // fplll, pfush...
616 {
617 return fp_LLL(M, U, strategy);
618 }
619
620 long a = mpz_get_si(mpq_numref(threshold));
621 long b = mpz_get_si(mpq_denref(threshold));
622 return ntl_LLL(M, U, a, b, strategy);
623}
624
626{
627 (void) M;
628#ifdef DEVELOPMENT
629#warning "implement smith"
630#endif
631 ERROR("not implemented yet");
632 return 0;
633}
634
636{
637 (void) M;
638#ifdef DEVELOPMENT
639#warning "implement hermite"
640#endif
641 ERROR("not implemented yet");
642 return 0;
643}
644
645/***************************************************
646 ***** Lapack routines for dense mutable matrices **
647 ***************************************************/
648
649/* Each of the following routines accepts honest MutableMatrix arguments,
650 and returns false if there is an error. The return values are placed into
651 some of the (already existing) parameters of the routine */
652
654 MutableMatrix *L,
655 MutableMatrix *U)
656{
657 try
658 {
659 return A->LU(L, U);
660 } catch (const exc::engine_error& e)
661 {
662 ERROR(e.what());
663 return nullptr;
664 }
665}
666
668 MutableMatrix *LU,
669 const MutableMatrix* v,
670 int i)
671{
672 try
673 {
674 // FIXME: can we not allocate new permutation array?
675 std::vector<size_t> perm = M2_arrayint_to_stdvector<size_t>(P);
676 return LU->LUincremental(perm, v, i);
677 } catch (const exc::engine_error& e)
678 {
679 ERROR(e.what());
680 return nullptr;
681 }
682}
683
684void rawTriangularSolve(MutableMatrix *Lv, /* modified in routine */
685 MutableMatrix *x, /* modified in routine */
686 int m,
687 int strategy)
688{
689 try
690 {
691 Lv->triangularSolve(x, m, strategy);
692 } catch (const exc::engine_error& e)
693 {
694 ERROR(e.what());
695 }
696}
697
699
700#if 0
701M2_bool rawSolve(MutableMatrix *A,
702 MutableMatrix *b,
704{
705 /* Check: A, b, x all have the same ring, either RR or CC */
706 /* Check: if all of these are dense mutable matrices, then
707 call the correct routine */
708 /* Otherwise: give error:
709 OR: make mutable matrices of the correct size, call the correct routine
710 and afterwards, copy to x. */
711 try {
712 const Ring *R = A->get_ring();
713 if (R != b->get_ring() || R != x->get_ring())
714 {
715 ERROR("expected matrices with same base ring");
716 return false;
717 }
718 if (A->n_rows() != b->n_rows())
719 {
720 ERROR("expected matrices with the same number of rows");
721 return false;
722 }
723 return A->solve(b,x);
724 }
725 catch (const exc::engine_error& e) {
726 ERROR(e.what());
727 return false;
728 }
729}
730#endif
731
733 MutableMatrix *eigenvalues,
734 M2_bool is_symm_or_hermitian)
735{
736 try
737 {
738 return A->eigenvalues(eigenvalues, is_symm_or_hermitian);
739 } catch (const exc::engine_error& e)
740 {
741 ERROR(e.what());
742 return false;
743 }
744}
745
747 MutableMatrix *eigenvalues,
748 MutableMatrix *eigenvectors,
749 M2_bool is_symm_or_hermitian)
750{
751 try
752 {
753 return A->eigenvectors(eigenvalues, eigenvectors, is_symm_or_hermitian);
754 } catch (const exc::engine_error& e)
755 {
756 ERROR(e.what());
757 return false;
758 }
759}
760
762 MutableMatrix *Sigma,
763 MutableMatrix *U,
764 MutableMatrix *VT,
765 M2_bool use_divide_and_conquer)
766{
767 try
768 {
769 return A->SVD(Sigma, U, VT, use_divide_and_conquer);
770 } catch (const exc::engine_error& e)
771 {
772 ERROR(e.what());
773 return false;
774 }
775}
776
778 MutableMatrix *b,
779 MutableMatrix *x, /* return value: argument modified */
780 M2_bool assume_full_rank)
781/* Case 1: A is a dense matrix over RR. Then so are b,x.
782 Case 2: A is a dense matrix over CC. Then so are b,x. */
783{
784 try
785 {
786 const Ring *R = A->get_ring();
787 if (R != b->get_ring() || R != x->get_ring())
788 {
789 ERROR("expected matrices with same base ring");
790 return false;
791 }
792 if (A->n_rows() != b->n_rows())
793 {
794 ERROR("expected matrices with the same number of rows");
795 return false;
796 }
797 return A->least_squares(b, x, assume_full_rank);
798 } catch (const exc::engine_error& e)
799 {
800 ERROR(e.what());
801 return false;
802 }
803}
804
806 MutableMatrix *Q,
807 MutableMatrix *R,
808 M2_bool return_QR)
809{
810 try
811 {
812 return A->QR(Q, R, return_QR);
813 } catch (const exc::engine_error& e)
814 {
815 ERROR(e.what());
816 return false;
817 }
818}
819
821// Fast linear algebra routines //
823
825{
826 try
827 {
828 return M->rank();
829 } catch (const exc::engine_error& e)
830 {
831 ERROR(e.what());
832 return -1;
833 }
834}
835
837{
838 try
839 {
840 return A->determinant();
841 } catch (const exc::engine_error& e)
842 {
843 ERROR(e.what());
844 return nullptr;
845 }
846}
847
849{
850 try
851 {
852 MutableMatrix *B = A->invert();
853 if (B==nullptr) ERROR("matrix not invertible");
854 return internMutableMatrix(B);
855 } catch (const exc::engine_error& e)
856 {
857 ERROR(e.what());
858 return nullptr;
859 }
860}
861
863{
864 try
865 {
867 } catch (const exc::engine_error& e)
868 {
869 ERROR(e.what());
870 return nullptr;
871 }
872}
873
875{
876 try
877 {
878 return A->rankProfile(row_profile);
879 } catch (const exc::engine_error& e)
880 {
881 ERROR(e.what());
882 return nullptr;
883 }
884}
885
887{
888 try
889 {
890 return internMutableMatrix(A->nullSpace());
891 } catch (const exc::engine_error& e)
892 {
893 ERROR(e.what());
894 return nullptr;
895 }
896}
897
899 const MutableMatrix *B,
900 int *success)
901{
902 try
903 {
904 *success = 1;
906 if (result != nullptr)
907 {
909 }
910 else
911 {
912 return nullptr;
913 }
914 } catch (const exc::engine_error& e)
915 {
916 *success = 0;
917 ERROR(e.what());
918 return nullptr;
919 }
920}
921
923 const MutableMatrix *B,
924 int *success)
925{
926 try
927 {
928 *success = 1;
930 if (result != nullptr)
931 {
933 }
934 else
935 {
936 return nullptr;
937 }
938 } catch (const exc::engine_error& e)
939 {
940 *success = 0;
941 ERROR(e.what());
942 return nullptr;
943 }
944}
945
947 const MutableMatrix *A,
948 const MutableMatrix *B)
949{
950 try
951 {
952 C->addMultipleTo(A, B);
953 return true;
954 } catch (const exc::engine_error& e)
955 {
956 ERROR(e.what());
957 return false;
958 }
959}
960
962 const MutableMatrix *A,
963 const MutableMatrix *B)
964{
965 try
966 {
967 C->subtractMultipleTo(A, B);
968 return true;
969 } catch (const exc::engine_error& e)
970 {
971 ERROR(e.what());
972 return false;
973 }
974}
975
976/* Note: the following routine is *not* called by the front end, as
977 the * operator for MutableMatrix is implemented directly in d/engine.dd
978*/
980 const MutableMatrix *B)
981{
982 try
983 {
984 return internMutableMatrix(A->mult(B));
985 } catch (const exc::engine_error& e)
986 {
987 ERROR(e.what());
988 return nullptr;
989 }
990}
991
992engine_RawRingElementArray convertRingelemsToArray(
993 const Ring *R,
994 std::vector<M2::ARingZZpFFPACK::ElementType> &elems)
995{
996 size_t len = elems.size();
997 engine_RawRingElementArray result =
998 getmemarraytype(engine_RawRingElementArray, len);
999 result->len = static_cast<int>(len);
1000 for (size_t i = 0; i < len; i++)
1001 result->array[i] = RingElement::make_raw(R, static_cast<int>(elems[i]));
1002
1003 return result;
1004}
1005
1007// returns an array whose coefficients give the characteristic polynomial of the
1008// square matrix A
1009{
1010 (void) A;
1011#if 1
1012#if 0
1013 const Ring *R = A->get_ring();
1016 if (B == 0)
1017 {
1018 ERROR("expected a dense mutable matrix over the ffpack finite field");
1019 return 0;
1020 }
1021 M2::ARingZZpFFPACK::ElementType *elemsA = B->get_Mat()->array();
1022 std::vector<M2::ARingZZpFFPACK::ElementType> charpoly;
1023
1024 // CharPoly isn't there any more (?)
1025 FFPACK::CharPoly(B->get_Mat()->ring().field(), charpoly, A->n_rows(),
1026 elemsA, A->n_rows());
1027
1028 for (size_t i = 0; i < charpoly.size(); i++) std::cout << charpoly[i] << " ";
1029 std::cout << std::endl;
1030 return convertRingelemsToArray(R, charpoly);
1031#else
1032 return nullptr;
1033#endif
1034#else
1035 ERROR("not implemented: configure M2 with --enable-ffpack-fflas");
1036 return 0;
1037#endif
1038}
1039
1041// returns an array whose coefficients give the minimal polynomial of the square
1042// matrix A
1043{
1044 (void) A;
1045#if 1
1046#if 0
1047 const Ring *R = A->get_ring();
1050 if (B == 0)
1051 {
1052 ERROR("expected a dense mutable matrix over the ffpack finite field");
1053 return 0;
1054 }
1055 typedef M2::ARingZZpFFPACK::ElementType Element;
1056 typedef std::vector<Element> Polynomial;
1057
1058 Element *elemsA = B->get_Mat()->array();
1059 size_t n = B->n_rows();
1060 Polynomial minpoly(n);
1061
1062 // the following are uninitialized! This is scratch space for use in the
1063 // algorithm, apparently...
1064 Element *X = new Element[n * (n + 1)];
1065 size_t *P = new size_t[n];
1066
1067 // this is in ffpack 2.3 but not in 2.2, and it might be the wrong name now, was MinPoly before
1068 FFPACK::Protected::Hybrid_KGF_LUK_MinPoly(
1069 B->get_Mat()->ring().field(), minpoly, n, elemsA, n, X, n, P);
1070
1071 delete[] P;
1072 delete[] X;
1073
1074 for (size_t i = 0; i < minpoly.size(); i++) std::cout << minpoly[i] << " ";
1075 std::cout << std::endl;
1076 return convertRingelemsToArray(R, minpoly);
1077#else
1078 return nullptr;
1079#endif
1080#else
1081 ERROR("not implemented: configure M2 with --enable-ffpack-fflas");
1082 return 0;
1083#endif
1084}
1085
1087// Support for RRR and CCC operations //
1089
1090const Matrix /* or null */ *rawMatrixClean(gmp_RR epsilon, const Matrix *M)
1091{
1092 try
1093 {
1094 if (M->get_ring()->get_precision() == 0)
1095 {
1096 ERROR("expected ring over an RR or CC");
1097 return nullptr;
1098 }
1099 return M->clean(epsilon);
1100 } catch (const exc::engine_error& e)
1101 {
1102 ERROR(e.what());
1103 return nullptr;
1104 }
1105}
1106const RingElement /* or null */ *rawRingElementClean(gmp_RR epsilon,
1107 const RingElement *f)
1108{
1109 const Ring *R = f->get_ring();
1110 if (R->get_precision() == 0)
1111 {
1112 ERROR("expected ring over an RR or CC");
1113 return nullptr;
1114 }
1115 return RingElement::make_raw(R, R->zeroize_tiny(epsilon, f->get_value()));
1116}
1118 MutableMatrix *M)
1119{
1120 /* modifies M in place */
1121 try
1122 {
1123 if (M->get_ring()->get_precision() == 0)
1124 {
1125 ERROR("expected ring over an RR or CC");
1126 return nullptr;
1127 }
1128 M->clean(epsilon);
1129 return M;
1130 } catch (const exc::engine_error& e)
1131 {
1132 ERROR(e.what());
1133 return nullptr;
1134 }
1135}
1136
1138{
1139 if (R->get_precision() == 0)
1140 {
1141 ERROR("expected ring over an RR or CC");
1142 return nullptr;
1143 }
1145 mpfr_init2(norm, mpfr_get_prec(p));
1146 mpfr_ui_div(norm, 1, p, MPFR_RNDN);
1147 if (!mpfr_zero_p(norm))
1148 {
1149 ERROR("Lp norm only implemented for p = infinity");
1150 mpfr_clear(norm);
1151 return nullptr;
1152 }
1153 return norm;
1154}
1155
1156gmp_RRorNull rawMatrixNorm(gmp_RR p, const Matrix *M) { return M->norm(p); }
1158{
1159 gmp_RRmutable norm = get_norm_start(p, f->get_ring());
1160 if (!norm) return nullptr; // error already given.
1161 f->get_ring()->increase_maxnorm(norm, f->get_value());
1162 return moveTo_gmpRR(norm);
1163}
1164
1166{
1167 (void) p;
1168 return M->norm();
1169}
1170
1738
1739// Local Variables:
1740// compile-command: "make -C $M2BUILDDIR/Macaulay2/e x-mutablemat.o "
1741// indent-tabs-mode: nil
1742// End:
Lenstra-Lenstra-Lovász integer lattice basis reduction, in place on a MutableMatrix.
M2::ARingZZpFFPACK — Z/p via FFLAS-FFPACK's Givaro::Modular<double> field.
Append-only GC-backed byte buffer used throughout the engine for text output.
Definition dmat.hpp:62
static M2_arrayintOrNull DO(MutableMatrix *M)
static bool LLL(MutableMatrix *M, MutableMatrix *U, gmp_QQ threshold)
Definition LLL.cpp:356
FieldType::Element ElementType
const Ring * get_ring() const
Definition matrix.hpp:134
Matrix * clean(gmp_RR epsilon) const
Definition matrix.cpp:2065
gmp_RRorNull norm(gmp_RR p) const
Definition matrix.cpp:2074
unsigned int hash() const
Definition hash.hpp:106
virtual size_t n_rows() const
virtual size_t n_rows() const =0
virtual bool dot_product(size_t i, size_t j, ring_elem &result) const =0
virtual const RingElement * determinant() const =0
virtual MutableMatrix * copy(bool prefer_dense) const =0
virtual MutableMatrix * nullSpace() const =0
virtual void triangularSolve(MutableMatrix *x, int m, int strategy)=0
virtual bool column2by2(size_t c1, size_t c2, ring_elem a1, ring_elem a2, ring_elem b1, ring_elem b2)=0
MutableMat< MatType > * cast_to_MutableMat()
Definition mat.hpp:139
virtual MutableMatrix * mult(const RingElement *f) const =0
virtual Matrix * to_matrix() const =0
virtual bool row_op(size_t i, ring_elem r, size_t j)=0
virtual bool scale_column(size_t i, ring_elem r)=0
virtual size_t n_cols() const =0
virtual bool interchange_rows(size_t i, size_t j)=0
virtual bool interchange_columns(size_t i, size_t j)=0
virtual bool QR(MutableMatrix *Q, MutableMatrix *R, bool return_QR) const =0
virtual bool is_equal(const MutableMatrix *B) const =0
virtual bool get_entry(size_t r, size_t c, ring_elem &result) const =0
virtual void addMultipleTo(const MutableMatrix *A, const MutableMatrix *B)=0
virtual size_t rank() const =0
Fast linear algebra routines (well, fast for some rings).
virtual M2_arrayintOrNull rankProfile(bool row_profile) const =0
virtual bool SVD(MutableMatrix *Sigma, MutableMatrix *U, MutableMatrix *Vt, bool use_divide_and_conquer) const =0
virtual MutableMatrix * invert() const =0
virtual gmp_RRorNull norm() const =0
virtual bool eigenvectors(MutableMatrix *eigenvals, MutableMatrix *eigenvecs, bool is_symm_or_hermitian) const =0
static MutableMatrix * zero_matrix(const Ring *R, size_t nrows, size_t ncols, bool dense)
Definition mat.cpp:54
virtual bool is_zero() const =0
static MutableMatrix * from_matrix(const Matrix *N, bool is_dense)
Definition mat.cpp:76
virtual bool row2by2(size_t r1, size_t r2, ring_elem a1, ring_elem a2, ring_elem b1, ring_elem b2)=0
virtual bool column_permute(size_t start_col, M2_arrayint perm)=0
virtual MutableMatrix * solveInvertible(const MutableMatrix *B) const =0
virtual bool is_dense() const =0
virtual bool delete_rows(size_t i, size_t j)=0
virtual void reduce_by_pivots()=0
void text_out(buffer &o) const
Definition mat.cpp:89
virtual MutableMatrix * transpose() const =0
virtual bool scale_row(size_t i, ring_elem r)=0
virtual MutableMatrix * submatrix(M2_arrayint rows, M2_arrayint cols) const =0
bool set_values(M2_arrayint rows, M2_arrayint cols, engine_RawRingElementArray values)
Definition mat.cpp:121
virtual bool insert_columns(size_t i, size_t n_to_add)=0
virtual bool eigenvalues(MutableMatrix *eigenvals, bool is_symm_or_hermitian) const =0
virtual bool column_op(size_t i, ring_elem r, size_t j)=0
virtual bool row_permute(size_t start_row, M2_arrayint perm)=0
virtual const Ring * get_ring() const =0
virtual void clean(gmp_RR epsilon)=0
virtual bool insert_rows(size_t i, size_t n_to_add)=0
virtual void subtractMultipleTo(const MutableMatrix *A, const MutableMatrix *B)=0
virtual M2_arrayintOrNull LU(MutableMatrix *L, MutableMatrix *U) const =0
virtual bool delete_columns(size_t i, size_t j)=0
virtual bool set_entry(size_t r, size_t c, const ring_elem a)=0
virtual bool least_squares(const MutableMatrix *b, MutableMatrix *x, bool assume_full_rank) const =0
virtual MutableMatrix * solveLinear(const MutableMatrix *B) const =0
virtual MutableMatrix * rowReducedEchelonForm() const =0
static MutableMatrix * identity(const Ring *R, size_t nrows, bool dense)
Definition mat.cpp:69
Abstract base class for mutable matrices over an arbitrary engine Ring, the in-place counterpart of t...
Definition mat.hpp:79
virtual void increase_maxnorm(gmp_RRmutable norm, const ring_elem f) const
Definition ring.cpp:446
virtual unsigned long get_precision() const
Definition ring.cpp:438
virtual ring_elem zeroize_tiny(gmp_RR epsilon, const ring_elem f) const
Definition ring.cpp:439
virtual bool is_zero(const ring_elem f) const =0
virtual ring_elem random() const
Definition ring.cpp:284
ring_elem get_value() const
Definition relem.hpp:79
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
const Ring * get_ring() const
Definition relem.hpp:81
Front-end-visible "ring element" value: an engine ring_elem paired with the Ring* that gives it meani...
Definition relem.hpp:67
xxx xxx xxx
Definition ring.hpp:102
M2_string to_string()
Definition buffer.cpp:20
Engine error-reporting primitives: ERROR, INTERNAL_ERROR, error, error_message.
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
#define Matrix
Definition factory.cpp:14
MutableMatrix * internMutableMatrix(MutableMatrix *G)
Definition finalize.cpp:200
intern_* helpers that register long-lived engine objects with bdwgc finalisers.
bool fp_LLL(MutableMatrix *M, MutableMatrix *U, int strategy)
Engine-side wrapper around the external fplll lattice-reduction library.
FF_LUComputation — Bareiss-style fraction-free LU over an integral domain.
mpfr_srcptr moveTo_gmpRR(mpfr_ptr _z)
Definition gmp-util.h:153
Inline helpers that move GMP / MPFR / MPFI limbs from malloc-managed storage into the bdwgc heap.
int p
DMat< M2::ARingZZp > DMatZZp
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemarraytype(S, len)
Definition m2-mem.h:142
#define getmemstructtype(S)
Definition m2-mem.h:143
mpfr_srcptr gmp_RR
Definition m2-types.h:148
M2_arrayint M2_arrayintOrNull
Definition m2-types.h:99
engine_RawRingElementArray engine_RawRingElementArrayOrNull
Definition m2-types.h:176
mpfr_ptr gmp_RRmutable
Definition m2-types.h:150
mpfr_srcptr gmp_RRorNull
Definition m2-types.h:149
char M2_bool
Definition m2-types.h:82
mpq_srcptr gmp_QQ
Definition m2-types.h:145
engine_RawRingElementArrayArray engine_RawRingElementArrayArrayOrNull
Definition m2-types.h:180
MutableMatrix — abstract base of every mutable matrix the engine hands across the boundary.
Matrix — the engine's immutable homomorphism F -> G between free modules.
M2_bool rawMutableMatrixIsDense(const MutableMatrix *M)
const RingElement * IM2_MutableMatrix_get_entry(const MutableMatrix *M, int r, int c)
engine_RawRingElementArrayOrNull rawLinAlgMinPoly(MutableMatrix *A)
M2_bool IM2_MutableMatrix_insert_columns(MutableMatrix *M, int i, int n_to_add)
M2_string IM2_MutableMatrix_to_string(const MutableMatrix *M)
MutableMatrix * rawMutableMatrixClean(gmp_RR epsilon, MutableMatrix *M)
const RingElement * rawRingElementClean(gmp_RR epsilon, const RingElement *f)
M2_bool IM2_MutableMatrix_set_entry(MutableMatrix *M, int r, int c, const RingElement *a)
M2_bool rawEigenvalues(MutableMatrix *A, MutableMatrix *eigenvalues, M2_bool is_symm_or_hermitian)
long rawLinAlgRank(MutableMatrix *M)
M2_bool IM2_MutableMatrix_sort_columns(MutableMatrix *M, int lo, int hi)
M2_bool IM2_MutableMatrix_column_scale(MutableMatrix *M, const RingElement *r, int i, M2_bool opposite_mult)
M2_bool IM2_SmithNormalForm(MutableMatrix *M)
M2_bool IM2_MutableMatrix_column_swap(MutableMatrix *M, int i, int j)
M2_bool IM2_MutableMatrix_delete_columns(MutableMatrix *M, int i, int j)
M2_bool rawLLL(MutableMatrix *M, MutableMatrix *U, gmp_QQ threshold, int strategy)
M2_bool IM2_MutableMatrix_insert_rows(MutableMatrix *M, int i, int n_to_add)
M2_bool IM2_MutableMatrix_row_operation(MutableMatrix *M, int i, const RingElement *r, int j, M2_bool opposite_mult)
M2_bool IM2_MutableMatrix_is_zero(const MutableMatrix *M)
MutableMatrix * rawMutableMatrixLift(int *success_return, const Ring *R, const MutableMatrix *f)
const Matrix * IM2_MutableMatrix_to_matrix(const MutableMatrix *M)
const Matrix * rawMatrixClean(gmp_RR epsilon, const Matrix *M)
M2_bool rawLinAlgSubMult(MutableMatrix *C, const MutableMatrix *A, const MutableMatrix *B)
void rawTriangularSolve(MutableMatrix *Lv, MutableMatrix *x, int m, int strategy)
M2_bool rawQR(const MutableMatrix *A, MutableMatrix *Q, MutableMatrix *R, M2_bool return_QR)
MutableMatrix * rawLinAlgNullSpace(MutableMatrix *A)
engine_RawRingElementArrayOrNull rawLinAlgCharPoly(MutableMatrix *A)
MutableMatrix * rawMutableMatrixPromote(const Ring *S, const MutableMatrix *f)
M2_bool IM2_HermiteNormalForm(MutableMatrix *M)
M2_bool rawLeastSquares(MutableMatrix *A, MutableMatrix *b, MutableMatrix *x, M2_bool assume_full_rank)
MutableMatrix * rawLinAlgMult(const MutableMatrix *A, const MutableMatrix *B)
gmp_RRorNull rawMutableMatrixNorm(gmp_RR p, const MutableMatrix *M)
MutableMatrix * IM2_MutableMatrix_submatrix(const MutableMatrix *M, M2_arrayint rows, M2_arrayint cols)
M2_bool IM2_MutableMatrix_column_permute(MutableMatrix *M, int start, M2_arrayint perm)
int IM2_MutableMatrix_n_rows(const MutableMatrix *M)
static gmp_RRmutable get_norm_start(gmp_RR p, const Ring *R)
MutableMatrix * IM2_MutableMatrix_copy(MutableMatrix *M, M2_bool prefer_dense)
gmp_RRorNull rawMatrixNorm(gmp_RR p, const Matrix *M)
M2_bool IM2_MutableMatrix_reduce_by_pivots(MutableMatrix *M)
M2_bool IM2_MutableMatrix_row_scale(MutableMatrix *M, const RingElement *r, int i, M2_bool opposite_mult)
engine_RawRingElementArray convertRingelemsToArray(const Ring *R, std::vector< M2::ARingZZpFFPACK::ElementType > &elems)
M2_bool IM2_MutableMatrix_set_values(MutableMatrix *M, M2_arrayint rows, M2_arrayint cols, engine_RawRingElementArray values)
M2_bool rawLinAlgAddMult(MutableMatrix *C, const MutableMatrix *A, const MutableMatrix *B)
MutableMatrix * IM2_MutableMatrix_make(const Ring *R, int nrows, int ncols, M2_bool is_dense)
MutableMatrix * rawLinAlgInverse(MutableMatrix *A)
const RingElement * rawLinAlgDeterminant(MutableMatrix *A)
M2_bool IM2_MutableMatrix_row_2by2(MutableMatrix *M, int r1, int r2, const RingElement *a1, const RingElement *a2, const RingElement *b1, const RingElement *b2, M2_bool opposite_mult)
MutableMatrix * IM2_MutableMatrix_submatrix1(const MutableMatrix *M, M2_arrayint cols)
MutableMatrix * rawLinAlgSolveInvertible(const MutableMatrix *A, const MutableMatrix *B, int *success)
MutableMatrix * rawLinAlgRREF(MutableMatrix *A)
M2_arrayintOrNull rawLinAlgRankProfile(MutableMatrix *A, M2_bool row_profile)
M2_arrayintOrNull rawLUincremental(M2_arrayintOrNull P, MutableMatrix *LU, const MutableMatrix *v, int i)
void rawMutableMatrixFillRandom(MutableMatrix *M, long nelems)
M2_bool IM2_MutableMatrix_is_equal(const MutableMatrix *M, const MutableMatrix *N)
M2_bool rawSVD(MutableMatrix *A, MutableMatrix *Sigma, MutableMatrix *U, MutableMatrix *VT, M2_bool use_divide_and_conquer)
M2_bool IM2_MutableMatrix_column_operation(MutableMatrix *M, int i, const RingElement *r, int j, M2_bool opposite_mult)
MutableMatrix * IM2_MutableMatrix_identity(const Ring *R, int n, M2_bool is_dense)
M2_bool IM2_MutableMatrix_row_swap(MutableMatrix *M, int i, int j)
engine_RawRingElementArrayArrayOrNull IM2_MutableMatrix_get_entries(const MutableMatrix *M)
unsigned int rawMutableMatrixHash(const MutableMatrix *M)
M2_arrayintOrNull rawLU(const MutableMatrix *A, MutableMatrix *L, MutableMatrix *U)
M2_bool IM2_MutableMatrix_row_permute(MutableMatrix *M, int start, M2_arrayint perm)
M2_bool IM2_MutableMatrix_column_2by2(MutableMatrix *M, int c1, int c2, const RingElement *a1, const RingElement *a2, const RingElement *b1, const RingElement *b2, M2_bool opposite_mult)
void rawMutableMatrixFillRandomDensity(MutableMatrix *M, double density, int special_type)
M2_arrayintOrNull IM2_FF_LU(MutableMatrix *M)
gmp_RRorNull rawRingElementNorm(gmp_RR p, const RingElement *f)
int IM2_MutableMatrix_n_cols(const MutableMatrix *M)
MutableMatrix * IM2_MutableMatrix_from_matrix(const Matrix *M, M2_bool is_dense)
MutableMatrix * rawMutableMatrixTranspose(MutableMatrix *M)
M2_bool IM2_MutableMatrix_delete_rows(MutableMatrix *M, int i, int j)
M2_bool rawEigenvectors(MutableMatrix *A, MutableMatrix *eigenvalues, MutableMatrix *eigenvectors, M2_bool is_symm_or_hermitian)
const RingElement * IM2_Matrix_dot_product(const MutableMatrix *M, int c1, int c2)
MutableMatrix * rawLinAlgSolve(const MutableMatrix *A, const MutableMatrix *B, int *success)
Engine-boundary C API for the engine's in-place MutableMatrix, including dense linear algebra.
bool ntl_LLL(MutableMatrix *M, MutableMatrix *U, long numer, long denom, int strategy)
Engine bridge into NTL — type conversions and the NTL-backed LLL entry point.
volatile int x
int32_t rawRandomInt(int32_t max)
Definition random.cpp:44
Engine-boundary C API for the engine's PRNG and rational / real / complex random draws.
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
Ring — the legacy abstract base class for every coefficient and polynomial ring.
ring_elem — the universal value type carried by every Ring* in the engine.
std::vector< T > M2_arrayint_to_stdvector(M2_arrayint arr)
Definition util.hpp:96
Conversion helpers between M2 boundary types and standard C++ containers.