Macaulay2 Engine
Loading...
Searching...
No Matches
matrix.cpp
Go to the documentation of this file.
1// Copyright 1995-2004 Michael E. Stillman
2
3#include "matrix.hpp"
4
5#include <algorithm>
6#include <iostream>
7#include <vector>
8
9#include "interface/gmp-util.h" // for mpz_reallocate_limbs
10#include "interface/random.h"
11
12#include "ExponentVector.hpp"
13#include "style.hpp"
14#include "text-io.hpp"
15#include "ring.hpp"
16#include "comb.hpp"
17#include "polyring.hpp"
18#include "assprime.hpp"
19#include "monideal.hpp"
20#include "relem.hpp"
21#include "freemod.hpp"
22#include "util.hpp"
23
24#include "exptable.h"
25
26#include "matrix-con.hpp"
27
29#include "M2FreeAlgebra.hpp"
30
31
33 const FreeModule *cols0,
34 const_monomial degree_shift0,
35 VECTOR(vec) & entries0)
36{
37 mTarget = const_cast<FreeModule *>(rows0);
38 mSource = const_cast<FreeModule *>(cols0);
39 mDegreeShift = const_cast<monomial>(degree_shift0);
40 for (int i = 0; i < cols0->rank(); i++) mEntries.push_back(entries0[i]);
41}
42
43unsigned int Matrix::computeHashValue() const
44{
45 unsigned int hashval = 234123 + (7 * n_rows() + 157 * n_cols());
46
47 iterator i(this);
48 for (int c = 0; c < n_cols(); c++)
49 {
50 int count = 0; // only use first 2 non-zero entries in each column
51 for (i.set(c); i.valid(); i.next())
52 {
53 hashval = 34224 * hashval + get_ring()->computeHashValue(i.entry());
54 if (++count > 2) break;
55 }
56 }
57 return hashval;
58}
59
60const Matrix /* or null */ *Matrix::make(const FreeModule *target,
61 int ncols,
62 const engine_RawRingElementArray M)
63{
64 // Checks to make:
65 // each vector in V is over same ring.
66
67 const Ring *R = target->get_ring();
68
69 if (M != nullptr)
70 for (unsigned int i = 0; i < M->len; i++)
71 {
72 if (R != M->array[i]->get_ring())
73 {
74 ERROR("expected vectors in the same ring");
75 return nullptr;
76 }
77 }
78
79 MatrixConstructor mat(target, ncols);
80 if (M != nullptr)
81 {
82 unsigned int next = 0;
83 for (int r = 0; r < target->rank(); r++)
84 for (int c = 0; c < ncols && next < M->len; c++)
85 {
86 mat.set_entry(r, c, M->array[next]->get_value());
87 next++;
88 }
90 }
91 return mat.to_matrix();
92}
93const Matrix /* or null */ *Matrix::make(const FreeModule *target,
94 const FreeModule *source,
95 M2_arrayint deg,
96 const engine_RawRingElementArray M)
97{
98 const Ring *R = target->get_ring();
99 auto D = R->degree_monoid();
100 if (source->get_ring() != R)
101 {
102 ERROR("expected free modules over the same ring");
103 return nullptr;
104 }
105 if (D->n_vars() != static_cast<int>(deg->len))
106 {
107 ERROR("expected degree of matrix to have %d entries", D->n_vars());
108 return nullptr;
109 }
110
111 if (M != nullptr)
112 {
113 for (unsigned int i = 0; i < M->len; i++)
114 {
115 if (R != M->array[i]->get_ring())
116 {
117 ERROR("expected vectors in the same ring");
118 return nullptr;
119 }
120 }
121 }
122
123 monomial degshift = D->make_one();
124 D->from_expvector(deg->array, degshift);
125 MatrixConstructor mat(target, source, degshift);
126
127 if (M != nullptr)
128 {
129 unsigned int next = 0;
130 for (int r = 0; r < target->rank(); r++)
131 {
132 for (int c = 0; c < source->rank(); c++)
133 {
134 mat.set_entry(r, c, M->array[next]->get_value());
135 next++;
136 if (next >= M->len) break;
137 }
138 }
139 }
140 return mat.to_matrix();
141}
142
144 const FreeModule *target,
145 int ncols,
148 const engine_RawRingElementArray entries)
149// returns false if an error, true otherwise.
150// Places the elements into 'mat'.
151{
152 const Ring *R = target->get_ring();
153 for (unsigned int i = 0; i < entries->len; i++)
154 {
155 if (R != entries->array[i]->get_ring())
156 {
157 ERROR("expected vectors in the same ring");
158 return false;
159 }
160 }
161 if (rows->len != cols->len || rows->len != entries->len)
162 {
163 ERROR("sparse matrix creation: encountered different length arrays");
164 return false;
165 }
166 for (int x = 0; x < entries->len; x++)
167 {
168 int r = rows->array[x];
169 int c = cols->array[x];
170 if (r < 0 || r >= target->rank())
171 {
172 ERROR("sparse matrix creation: row index out of range");
173 return false;
174 }
175 if (c < 0 || c >= ncols)
176 {
177 ERROR("sparse matrix creation: column index out of range");
178 return false;
179 }
180 }
181
182 for (int x = 0; x < entries->len; x++)
183 {
184 int r = rows->array[x];
185 int c = cols->array[x];
186 mat.set_entry(r, c, entries->array[x]->get_value());
187 }
188 return true;
189}
190
191const Matrix /* or null */ *Matrix::make_sparse(
192 const FreeModule *target,
193 int ncols,
196 const engine_RawRingElementArray entries)
197{
198 MatrixConstructor mat(target, ncols);
199 if (!Matrix::make_sparse_vecs(mat, target, ncols, rows, cols, entries))
200 return nullptr; // error message has already been sent
202 return mat.to_matrix();
203}
204
205const Matrix /* or null */ *Matrix::make_sparse(
206 const FreeModule *target,
207 const FreeModule *source,
208 M2_arrayint deg,
211 const engine_RawRingElementArray entries)
212{
213#ifdef DEVELOPMENT
214#warning "check that all rings are correct, give error otherwise"
215#endif
216 const Ring *R = target->get_ring();
217 auto D = R->degree_monoid();
218 monomial degshift = D->make_one();
219 D->from_expvector(deg->array, degshift);
220
221 MatrixConstructor mat(target, source, degshift);
223 mat, target, source->rank(), rows, cols, entries))
224 return nullptr; // error message has already been sent
225 return mat.to_matrix();
226}
227
228const Matrix /* or null */ *Matrix::remake(const FreeModule *target,
229 const FreeModule *source,
230 M2_arrayint deg) const
231{
232 if (n_rows() != target->rank() || n_cols() != source->rank())
233 {
234 ERROR("wrong number of rows or columns");
235 return nullptr;
236 }
237 const Ring *R = get_ring();
238 auto D = R->degree_monoid();
239 if (deg->len != D->n_vars())
240 {
241 ERROR("degree for matrix has the wrong length");
242 return nullptr;
243 }
244 const Ring *Rtarget = target->get_ring();
245 const Ring *Rsource = source->get_ring();
246 if (R != Rtarget || Rtarget != Rsource)
247 {
248 ERROR("expected same ring");
249 return nullptr;
250 }
251
252 monomial degshift = D->make_one();
253 D->from_expvector(deg->array, degshift);
254 MatrixConstructor mat(target, source, degshift);
255 for (int i = 0; i < source->rank(); i++)
256 mat.set_column(i, R->copy_vec(mEntries[i]));
257 return mat.to_matrix();
258}
259
260const Matrix /* or null */ *Matrix::remake(const FreeModule *target) const
261{
262 if (n_rows() != target->rank())
263 {
264 ERROR("wrong number of rows");
265 return nullptr;
266 }
267 const Ring *R = get_ring();
268 if (R != target->get_ring())
269 {
270 ERROR("expected same ring");
271 return nullptr;
272 }
273
274 MatrixConstructor mat(target, n_cols());
275 for (int i = 0; i < n_cols(); i++)
276 mat.set_column(i, R->copy_vec(mEntries[i]));
278 return mat.to_matrix();
279}
280
281const Matrix /* or null */ *Matrix::make(const MonomialIdeal *mi)
282{
284 if (P == nullptr)
285 {
286 ERROR("expected a matrix over a polynomial ring");
287 return nullptr;
288 }
289 const Monoid *M = P->getMonoid();
290 monomial mon = M->make_one();
291
292 MatrixConstructor mat(P->make_FreeModule(1), mi->size());
293 int next = 0;
294 for (auto i = mi->beginAtLast(); i != mi->end(); --i) // TODO MES: should go from last() via --i to end()...
295 {
296 M->from_varpower(i->monom().data(), mon);
297 ring_elem f =
299 mat.set_entry(0, next++, f);
300 }
301 M->remove(mon);
302
304 return mat.to_matrix();
305}
306
307ring_elem Matrix::elem(int i, int j) const
308{
309 return get_ring()->get_entry(elem(j), i);
310}
311
312bool Matrix::is_equal(const Matrix &m) const
313{
314 auto R = get_ring();
315 if (this == &m) return true;
316 if (hash() != m.hash()) return false;
317 if (R != m.get_ring()) return false;
318 if (n_rows() != m.n_rows()) return false;
319 if (n_cols() != m.n_cols()) return false;
320 for (int i = 0; i < n_cols(); i++)
321 if (!R->is_equal(elem(i), m.elem(i))) return false;
322 return true;
323}
324
325bool Matrix::is_zero() const
326{
327 for (int i = 0; i < n_cols(); i++)
328 if (elem(i) != nullptr) return false;
329 return true;
330}
331
333{
334 auto R = get_ring();
335 auto D = R->degree_monoid();
336 if (!R->is_graded()) return 0;
337 monomial d = D->make_one();
338 for (int i = 0; i < n_cols(); i++)
339 {
340 if (elem(i) == nullptr) continue;
341 if (!R->vec_is_homogeneous(rows(), elem(i)))
342 {
343 D->remove(d);
344 return 0;
345 }
346
347 R->vec_multi_degree(rows(), elem(i), d);
348 D->divide(d, degree_shift(), d);
349 if (0 != D->compare(d, cols()->degree(i)))
350 {
351 D->remove(d);
352 return 0;
353 }
354 }
355 D->remove(d);
356 return 1;
357}
358
359Matrix *Matrix::homogenize(int v, const std::vector<int> &wts) const
360{
361 auto R = get_ring();
362 MatrixConstructor mat(rows(), n_cols());
363 for (int i = 0; i < n_cols(); i++)
364 mat.set_column(i, R->vec_homogenize(rows(), elem(i), v, wts));
366 return mat.to_matrix();
367}
368
370{
371 if (F->get_ring() != G->get_ring())
372 {
373 ERROR("free modules have different base rings");
374 return nullptr;
375 }
376 MatrixConstructor mat(F, G);
377 return mat.to_matrix();
378}
379
381{
382 const Ring *R = F->get_ring();
383 const ring_elem one = R->from_long(1);
384 MatrixConstructor mat(F, F, nullptr);
385 for (int i = 0; i < F->rank(); i++) mat.set_entry(i, i, R->copy(one));
386 return mat.to_matrix();
387}
388
390{
391 auto R = get_ring();
392 if (R != m.get_ring())
393 {
394 ERROR("matrices have different base rings");
395 return nullptr;
396 }
397 if (rows()->rank() != m.rows()->rank() || cols()->rank() != m.cols()->rank())
398 {
399 ERROR("matrices have different shapes");
400 return nullptr;
401 }
402
403 const FreeModule *F = rows();
404 const FreeModule *G = cols();
405 const_monomial deg;
406
407 if (!rows()->is_equal(m.rows())) F = R->make_FreeModule(n_rows());
408
409 if (!cols()->is_equal(m.cols())) G = R->make_FreeModule(n_cols());
410
411 auto D = R->degree_monoid();
412 if (EQ == D->compare(degree_shift(), m.degree_shift()))
413 deg = degree_shift();
414 else
415 deg = D->make_one();
416
417 MatrixConstructor mat(F, G, deg);
418 for (int i = 0; i < n_cols(); i++)
419 {
420 vec v = R->copy_vec(elem(i));
421 vec w = R->copy_vec(m[i]);
422 R->add_vec_to(v, w);
423 mat.set_column(i, v);
424 }
425 return mat.to_matrix();
426}
427
429{
430 auto R = get_ring();
431 if (R != m.get_ring())
432 {
433 ERROR("matrices have different base rings");
434 return nullptr;
435 }
436 if (rows()->rank() != m.rows()->rank() || cols()->rank() != m.cols()->rank())
437 {
438 ERROR("matrices have different shapes");
439 return nullptr;
440 }
441
442 const FreeModule *F = rows();
443 const FreeModule *G = cols();
444 const_monomial deg;
445
446 if (!rows()->is_equal(m.rows())) F = R->make_FreeModule(n_rows());
447
448 if (!cols()->is_equal(m.cols())) G = R->make_FreeModule(n_cols());
449
450 auto D = R->degree_monoid();
451 if (EQ == D->compare(degree_shift(), m.degree_shift()))
452 deg = degree_shift();
453 else
454 deg = D->make_one();
455
456 MatrixConstructor mat(F, G, deg);
457 for (int i = 0; i < n_cols(); i++)
458 mat.set_column(i, R->subtract_vec(elem(i), m[i]));
459 return mat.to_matrix();
460}
461
463{
465 for (int i = 0; i < n_cols(); i++)
466 mat.set_column(i, get_ring()->negate_vec(elem(i)));
467 return mat.to_matrix();
468}
469
471{
472 const FreeModule *F = rows()->sub_space(r);
473 const FreeModule *G = cols()->sub_space(c);
474 if (F == nullptr || G == nullptr) return nullptr;
475
476 int *minrow = newarray_atomic(int, n_rows());
477 int *maxrow = newarray_atomic(int, n_rows());
478 for (int i = 0; i < n_rows(); i++)
479 {
480 minrow[i] = n_rows();
481 maxrow[i] = -1;
482 }
483
484 for (int i = 0; i < r->len; i++)
485 if (r->array[i] >= 0 && r->array[i] < n_rows())
486 {
487 minrow[r->array[i]] = std::min(minrow[r->array[i]], i);
488 maxrow[r->array[i]] = std::max(maxrow[r->array[i]], i);
489 }
490
492 for (size_t j = 0; j < c->len; j++)
493 {
494 vec v = elem(c->array[j]);
495 for (; v != nullptr; v = v->next)
496 for (int i = minrow[v->comp]; i <= maxrow[v->comp]; i++)
497 if (v->comp == r->array[i])
498 mat.set_entry(i, j, v->coeff);
499 }
500 freemem(minrow);
501 freemem(maxrow);
502 return mat.to_matrix();
503}
504
505Matrix /* or null */ *Matrix::sub_matrix(M2_arrayint c) const
506{
507 const FreeModule *G = cols()->sub_space(c);
508 if (G == nullptr) return nullptr;
509
511 for (unsigned int i = 0; i < c->len; i++)
512 mat.set_column(i, get_ring()->copy_vec(elem(c->array[i])));
513 return mat.to_matrix();
514}
515
516Matrix /* or null */ *Matrix::reshape(const FreeModule *F,
517 const FreeModule *G) const
518// Reshape 'this' : F <--- G, where
519// (rank F)(rank G) = (nrows this)(ncols this)
520{
521 if (F->get_ring() != get_ring() || G->get_ring() != get_ring())
522 {
523 ERROR("reshape: expected same ring");
524 return nullptr;
525 }
526 if (n_rows() * n_cols() != F->rank() * G->rank())
527 {
528 ERROR("reshape: ranks of the free modules are incorrect");
529 return nullptr;
530 }
531
532 // EFFICIENCY: might be better to sort columns at end?
534 for (int c = 0; c < n_cols(); c++)
535 for (vecterm *p = elem(c); p != nullptr; p = p->next)
536 {
537 // Determine new component
538 int loc = c * n_rows() + p->comp;
539 int result_col = loc / F->rank();
540 int result_row = loc % F->rank();
541
542 mat.set_entry(result_row, result_col, p->coeff);
543 }
544 return mat.to_matrix();
545}
546
547Matrix /* or null */ *Matrix::flip(const FreeModule *F, const FreeModule *G)
548{
549 const Ring *R = F->get_ring();
550 if (R != G->get_ring())
551 {
552 ERROR("flip: expected same ring");
553 return nullptr;
554 }
555 const FreeModule *H = F->tensor(G);
556 const FreeModule *K = G->tensor(F);
557
558 MatrixConstructor mat(K, H, nullptr);
559 int next = 0;
560 for (int f = 0; f < F->rank(); f++)
561 for (int g = 0; g < G->rank(); g++)
562 mat.set_column(next++, R->e_sub_i(f + g * F->rank()));
563 return mat.to_matrix();
564}
565
567{
568 const FreeModule *F = cols()->transpose();
569 const FreeModule *G = rows()->transpose();
570 const Ring *R = F->get_ring();
571
573
574 // The efficiency of this code relies on the way of ordering
575 // the sparse vectors (lead term has largest component)
576 iterator i(this);
577 for (int c = 0; c < n_cols(); c++)
578 {
579 for (i.set(c); i.valid(); i.next())
580 {
581 ring_elem f = i.entry();
582 mat.set_entry(c, i.row(), R->antipode(f));
583 }
584 }
585 return mat.to_matrix();
586}
587
588Matrix *Matrix::scalar_mult(const ring_elem r, bool opposite_mult) const
589{
590 auto R = get_ring();
591 auto D = R->degree_monoid();
592 monomial deg = D->make_one();
593 if (!R->is_zero(r)) R->multi_degree(r, deg);
594 D->mult(deg, degree_shift(), deg);
595 MatrixConstructor mat(rows(), cols(), deg);
596 for (int i = 0; i < n_cols(); i++)
597 {
598 vec w = R->copy_vec(elem(i));
599 R->mult_vec_to(w, r, opposite_mult);
600 mat.set_column(i, w);
601 }
602 return mat.to_matrix();
603}
604
606{
607 auto R = get_ring();
608 if (R != m.get_ring())
609 {
610 ERROR("concat: different base rings");
611 return nullptr;
612 }
613 if (n_rows() != m.n_rows())
614 {
615 ERROR("concat: matrices have different numbers of rows");
616 return nullptr;
617 }
618
619 const FreeModule *G = cols()->direct_sum(m.cols());
620 MatrixConstructor mat(rows(), G, nullptr);
621 int i;
622 int nc = n_cols();
623 for (i = 0; i < nc; i++) mat.set_column(i, R->copy_vec(elem(i)));
624 for (i = 0; i < m.n_cols(); i++)
625 mat.set_column(nc + i, R->copy_vec(m.elem(i)));
626 return mat.to_matrix();
627}
628
630{
631 auto R = get_ring();
632 if (R != m->get_ring())
633 {
634 ERROR("concat: different base rings");
635 return nullptr;
636 }
637
638 // direct_sum ignores the degree shift of each summand.
644
645 const FreeModule *F = rows()->direct_sum(m->rows());
646 const FreeModule *G = cols()->direct_sum(m->cols());
647
648 MatrixConstructor mat(F, G, nullptr);
649
650 int i;
651 int nr = n_rows();
652 int nc = n_cols();
653 for (i = 0; i < nc; i++) mat.set_column(i, R->copy_vec(elem(i)));
654 for (i = 0; i < m->n_cols(); i++)
655 mat.set_column(nc + i, R->component_shift(nr, m->elem(i)));
656 return mat.to_matrix();
657}
658
659Matrix *Matrix::mult(const Matrix *m, bool opposite_mult) const
660{
661 const Ring *R = get_ring();
662 if (R != m->get_ring())
663 {
664 ERROR("matrix mult: different base rings");
665 return nullptr;
666 }
667 if (n_cols() != m->n_rows())
668 {
669 ERROR("matrix mult: matrix sizes don't match");
670 return nullptr;
671 }
672
673 auto D = R->degree_monoid();
674 monomial deg = D->make_new(degree_shift());
675 D->mult(deg, m->degree_shift(), deg);
676
677 MatrixConstructor mat(rows(), m->cols(), deg);
678
679 D->remove(deg);
680
681 for (int i = 0; i < m->n_cols(); i++)
682 mat.set_column(i, R->mult_vec_matrix(this, m->elem(i), opposite_mult));
683 return mat.to_matrix();
684}
685
687{
688 auto R = get_ring();
689 if (R != m->get_ring())
690 {
691 ERROR("module tensor: different base rings");
692 return nullptr;
693 }
694 FreeModule *F = rows()->tensor(m->rows());
695 FreeModule *G = rows()->tensor(m->cols());
696 FreeModule *G1 = m->rows()->tensor(cols());
697 G->direct_sum_to(G1);
698 freemem(G1);
699
700 MatrixConstructor mat(F, G, nullptr);
701
702 int i, j, next = 0;
703
704 for (i = 0; i < n_rows(); i++)
705 for (j = 0; j < m->n_cols(); j++)
706 mat.set_column(next++, R->component_shift(i * m->n_rows(), m->elem(j)));
707
708 for (i = 0; i < m->n_rows(); i++)
709 for (j = 0; j < n_cols(); j++)
710 mat.set_column(next++, R->tensor_shift(m->n_rows(), i, elem(j)));
711 return mat.to_matrix();
712}
713
715 const Ring *R,
716 int r,
717 int c,
718 double density,
719 int special_type) // 0: general, 1:upper triangular, others?
720{
721 bool doing_fraction = false;
722 int threshold = 0;
723
724 FreeModule *F = R->make_FreeModule(r);
726 MatrixConstructor mat(F, G, nullptr);
727
728 // Loop through all selected elements, flip a 'fraction_non_zero' coin, and if
729 // non-zero
730 // set that element.
731
732 if (density != 1.0)
733 {
734 doing_fraction = true;
735 threshold = static_cast<int>(density * 10000);
736 }
737
738 if (special_type == 0)
739 {
740 for (int i = 0; i < c; i++)
741 for (int j = 0; j < r; j++)
742 {
743 if (doing_fraction)
744 {
745 int32_t u = rawRandomInt((int32_t)10000);
746 if (u > threshold) continue;
747 }
748 try {
749 mat.set_entry(j, i, R->random());
750 } catch (const exc::engine_error& e) {
751 ERROR(e.what());
752 return nullptr;
753 }
754 }
755 }
756 else if (special_type == 1)
757 {
758 for (int i = 0; i < c; i++)
759 {
760 int top = (i >= r ? r : i);
761 for (int j = 0; j < top; j++)
762 {
763 if (doing_fraction)
764 {
765 int32_t u = rawRandomInt((int32_t)10000);
766 if (u > threshold) continue;
767 }
768 try {
769 mat.set_entry(j, i, R->random());
770 } catch (const exc::engine_error& e) {
771 ERROR(e.what());
772 return nullptr;
773 }
774 }
775 }
776 }
777 return mat.to_matrix();
778}
779
781{
782 auto R = get_ring();
783 if (R != m->get_ring())
784 {
785 ERROR("matrix tensor: different base rings");
786 return nullptr;
787 }
788
789 const FreeModule *F = rows()->tensor(m->rows());
790 const FreeModule *G = cols()->tensor(m->cols());
791
792 auto D = R->degree_monoid();
793 monomial deg = D->make_new(degree_shift());
794 D->mult(deg, m->degree_shift(), deg);
795
796 MatrixConstructor mat(F, G, deg);
797 D->remove(deg);
798 int i, j, next = 0;
799 for (i = 0; i < n_cols(); i++)
800 for (j = 0; j < m->n_cols(); j++)
801 mat.set_column(next++, R->tensor(rows(), elem(i), m->rows(), (*m)[j]));
802 return mat.to_matrix();
803}
804
805Matrix *Matrix::diff(const Matrix *m, int use_coef) const
806{
807 const PolynomialRing *P = get_ring()->cast_to_PolynomialRing();
808 if (P == nullptr)
809 {
810 ERROR("expected a polynomial ring");
811 return nullptr;
812 }
813 if (P != m->get_ring())
814 {
815 ERROR("matrix diff: different base rings");
816 return nullptr;
817 }
818 FreeModule *F1 = rows()->transpose();
819 const FreeModule *F = F1->tensor(m->rows());
820 FreeModule *G1 = cols()->transpose();
821 const FreeModule *G = G1->tensor(m->cols());
822
823 auto D = P->degree_monoid();
824 monomial deg = D->make_one();
825 D->divide(m->degree_shift(), degree_shift(), deg);
826 freemem(F1);
827 freemem(G1);
828
829 MatrixConstructor mat(F, G, deg);
830 D->remove(deg);
831 int i, j, next = 0;
832 for (i = 0; i < n_cols(); i++)
833 for (j = 0; j < m->n_cols(); j++)
834 mat.set_column(
835 next++,
836 P->vec_diff(elem(i), m->rows()->rank(), m->elem(j), use_coef));
837 return mat.to_matrix();
838}
839
840Matrix *Matrix::lead_term(int nparts) const
841// Select those monomials in each column
842// which are maximal in the order under
843// the first n parts of the monomial order.
844{
845 auto R = get_ring();
847
848 for (int i = 0; i < n_cols(); i++)
849 mat.set_column(i, R->vec_lead_term(nparts, rows(), elem(i)));
850 return mat.to_matrix();
851}
852
853#if 0
854// void Matrix::minimal_lead_terms_ZZ(intarray &result) const
855// {
856// int x;
857// M2_arrayint indices;
858// array<TermIdeal *> mis;
859// const array<vec> vecs = _entries;
860// indices = rows()->sort(vecs, NULL, 0, 1);
861// const PolynomialRing *P = get_ring()->cast_to_PolynomialRing();
862// const FreeModule *Rsyz = P->get_Rsyz(); // NULL if not a quotient ring.
863// FreeModule *Gsyz = P->make_FreeModule(vecs.length());
864// for (x=0; x<n_cols(); x++)
865// mis.append(new TermIdeal(P,Gsyz));
866// for (int i=0; i<vecs.length(); i++)
867// {
868// vec v = vecs[indices->array[i]];
869// vec gsyz, rsyz;
870// if (v == NULL) continue;
871// if (TI_TERM != mis[v->comp]->search(v->coeff, v->monom, gsyz, rsyz))
872// {
873// mis[v->comp]->insert_minimal(
874// new tagged_term(P->getCoefficientRing()->copy(v->coeff),
875// P->getMonoid()->make_new(v->monom),
876// NULL,
877// NULL));
878// result.append(indices->array[i]);
879// }
880// Gsyz->remove(gsyz);
881// if (rsyz != NULL) Rsyz->remove(rsyz);
882// }
883// for (x=0; x<n_cols(); x++)
884// freemem(mis[x]);
885// }
886#endif
887
888#if 0
889// void Matrix::minimal_lead_terms(intarray &result) const
890// {
891// if (get_ring()->getCoefficientRing()->is_ZZ())
892// {
893// minimal_lead_terms_ZZ(result);
894// return;
895// }
896// M2_arrayint indices;
897// intarray vp;
898// array<MonomialIdeal *> mis;
899// const array<vec> vecs = _entries;
900// indices = rows()->sort(vecs, NULL, 0, 1);
901// for (int x=0; x<n_rows(); x++)
902// mis.append(new MonomialIdeal(get_ring()));
903// for (int i=0; i<vecs.length(); i++)
904// {
905// vec v = vecs[indices->array[i]];
906// if (v == NULL) continue;
907// // Reduce each one in turn, and replace.
908// Bag *junk_bag;
909// vp.resize(0);
910// rows()->lead_varpower(v, vp);
911// if (!mis[v->comp]->search(vp.data(),junk_bag))
912// {
913// Bag *b = new Bag(indices->array[i], vp);
914// mis[v->comp]->insert(b);
915// result.append(indices->array[i]);
916// }
917// }
918// }
919//
920#endif
921
923{
924 const PolynomialRing *R = get_ring()->cast_to_PolynomialRing();
925 if (R != nullptr)
926 {
927 int n = R->n_vars();
928 int nsupp = 0;
929 exponents_t exp = newarray_atomic(int, R->n_vars());
930 exponents_t exp2 = newarray_atomic(int, R->n_vars());
931 for (int i = 0; i < R->n_vars(); i++) exp[i] = exp2[i] = 0;
932 for (int j = 0; j < n_cols(); j++)
933 for (vec v = elem(j); v != nullptr; v = v->next)
934 for (Nterm& f : v->coeff)
935 {
936 R->getMonoid()->to_expvector(f.monom, exp2);
937 for (int k = 0; k < n; k++)
938 if (exp2[k] != 0 && exp[k] == 0)
939 {
940 exp[k] = 1;
941 if (++nsupp == n) goto out;
942 }
943 }
944out:
946 int next = 0;
947 for (int i = 0; i < n; i++)
948 if (exp[i] > 0) result->array[next++] = i;
949 freemem(exp);
950 freemem(exp2);
951 return result;
952 }
953
954 // FreeAlgebraOrQuotient matrix support
955 const M2FreeAlgebraOrQuotient* Q = dynamic_cast<const M2FreeAlgebraOrQuotient*>(get_ring());
956 if (Q != nullptr)
957 {
958 int n = Q->n_vars();
959 int nsupp = 0;
960 std::vector<int> exp,exp2; // commutative code above uses newarray_atomic. Is std::vector ok?
961 for (int i = 0; i < n; i++)
962 exp.push_back(0);
963 for (int j = 0; j < n_cols() && nsupp < n; j++)
964 for (vec v = elem(j); v != nullptr && nsupp < n; v = v->next)
965 {
966 auto f = Q->toPoly(v->coeff);
967 for (auto t = f->cbegin(); t != f->cend(); ++t)
968 {
969 Q->freeAlgebra().monoid().support(t.monom(),exp2);
970 for (int k = 0; k < exp2.size(); k++)
971 {
972 if (exp[exp2[k]] == 0)
973 {
974 exp[exp2[k]] = 1;
975 if (++nsupp == n) break;
976 }
977 }
978 }
979 }
980
982 int next = 0;
983 for (int i = 0; i < n; i++)
984 if (exp[i] > 0) result->array[next++] = i;
985 //freemem(exp);
986 //freemem(exp2);
987 return result;
988 }
989
990 ERROR("expected a polynomial ring");
991 return nullptr;
992}
993
995{
996 const PolynomialRing *R = get_ring()->cast_to_PolynomialRing();
997 if (R == nullptr)
998 {
999 ERROR("expected polynomial ring");
1000 return nullptr;
1001 }
1003 MatrixConstructor cons_monoms(R->make_FreeModule(1), 0);
1004 for (int i = 0; i < n_cols(); i++)
1005 {
1006 int var, exp;
1007 vec u = elem(i);
1008 vec v = R->vec_top_coefficient(u, var, exp);
1009 result.append(v);
1010 if (v == nullptr)
1011 cons_monoms.append(v);
1012 else
1013 {
1014 ring_elem b;
1015 if (var < R->n_vars())
1016 {
1017 ring_elem a = R->var(var);
1018 b = R->power(a, exp);
1019 }
1020 else
1021 {
1022 b = R->from_long(1);
1023 }
1024 vec w = R->make_vec(0, b);
1025 cons_monoms.append(w);
1026 }
1027 }
1028 monoms = cons_monoms.to_matrix();
1029 return result.to_matrix();
1030}
1031
1033{
1034 gc_vector<int> keep;
1035 const PolynomialRing *P = get_ring()->cast_to_PolynomialRing();
1036 if (P == nullptr)
1037 {
1038 ERROR("expected polynomial ring");
1039 return nullptr;
1040 }
1041 int nslots = P->getMonoid()->n_slots(nparts);
1042 for (int i = 0; i < n_cols(); i++)
1043 if (P->vec_in_subring(nslots, elem(i))) keep.push_back(i);
1044 return stdvector_to_M2_arrayint<int>(keep);
1045}
1046
1048{
1049 gc_vector<int> keep;
1050 const PolynomialRing *P = get_ring()->cast_to_PolynomialRing();
1051 if (P == nullptr)
1052 {
1053 ERROR("expected polynomial ring");
1054 return nullptr;
1055 }
1056 int nslots = P->getMonoid()->n_slots(nparts);
1057 for (int i = 0; i < n_cols(); i++)
1058 if (!P->vec_in_subring(nslots, elem(i))) keep.push_back(i);
1059 return stdvector_to_M2_arrayint<int>(keep);
1060}
1061
1062Matrix *Matrix::divide_by_var(int n, int maxd, int &maxdivided) const
1063{
1064 const PolynomialRing *P = get_ring()->cast_to_PolynomialRing();
1065 if (P == nullptr)
1066 {
1067 ERROR("expected polynomial ring");
1068 return nullptr;
1069 }
1070 MatrixConstructor mat(rows(), 0);
1071 maxdivided = 0;
1072 for (int i = 0; i < n_cols(); i++)
1073 {
1074 if (elem(i) != nullptr)
1075 {
1076 int lo, hi;
1077 P->vec_degree_of_var(n, elem(i), lo, hi);
1078 if (maxd >= 0 && lo > maxd) lo = maxd;
1079 if (lo > maxdivided) maxdivided = lo;
1080 mat.append(P->vec_divide_by_var(n, lo, elem(i)));
1081 }
1082 }
1083 return mat.to_matrix();
1084}
1085
1086// ideal operations
1087Matrix /* or null */ *Matrix::koszul(int p) const
1088{
1089 if (n_rows() != 1)
1090 {
1091 ERROR("expected a matrix with one row");
1092 return nullptr;
1093 }
1094
1095 FreeModule *F = cols()->exterior(p - 1);
1096 FreeModule *G = cols()->exterior(p);
1097 const Ring *R = get_ring();
1098 MatrixConstructor mat(F, G, degree_shift());
1099 if (p <= 0 || p > n_cols()) return mat.to_matrix();
1100
1101 Subsets C(n_cols(), p);
1102 Subset a(p, 0);
1103 for (int c = 0; c < G->rank(); c++)
1104 {
1105 C.decode(c, a);
1106 int negate = ((p % 2) != 0);
1107 for (int r = p - 1; r >= 0; r--)
1108 {
1109 negate = !negate;
1110 size_t x = C.encodeBoundary(r, a);
1111 ring_elem f = elem(0, static_cast<int>(a[r]));
1112 if (negate) R->negate_to(f);
1113
1114 mat.set_entry(static_cast<int>(x), c, f);
1115 }
1116 }
1117 return mat.to_matrix();
1118}
1119
1121// koszul monomials //////////////////////
1124{
1126 if (P == nullptr)
1127 {
1128 ERROR("expected polynomial ring");
1129 return nullptr;
1130 }
1131 const Monoid *M = P->getMonoid();
1132 VECTOR(Bag *) new_elems;
1133
1134 for (int i = 0; i < A->n_cols(); i++)
1135 {
1136 vec v = A->elem(i);
1137 if (v == nullptr) continue;
1138 Bag *b = new Bag(i);
1139 M->to_varpower(P->lead_flat_monomial(v->coeff), b->monom());
1140 new_elems.push_back(b);
1141 }
1142
1143 MonomialIdeal *result = new MonomialIdeal(P, new_elems);
1144 return result;
1145}
1147{
1148 int sign = 0;
1149 int sum = 0;
1150 for (int i = 0; i < n; i++)
1151 {
1152 int e = a[i] - b[i];
1153 if (e < 0) return 0;
1154 exp[i] = e;
1155 sign += sum * e;
1156 sum += b[i];
1157 }
1158 sign %= 2;
1159 if (sign == 0) return 1;
1160 return -1;
1161}
1162Matrix /* or null */ *Matrix::koszul_monomials(int nskew,
1163 const Matrix *r,
1164 const Matrix *c)
1165// The first nskew variables are considered skew commuting for the purpose of
1166// computing signs.
1167{
1168 // First check rings: r,c,'this' should be row vectors.
1169 // and the ring should be a polynomial ring
1170 const FreeModule *F = r->cols();
1171
1173 if (P == nullptr)
1174 {
1175 ERROR("expected polynomial ring");
1176 return nullptr;
1177 }
1178 const MonomialIdeal *A = makemonideal(r);
1179
1180 const Ring *K = P->getCoefficients();
1181 const Monoid *M = P->getMonoid();
1182
1183 MatrixConstructor mat(F, c->cols(), nullptr);
1184
1185 int nvars = M->n_vars();
1186 int *skew_list = newarray_atomic(int, nskew);
1187 for (int j = 0; j < nskew; j++) skew_list[j] = j;
1188 SkewMultiplication skew(nvars, nskew, skew_list);
1189 int ncols = c->n_cols();
1190
1191 exponents_t aexp = newarray_atomic(int, nvars);
1192 exponents_t bexp = newarray_atomic(int, nvars);
1193 exponents_t result_exp = newarray_atomic(int, nvars);
1194 monomial m = M->make_one();
1195 VECTOR(Bag *) divisors;
1196 for (int i = 0; i < ncols; i++)
1197 {
1198 if (c->elem(i) == nullptr) continue;
1199 const_monomial a = P->lead_flat_monomial(c->elem(i)->coeff);
1200 M->to_expvector(a, aexp);
1201 divisors.clear();
1202 A->find_all_divisors(aexp, divisors);
1203 for (int j = 0; j < divisors.size(); j++)
1204 {
1205 int rownum = divisors[j]->basis_elem();
1206 const_monomial b = P->lead_flat_monomial(r->elem(rownum)->coeff);
1207 M->to_expvector(b, bexp);
1208 exponents::divide(nvars, aexp, bexp, result_exp);
1209 int sign = skew.mult_sign(result_exp, bexp);
1210 if (sign != 0)
1211 {
1212 M->from_expvector(result_exp, m);
1213 ring_elem s = (sign > 0 ? K->one() : K->minus_one());
1214 ring_elem f = P->make_flat_term(s, m);
1215 mat.set_entry(rownum, i, f);
1216 }
1217 }
1218 }
1219 freemem(aexp);
1220 freemem(bexp);
1221 freemem(result_exp);
1222 return mat.to_matrix();
1223}
1224
1225Matrix /* or null */ *Matrix::koszul(const Matrix *r, const Matrix *c)
1226{
1227 // First check rings: r,c,'this' should be row vectors.
1228 // and the ring should be a polynomial ring
1229 const FreeModule *F = r->cols();
1230
1232 if (P == nullptr) return nullptr;
1233 const Ring *K = P->getCoefficients();
1234 const Monoid *M = P->getMonoid();
1235
1236 MatrixConstructor mat(F, c->cols(), nullptr);
1237
1238 int nvars = M->n_vars();
1239 int nrows = r->n_cols();
1240 int ncols = c->n_cols();
1241 const_monomial a, b;
1242 exponents_t aexp = newarray_atomic(int, nvars);
1243 exponents_t bexp = newarray_atomic(int, nvars);
1244 exponents_t result_exp = newarray_atomic(int, nvars);
1245 for (int i = 0; i < ncols; i++)
1246 {
1247 if (c->elem(i) == nullptr) continue;
1248 a = P->lead_flat_monomial(c->elem(i)->coeff);
1249 M->to_expvector(a, aexp);
1250 for (int j = 0; j < nrows; j++)
1251 {
1252 if (r->elem(j) == nullptr) continue;
1253 b = P->lead_flat_monomial(r->elem(j)->coeff);
1254 M->to_expvector(b, bexp);
1255 int sign = signdivide(nvars, aexp, bexp, result_exp);
1256 if (sign != 0)
1257 {
1258 monomial m = M->make_one();
1259 M->from_expvector(result_exp, m);
1260 ring_elem s = (sign > 0 ? K->one() : K->minus_one());
1261 ring_elem f = P->make_flat_term(s, m);
1262 mat.set_entry(j, i, f);
1263 }
1264 }
1265 }
1266 freemem(aexp);
1267 freemem(bexp);
1268 freemem(result_exp);
1269 return mat.to_matrix();
1270}
1271
1273{
1274 const FreeModule *Fp = F->exterior(p);
1275 const FreeModule *Fq = F->exterior(q);
1276 const FreeModule *Fn = F->exterior(p + q);
1277 const FreeModule *G = Fp->tensor(Fq);
1278 const Ring *R = F->get_ring();
1279
1280 MatrixConstructor mat(Fn, G, nullptr);
1281
1282 if (p < 0 || q < 0 || p + q > F->rank()) return mat.to_matrix();
1283
1284 if (p == 0 || q == 0)
1285 {
1286 for (int i = 0; i < G->rank(); i++) mat.set_entry(i, i, R->one());
1287 return mat.to_matrix();
1288 }
1289
1290 Subsets C(F->rank(), p + q);
1291 Subset a(p, 0);
1292 Subset b(q, 0);
1293 Subset c(p + q, 0);
1294 int col = 0;
1295
1296 for (int i = 0; i < Fp->rank(); i++)
1297 {
1298 C.decode(i, a);
1299 for (int j = 0; j < Fq->rank(); j++)
1300 {
1301 C.decode(j, b);
1302 int sgn = Subsets::concatenateSubsets(a, b, c);
1303 if (sgn == 0)
1304 {
1305 col++;
1306 continue;
1307 }
1308 ring_elem r = R->from_long(sgn);
1309 int row = static_cast<int>(C.encode(c));
1310 mat.set_entry(row, col++, r);
1311 }
1312 }
1313 return mat.to_matrix();
1314}
1315
1317{
1318 auto R = get_ring();
1319 int nrows = n_rows();
1320 int ncols = n_cols();
1321
1322 buffer *p = new buffer[nrows];
1323 // buffer *p = new buffer[nrows];
1324 int r;
1325 for (int c = 0; c < ncols; c++)
1326 {
1327 int maxcount = 0;
1328 for (r = 0; r < nrows; r++)
1329 {
1330 ring_elem f = elem(r, c);
1331 R->elem_text_out(p[r], f);
1332 R->remove(f);
1333 if (p[r].size() > maxcount) maxcount = p[r].size();
1334 }
1335 for (r = 0; r < nrows; r++)
1336 for (int k = maxcount + 1 - p[r].size(); k > 0; k--) p[r] << ' ';
1337 }
1338 for (r = 0; r < nrows; r++)
1339 {
1340 p[r] << '\0';
1341 char *s = p[r].str();
1342 o << s << newline;
1343 }
1344 delete[] p;
1345}
1346
1348{
1350 for (int i = 0; i < n_cols(); i++)
1351 if (elem(i) != nullptr) result.append(elem(i), cols()->degree(i));
1352 return result.to_matrix();
1353}
1354
1355#if 0
1356// int Matrix::moneq(const int *exp, int *m, const int *vars, int *exp2) const
1357// // Internal private routine for 'coeffs'.
1358// // exp2 is a scratch value. It is a parameter so we only have to allocate
1359// // it once...
1360// {
1361// get_ring()->getMonoid()->to_expvector(m, exp2);
1362// int nvars = get_ring()->n_vars();
1363// for (int i=0; i<nvars; i++)
1364// {
1365// if (vars[i] == 0) continue;
1366// if (exp[i] != exp2[i])
1367// return 0;
1368// else
1369// exp2[i] = 0;
1370// }
1371// get_ring()->getMonoid()->from_expvector(exp2, m);
1372// return 1;
1373// }
1374// vec Matrix::strip_vector(vec &f, const int *vars,
1375// const FreeModule *F, vec &vmonom) const
1376// // private routine for 'coeffs'
1377// {
1378// if (f == NULL)
1379// {
1380// vmonom = NULL;
1381// return NULL;
1382// }
1383// if (get_ring()->getMonoid() == NULL)
1384// {
1385// vmonom = F->e_sub_i(0);
1386// vec result = f;
1387// f = NULL;
1388// return result;
1389// }
1390// // At this point, we know that we have a polynomial ring
1391// int nvars = get_ring()->n_vars();
1392// int *exp = newarray_atomic(int,nvars);
1393// int *scratch_exp = newarray_atomic(int,nvars);
1394// const Monoid *M = get_ring()->getMonoid();
1395//
1396// M->to_expvector(f->monom, exp);
1397// for (int i=0; i<nvars; i++)
1398// if (vars[i] == 0) exp[i] = 0;
1399//
1400// // the following two lines do NOT work if 'F' is a Schreyer free module,
1401// // but this routine is private to 'coeffs', where this is not the case.
1402// vmonom = F->e_sub_i(0);
1403// M->from_expvector(exp, vmonom->monom);
1404//
1405// vecterm head;
1406// vecterm *newf = &head;
1407// vec result = NULL;
1408//
1409// // Loop through f: if monomial matches 'exp', strip and add to result,
1410// // otherwise leave alone, and place on head list.
1411// while (f != NULL)
1412// {
1413// if (moneq(exp, f->monom, vars, scratch_exp))
1414// {
1415// vec temp = f;
1416// f = f->next;
1417// temp->next = NULL;
1418// rows()->add_to(result, temp);
1419// }
1420// else
1421// {
1422// newf->next = f;
1423// f = f->next;
1424// newf = newf->next;
1425// newf->next = NULL;
1426// }
1427// }
1428// newf->next = NULL;
1429// f = head.next;
1430//
1431// freemem(exp);
1432// freemem(scratch_exp);
1433// return result;
1434// }
1435#endif
1436
1438{
1439 bool keep;
1440 auto R = get_ring();
1442 for (int i = 0; i < n_cols(); i++)
1443 {
1444 vec f = elem(i);
1445 if (f == nullptr) continue;
1446 keep = true;
1447 for (int j = i + 1; j < n_cols(); j++)
1448 {
1449 vec g = elem(j);
1450 if (g == nullptr) continue;
1451 if (R->vec_is_scalar_multiple(f, g))
1452 {
1453 keep = false;
1454 break;
1455 }
1456 }
1457 if (keep) result.append(R->copy_vec(f));
1458 }
1459 return result.to_matrix();
1460}
1461
1462Matrix *Matrix::remove_monomial_factors(bool make_squarefree_only) const
1463// Divide each column v by the maximal monomial 'm' which divides v.
1464// If keep_one is true, divide by somewhat less, making the resulting monomial
1465// factor squarefree.
1466{
1467 auto R = get_ring();
1469 for (int i = 0; i < n_cols(); i++)
1470 {
1471 vec f = R->vec_remove_monomial_factors(elem(i), make_squarefree_only);
1472 result.append(f);
1473 }
1474 return result.to_matrix();
1475}
1476
1477#if 0
1478// // MES Aug 2002
1479// Matrix *Matrix::simplify(int n) const
1480// {
1481// int i,j, keep;
1482// Matrix *result = new Matrix(rows());
1483//
1484// switch (n) {
1485// case 1:
1486// for (i=0; i<n_cols(); i++)
1487// {
1488// vec f = elem(i);
1489// if (f == NULL) continue;
1490// result->append(rows()->copy(f));
1491// }
1492// break;
1493// // case SIMP_SCALAR_MULTIPLES:
1494// case 2:
1495// for (i=0; i<n_cols(); i++)
1496// {
1497// vec f = elem(i);
1498// if (f == NULL) continue;
1499// keep = 1;
1500// for (j=i+1; j<n_cols(); j++)
1501// {
1502// vec g = elem(j);
1503// if (g == NULL) continue;
1504// if (rows()->is_scalar_multiple(f, g))
1505// {
1506// keep = 0;
1507// break;
1508// }
1509// }
1510// if (keep) result->append(rows()->copy(f));
1511// }
1512// break;
1513// case 3:
1514// // Remove multiple monomial divisors (i.e. x^2*f --> x*f)
1515// for (i=0; i<n_cols(); i++)
1516// {
1517// vec f = elem(i);
1518// if (f == NULL) continue;
1519// result->append(rows()->monomial_squarefree(f));
1520// }
1521// break;
1522// case 4:
1523// // Remove monomial divisors (i.e. x*f --> f)
1524// for (i=0; i<n_cols(); i++)
1525// {
1526// vec f = elem(i);
1527// if (f == NULL) continue;
1528// result->append(rows()->remove_monomial_divisors(f));
1529// }
1530// break;
1531// #if 0
1532// // case SIMP_ZEROS:
1533// // break;
1534// // case SIMP_MULTIPLES:
1535// // break;
1536// // case SIMP_AUTO_REDUCE:
1537// // break;
1538// // case SIMP_SQUAREFREE:
1539// // break;
1540// // case SIMP_MONOMIAL_DIVISORS:
1541// // break;
1542// #endif
1543// default:
1544// ERROR("bad simplification type");
1545// return 0;
1546// }
1547//
1548// return result;
1549// }
1550#endif
1551#if 0
1552// // MES Aug 2002
1553// Matrix *Matrix::auto_reduce() const
1554// {
1555// array<vec> vecs;
1556// int i;
1557// for (i=0; i<n_cols(); i++)
1558// vecs.append(rows()->copy(elem(i)));
1559// rows()->auto_reduce(vecs);
1560// Matrix *result = new Matrix(rows());
1561// for (i=0; i<vecs.length(); i++)
1562// result->append(vecs[i]);
1563// return result;
1564// }
1565#endif
1566
1567#if 0
1568// Matrix *Matrix::coeffs(const int *vars, Matrix * &result_monoms) const
1569// {
1570// Matrix *result_coeffs = new Matrix(rows());
1571// result_monoms = new Matrix(get_ring()->make_FreeModule(1)); // One row matrix
1572// for (int j=0; j<n_cols(); j++)
1573// {
1574// vec f = rows()->copy(elem(j));
1575// vec vmonom;
1576// while (f != NULL)
1577// {
1578// vec g = strip_vector(f, vars, result_monoms->rows(), vmonom);
1579// result_coeffs->append(g);
1580// result_monoms->append(vmonom);
1581// }
1582// }
1583// // MES: now sort both matrices...
1584// return result_coeffs;
1585// }
1586#endif
1587
1589// M2FreeAlgebra coeff, monoms commands //
1591
1592// NCMonomials: adds the monomials of 'M' to the hash table 'H'.
1594{
1595 const M2FreeAlgebraOrQuotient* Q = dynamic_cast<const M2FreeAlgebraOrQuotient*>(M->get_ring());
1596 if (Q == nullptr) return;
1597
1598 // should not get here unless 'M' is a matrix over a M2FreeAlgebraOrQuotient
1599
1600 for (int c = 0; c < M->n_cols(); c++)
1601 {
1602 vec v = M->elem(c);
1603 for (; v != nullptr; v = v->next)
1604 {
1605 int comp = v->comp;
1606 auto f = Q->toPoly(v->coeff);
1607 for (auto i = f->cbegin(); i != f->cend(); ++i)
1608 H.insert(i.monom(), comp);
1609 }
1610 }
1611}
1612
1613// NCMonomialMatrix: makes a Matrix (with the same row space as 'M', where 'M' is the
1614// matrix used when constructing H.
1616{
1617 const M2FreeAlgebraOrQuotient* Q = dynamic_cast<const M2FreeAlgebraOrQuotient*>(target->get_ring());
1618 if (Q == nullptr)
1619 {
1620 ERROR("expected NC polynomial algebra");
1621 return nullptr;
1622 }
1623
1624 MatrixConstructor mat(target, 0);
1625 for (auto i = H.begin(); i != H.end(); ++i)
1626 {
1627 ring_elem rf = Q->fromModuleMonom(*i);
1628 vec v = Q->make_vec(i->component(), rf);
1629 mat.append(v);
1630 }
1631
1632 // Finally, we sort them
1633 Matrix *result = mat.to_matrix();
1634
1635 M2_arrayint perm = result->sort(0, -1);
1636 return result->sub_matrix(perm);
1637}
1638
1640{
1641 const M2FreeAlgebraOrQuotient* Q = dynamic_cast<const M2FreeAlgebraOrQuotient*>(M->get_ring());
1642 if (Q == nullptr)
1643 {
1644 ERROR("expected NC polynomial algebra");
1645 return nullptr;
1646 }
1647
1648 // should not get here unless 'M' is a matrix over a M2FreeAlgebraOrQuotient
1649
1650 MatrixConstructor mat(Q->make_FreeModule(H.size()), M->cols());
1651 for (int c = 0; c < M->n_cols(); c++)
1652 {
1653 vec v = M->elem(c);
1654 for (; v != nullptr; v = v->next)
1655 {
1656 int comp = v->comp;
1657 auto f = Q->toPoly(v->coeff);
1658 for (auto i = f->cbegin(); i != f->cend(); ++i)
1659 {
1660 auto result = H.find(i.monom(), comp);
1661 if (result.second)
1662 {
1663 ring_elem cf = Q->from_coefficient(i.coeff());
1664 mat.set_entry(result.first, c, cf);
1665 }
1666 }
1667 }
1668 }
1669 return mat.to_matrix();
1670}
1671
1672// TODO: not done yet!! Although, it is not yet called either.
1673std::pair<Matrix*, Matrix*> NCCoefficientMatrix(const Matrix* M)
1674{
1675 const M2FreeAlgebraOrQuotient* Q = dynamic_cast<const M2FreeAlgebraOrQuotient*>(M->get_ring());
1676 if (Q == nullptr)
1677 {
1678 ERROR("expected NC polynomial algebra");
1679 return {nullptr, nullptr};
1680 }
1681
1683 NCMonomials(H, M);
1684
1685 // now loop through all columns in M, monomials in column:
1686 // find index.
1687 // create coeff
1688 // return matrix constructed.
1689 return {nullptr, nullptr};
1690}
1691
1692// Method to compute monomials for NC polynomial algebra case.
1693// NCMonomials(M:Matrix) --> HashTable, or a set.
1694// NCMonomialSet --> std::vector of monomials, sorted, with values stored in NCMonomialSet.
1695// monomials(NCMonomialSet) --> Matrix
1696// coeffs(NCMonomialSet, Matrix) --> Matrix of coeffs
1697//
1698//
1699Matrix /* or null */ *Matrix::monomials(M2_arrayint vars) const
1700// Returns a one row matrix of all of the monomials in the variable subset
1701// 'vars'
1702// which occur in 'this'. These monomials are sorted into increasing degree
1703// order.
1704{
1705 const PolynomialRing *P = get_ring()->cast_to_PolynomialRing();
1706 if (P == nullptr)
1707 {
1708 const M2FreeAlgebraOrQuotient* Q = dynamic_cast<const M2FreeAlgebraOrQuotient*>(get_ring());
1709 if (Q == nullptr)
1710 {
1711 ERROR("expected polynomial ring");
1712 return nullptr;
1713 }
1715 NCMonomials(monom_set, this);
1716 //PRINT_ELEMENTS(monom_set.set(), "hashtable: ");
1717 //PRINT_ELEMENTS(monom_set.uniqueMonoms(), "monoms: ");
1718 //printHashTableState(monom_set.set());
1719 //monom_set.display(std::cout);
1720 return NCMonomialMatrix(monom_set, rows());
1721 // NCMonomialSet H(Q->n_vars());
1722 // NCMonomials(H, this);
1723 // MonomialAreaTest montest;
1724 // size_t sz = montest.test1();
1725 // std::cout << "sz = " << sz << std::endl;
1726 }
1727 const Monoid *M = P->getMonoid();
1728 const Ring *K = P->getCoefficients();
1729 int nvars = M->n_vars();
1730 // Check that 'vars' is valid
1731 for (unsigned int i = 0; i < vars->len; i++)
1732 if (vars->array[i] < 0 || vars->array[i] >= nvars)
1733 {
1734 ERROR("expected a list of indices of indeterminates");
1735 return nullptr;
1736 }
1737
1738 // Now collect all of the monomials
1739 monomial mon = M->make_one();
1740 exponents_t exp = newarray_atomic(int, M->n_vars());
1741 ring_elem one = K->from_long(1);
1742 exponent_table *E =
1743 exponent_table_new(50000, vars->len + 1); // the +1 is for the component
1744
1745 for (int c = 0; c < n_cols(); c++)
1746 {
1747 vec v = elem(c);
1748 for (; v != nullptr; v = v->next)
1749 {
1750 for (Nterm& t : v->coeff)
1751 {
1752 exponents_t exp1 = newarray_atomic(int, vars->len + 1);
1753 M->to_expvector(t.monom, exp);
1754 for (unsigned int i = 0; i < vars->len; i++)
1755 exp1[i] = exp[vars->array[i]];
1756 exp1[vars->len] = v->comp;
1757 exponent_table_put(E, exp1, 1);
1758 }
1759 }
1760 }
1761
1762 // Take all of these monomials and make an array_ out of them
1763 MatrixConstructor mat(rows(), 0);
1764 const void **monoms = exponent_table_to_array(E);
1765 for (int i = 0; i < nvars; i++) exp[i] = 0;
1766 for (int i = 0; monoms[i] != nullptr; i += 2)
1767 {
1768 const_exponents exp1 = reinterpret_cast<const_exponents>(monoms[i]);
1769 for (unsigned int j = 0; j < vars->len; j++)
1770 exp[vars->array[j]] = exp1[j];
1771 int x = exp1[vars->len]; // component
1772 M->from_expvector(exp, mon);
1773 ring_elem a = P->make_flat_term(one, mon);
1774 mat.append(P->make_vec(x, a));
1775 }
1776
1777 // Remove the garbage memory
1778 freemem(exp);
1779 M->remove(mon);
1781
1782 // Finally, we sort them
1783 Matrix *result = mat.to_matrix();
1784 M2_arrayint perm = result->sort(0, -1);
1785 return result->sub_matrix(perm);
1786}
1787
1789 exponent big,
1790 int comp,
1792// sets result[0..vars->len-1] with the corresponding exponents in 'big'
1793// sets result[vars->len] to be the component
1794// zeros out any variables in big which are placed into result.
1795//
1796// private routine for 'coeffs'.
1797{
1798 for (int j = 0; j < vars->len; j++)
1799 {
1800 int v = vars->array[j];
1801 result[j] = big[v];
1802 big[v] = 0;
1803 }
1804 result[vars->len] = comp;
1805}
1806
1808 M2_arrayint vars,
1809 const FreeModule *F,
1810 vec f)
1811// private routine for 'coeffs'.
1812#ifdef DEVELOPMENT
1813#warning "coeffs_of_vec should maybe be in PolynomialRing"
1814#endif
1815{
1816 if (f == nullptr) return nullptr;
1818 if (P == nullptr) return nullptr;
1819 const Monoid *M = P->getMonoid();
1820 monomial mon = M->make_one();
1821
1822 // At this point, we know that we have a polynomial ring
1823 int nvars = M->n_vars();
1824 exponents_t exp = newarray_atomic(int, nvars);
1825 exponents_t scratch_exp = newarray_atomic(int, 1 + vars->len);
1826
1827 vec result = nullptr;
1828 for (vec g = f; g != nullptr; g = g->next)
1829 {
1830 for (Nterm& h : g->coeff)
1831 {
1832 M->to_expvector(h.monom, exp);
1833 get_part_of_expvector(vars, exp, g->comp, scratch_exp);
1834 int val = static_cast<int>(exponent_table_get(E, scratch_exp));
1835 if (val > 0)
1836 {
1837 M->from_expvector(exp, mon);
1838 ring_elem t = P->make_flat_term(h.coeff, mon);
1839 vec v = P->make_vec(val - 1, t);
1840 v->next = result;
1841 result = v;
1842 }
1843 }
1844 }
1845 freemem(exp);
1846 freemem(scratch_exp);
1847 M->remove(mon);
1848 P->vec_sort(result);
1849 return result;
1850}
1851
1853 const Matrix *monoms) const
1854{
1855 // Given an array_ of variable indices, 'vars', and given
1856 // that 'monoms' and 'this' both have one row, makes a matrix
1857 // having number of rows = ncols(monoms),
1858 // number of cols = ncols(this),
1859 // whose (r,c) entry is the coefficient (in the other variables)
1860 // of this[0,c] in the monomial monoms[0,r].
1861
1862 // Step 0: Do some error checking
1863 const PolynomialRing *P = get_ring()->cast_to_PolynomialRing();
1864 if (P != nullptr)
1865 {
1866 int nvars = P->n_vars();
1867 int nelements = monoms->n_cols();
1868 if (monoms->n_rows() != n_rows())
1869 {
1870 ERROR("expected matrices with the same number of rows");
1871 return nullptr;
1872 }
1873 for (unsigned int i = 0; i < vars->len; i++)
1874 if (vars->array[i] < 0 || vars->array[i] >= nvars)
1875 {
1876 ERROR("coeffs: expected a set of variable indices");
1877 return nullptr;
1878 }
1879
1880 // Step 1: Make an exponent_table of all of the monoms.
1881 // We set the value of the i th monomial to be 'i+1', since 0
1882 // indicates a non-existent entry.
1883
1884 // The extra size in monomial refers to the component:
1885 exponent_table *E = exponent_table_new(nelements, 1 + vars->len);
1886 exponent EXP = newarray_atomic(int, nvars);
1887 for (int i = 0; i < nelements; i++)
1888 {
1889 vec v = monoms->elem(i);
1890 if (v == nullptr)
1891 {
1892 ERROR("expected non-zero column");
1893 return nullptr;
1894 }
1895 ring_elem f = v->coeff;
1897 P->getMonoid()->to_expvector(m, EXP);
1898
1899 // grab only that part of the monomial we need
1900 exponent e = newarray_atomic(int, 1 + vars->len);
1901 get_part_of_expvector(vars, EXP, v->comp, e);
1902 exponent_table_put(E, e, i + 1);
1903 }
1904
1905 // Step 2: for each vector column of 'this'
1906 // create a column, and put this vector into result.
1907
1909 for (int i = 0; i < n_cols(); i++)
1910 mat.append(coeffs_of_vec(E, vars, rows(), elem(i)));
1911
1912 return mat.to_matrix();
1913 }
1914 const M2FreeAlgebraOrQuotient* Q = dynamic_cast<const M2FreeAlgebraOrQuotient*>(get_ring());
1915 if (Q != nullptr)
1916 {
1917 ModuleMonomialSet H(Q->n_vars());
1918 NCMonomials(H, monoms);
1919 return NCCoefficientMatrix(H, this);
1920 }
1921 ERROR("expected polynomial ring");
1922 return nullptr;
1923}
1924
1926 int n,
1927 bool use_only_monomials_with_unit_coeffs) const
1928{
1929 const PolynomialRing *P = get_ring()->cast_to_PolynomialRing();
1930 if (P == nullptr)
1931 {
1932 ERROR("expected polynomial ring");
1933 return nullptr;
1934 }
1935 bool coeffsZZ = (P->coefficient_type() == Ring::COEFF_ZZ &&
1936 use_only_monomials_with_unit_coeffs);
1937 const Monoid *M = P->getMonoid();
1938 VECTOR(Bag *) new_elems;
1939 for (int i = 0; i < n_cols(); i++)
1940 {
1941 vec v = elem(i);
1942 if (v == nullptr) continue;
1943 const vecterm *w = P->vec_locate_lead_term(rows(), v);
1944 if (w->comp != n) continue;
1945 if (coeffsZZ && !globalZZ->is_unit(P->lead_flat_coeff(w->coeff)))
1946 continue;
1947 Bag *b = new Bag(i);
1948 M->to_varpower(P->lead_flat_monomial(w->coeff), b->monom());
1949 new_elems.push_back(b);
1950 }
1951
1952 // If the base ring is a quotient ring, include these lead monomials.
1953 for (int i = 0; i < P->n_quotients(); i++)
1954 {
1955 Nterm *f = P->quotient_element(i);
1956 if (coeffsZZ && !globalZZ->is_unit(f->coeff)) continue;
1957 Bag *b = new Bag(-1);
1958 M->to_varpower(f->monom, b->monom());
1959 new_elems.push_back(b);
1960 }
1961
1962 // If the base ring has skew commuting variables, include their squares
1963 if (P->is_skew_commutative())
1964 {
1965 for (int i = 0; i < M->n_vars(); i++)
1966 if (P->is_skew_var(i))
1967 {
1968 Bag *b = new Bag(-1);
1969 varpower::var(i, 2, b->monom());
1970 new_elems.push_back(b);
1971 }
1972 }
1973
1974 MonomialIdeal *result = new MonomialIdeal(P, new_elems);
1975 return result;
1976}
1977
1979{
1980 const PolynomialRing *P = get_ring()->cast_to_PolynomialRing();
1981 const Ring *K = (P != nullptr ? P->getCoefficientRing() : get_ring());
1982 bool is_ZZ = K->is_ZZ();
1983 int base = (is_ZZ ? 1 : 0);
1984 int result = -1;
1985 if (P != nullptr)
1986 {
1987 int n = P->n_vars();
1988 for (int i = 0; i < n_rows(); i++)
1989 {
1991 AssociatedPrimes ap(mi);
1992 int d = n - ap.codimension();
1993 if (d > result) result = d;
1994 }
1995 if (result != -1) result += base;
1996 return result;
1997 }
1998 else
1999 {
2000 // This handles the case when the coefficients are a field, or ZZ
2001 int i, j;
2002 int *dims = newarray_atomic(int, n_rows());
2003 for (i = 0; i < n_rows(); i++) dims[i] = base;
2004 for (j = 0; j < n_cols(); j++)
2005 {
2006 vec f = elem(j);
2007 if (f == nullptr) continue;
2008 if (dims[f->comp] == -1) continue;
2009 if (K->is_unit(f->coeff))
2010 dims[f->comp] = -1;
2011 else
2012 dims[f->comp] = 0;
2013 }
2014 for (i = 0; i < n_rows(); i++)
2015 if (dims[i] > result) result = dims[i];
2016 freemem(dims);
2017 return result;
2018 }
2019}
2020
2021const Matrix /* or null */ *Matrix::content() const
2022{
2023 const Ring *R = get_ring();
2024 const PolynomialRing *P = R->cast_to_PolynomialRing();
2025 const Ring *targetR = (P == nullptr ? R : P->getCoefficients());
2026
2027 const FreeModule *F = targetR->make_FreeModule(1);
2028 MatrixConstructor mat(F, n_cols());
2029 for (int i = 0; i < n_cols(); i++)
2030 mat.set_entry(0, i, R->vec_content(elem(i)));
2031 return mat.to_matrix();
2032}
2033
2034const Matrix /* or null */ *Matrix::remove_content() const
2035{
2036 const Ring *R = get_ring();
2038 for (int i = 0; i < n_cols(); i++)
2039 mat.set_column(i, R->vec_divide_by_content(elem(i)));
2040 return mat.to_matrix();
2041}
2042
2044 const Matrix /* or null */ *&result) const
2045{
2046 const Ring *R = get_ring();
2047 const PolynomialRing *P = R->cast_to_PolynomialRing();
2048 const Ring *targetR = (P == nullptr ? R : P->getCoefficients());
2049
2050 const FreeModule *F = targetR->make_FreeModule(1);
2051 MatrixConstructor mat_content(F, n_cols());
2053
2054 for (int i = 0; i < n_cols(); i++)
2055 {
2056 vec g;
2057 ring_elem c = R->vec_split_off_content(elem(i), g);
2058 mat_content.set_entry(0, i, c);
2059 mat.set_column(i, g);
2060 }
2061 result = mat.to_matrix();
2062 return mat_content.to_matrix();
2063}
2064
2065Matrix /* or null */ *Matrix::clean(gmp_RR epsilon) const
2066{
2067 auto R = get_ring();
2069 for (int i = 0; i < n_cols(); i++)
2070 mat.set_column(i, R->vec_zeroize_tiny(epsilon, elem(i)));
2071 return mat.to_matrix();
2072}
2073
2075{
2076 const Ring *R = get_ring();
2077 if (R->get_precision() == 0)
2078 {
2079 ERROR("expected ring over an RR or CC");
2080 return nullptr;
2081 }
2083 mpfr_init2(nm, mpfr_get_prec(p));
2084 mpfr_ui_div(nm, 1, p, MPFR_RNDN);
2085 if (!mpfr_zero_p(nm))
2086 {
2087 ERROR("Lp norm only implemented for p = infinity");
2088 mpfr_clear(nm);
2089 return nullptr;
2090 }
2091
2092 for (int i = 0; i < n_cols(); i++) R->vec_increase_maxnorm(nm, elem(i));
2093
2094 return moveTo_gmpRR(nm);
2095}
2096
2097// Local Variables:
2098// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
2099// indent-tabs-mode: nil
2100// End:
static const int nelements
exponents::ConstExponents const_exponents
exponents::Exponents exponents_t
Dense exponent-vector template [e_0, ..., e_{nvars-1}] for monomial operations.
Ring-shaped wrapper that exposes a non-commutative FreeAlgebra to the rest of the engine.
AssociatedPrimes — codimension and minimal-codimension associated primes of a monomial ideal.
unsigned int hash() const
Definition hash.hpp:70
static void var(Exponent v, Exponent e, Vector &result)
static void divide(int nvars, ConstExponents a, ConstExponents b, Exponents result)
const FreeMonoid & monoid() const
FreeModule * tensor(const FreeModule *G) const
Definition freemod.cpp:271
const Ring * get_ring() const
Definition freemod.hpp:102
FreeModule * exterior(int p) const
Definition freemod.cpp:296
int rank() const
Definition freemod.hpp:105
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
void support(const Monom &m, std::vector< int > &result) const
bool insert(Monom m, int comp)
std::pair< int, bool > find(Monom m, int comp)
auto begin() const -> decltype(mElements.begin())
auto end() const -> decltype(mElements.end())
std::size_t size() const
virtual ring_elem from_coefficient(const ring_elem a) const =0
const Poly * toPoly(const ring_elem f) const
virtual int n_vars() const =0
ring_elem fromModuleMonom(const ModuleMonom &m) const
virtual const FreeAlgebra & freeAlgebra() const =0
Abstract Ring subclass that lifts either a FreeAlgebra or a FreeAlgebraQuotient into the engine's Rin...
void set(int newcol)
Definition matrix.hpp:312
ring_elem entry()
Definition matrix.hpp:320
Reseatable iterator over the non-zero entries of one column of the matrix.
Definition matrix.hpp:303
friend class FreeModule
Definition matrix.hpp:73
static const Matrix * make_sparse(const FreeModule *target, int ncols, M2_arrayint rows, M2_arrayint cols, const engine_RawRingElementArray entries)
Definition matrix.cpp:191
const_monomial degree_shift() const
Definition matrix.hpp:149
static Matrix * flip(const FreeModule *G, const FreeModule *H)
Definition matrix.cpp:547
Matrix * concat(const Matrix &m) const
Definition matrix.cpp:605
const Ring * get_ring() const
Definition matrix.hpp:134
ring_elem elem(int i, int j) const
Definition matrix.cpp:307
Matrix * mult(const Matrix *m, bool opposite_mult) const
Definition matrix.cpp:659
Matrix * remove_monomial_factors(bool make_squarefree_only) const
Definition matrix.cpp:1462
monomial mDegreeShift
Definition matrix.hpp:70
Matrix * top_coefficients(Matrix *&monoms) const
Definition matrix.cpp:994
Matrix * clean(gmp_RR epsilon) const
Definition matrix.cpp:2065
gc_vector< vec > mEntries
Definition matrix.hpp:71
static Matrix * wedge_product(int p, int q, const FreeModule *F)
Definition matrix.cpp:1272
static Matrix * identity(const FreeModule *F)
Definition matrix.cpp:380
static const Matrix * make(const FreeModule *target, int ncols, const engine_RawRingElementArray M)
Definition matrix.cpp:60
M2_arrayintOrNull support() const
Definition matrix.cpp:922
Matrix * operator-() const
Definition matrix.cpp:462
const Matrix * remake(const FreeModule *target, const FreeModule *source, M2_arrayint deg) const
Definition matrix.cpp:228
const Matrix * remove_content() const
Definition matrix.cpp:2034
friend class MatrixConstructor
Definition matrix.hpp:76
bool is_zero() const
Definition matrix.cpp:325
Matrix * module_tensor(const Matrix *m) const
Definition matrix.cpp:686
FreeModule * mSource
Definition matrix.hpp:69
Matrix * monomials(M2_arrayint vars) const
Definition matrix.cpp:1699
int n_cols() const
Definition matrix.hpp:147
Matrix(const FreeModule *rows, const FreeModule *cols, const_monomial degree_shift, VECTOR(vec) &entries)
Definition matrix.cpp:32
M2_arrayint elim_keep(int nparts) const
Definition matrix.cpp:1047
virtual unsigned int computeHashValue() const
Definition matrix.cpp:43
static Matrix * zero(const FreeModule *F, const FreeModule *G)
Definition matrix.cpp:369
int n_rows() const
Definition matrix.hpp:146
bool is_homogeneous() const
Definition matrix.cpp:332
const Matrix * split_off_content(const Matrix *&result) const
Definition matrix.cpp:2043
static Matrix * koszul_monomials(int nskew, const Matrix *rows, const Matrix *cols)
Definition matrix.cpp:1162
static Matrix * random(const Ring *R, int r, int c)
Matrix * homogenize(int v, const std::vector< int > &wts) const
Definition matrix.cpp:359
MonomialIdeal * make_monideal(int n, bool use_only_monomials_with_unit_coeffs=false) const
Definition matrix.cpp:1925
Matrix * operator+(const Matrix &m) const
Definition matrix.cpp:389
const FreeModule * rows() const
Definition matrix.hpp:144
Matrix * diff(const Matrix *m, int use_coef) const
Definition matrix.cpp:805
Matrix * lead_term(int n=-1) const
Definition matrix.cpp:840
void text_out(buffer &o) const
Definition matrix.cpp:1316
Matrix * transpose() const
Definition matrix.cpp:566
const FreeModule * cols() const
Definition matrix.hpp:145
Matrix * koszul(int p) const
Definition matrix.cpp:1087
Matrix * tensor(const Matrix *m) const
Definition matrix.cpp:780
Matrix * compress() const
Definition matrix.cpp:1347
Matrix * divide_by_var(int n, int maxd, int &maxdivided) const
Definition matrix.cpp:1062
bool is_equal(const Matrix &m) const
Definition matrix.cpp:312
int dimension1() const
Definition matrix.cpp:1978
M2_arrayint elim_vars(int nparts) const
Definition matrix.cpp:1032
Matrix * reshape(const FreeModule *G, const FreeModule *H) const
Definition matrix.cpp:516
const Matrix * content() const
Definition matrix.cpp:2021
Matrix * direct_sum(const Matrix *m) const
Definition matrix.cpp:629
Matrix * scalar_mult(const ring_elem r, bool opposite_mult) const
Definition matrix.cpp:588
FreeModule * mTarget
Definition matrix.hpp:68
Matrix * remove_scalar_multiples() const
Definition matrix.cpp:1437
Matrix * coeffs(M2_arrayint vars, const Matrix *monoms) const
Definition matrix.cpp:1852
gmp_RRorNull norm(gmp_RR p) const
Definition matrix.cpp:2074
Matrix * sub_matrix(M2_arrayint r, M2_arrayint c) const
Definition matrix.cpp:470
static bool make_sparse_vecs(MatrixConstructor &mat, const FreeModule *target, int ncols, M2_arrayint rows, M2_arrayint cols, const engine_RawRingElementArray entries)
Definition matrix.cpp:143
Matrix * to_matrix()
void compute_column_degrees()
void append(vec v)
void set_entry(int r, int c, ring_elem a)
void set_column(int c, vec v)
Mutable builder used to assemble an immutable Matrix one column (or one term) at a time.
Current IntsSet configuration: exposes Hash and Eq as discrete member functors so the unordered_set c...
void to_expvector(const_monomial m, exponents_t result_exp) const
Definition monoid.cpp:747
void to_varpower(const_monomial m, gc_vector< int > &result_vp) const
Definition monoid.cpp:735
void from_varpower(const_varpower vp, monomial result) const
Definition monoid.cpp:728
int n_vars() const
Definition monoid.hpp:207
monomial make_one() const
Definition monoid.cpp:455
void remove(monomial d) const
Definition monoid.cpp:462
void from_expvector(const_exponents exp, monomial result) const
Definition monoid.cpp:742
int n_slots(int nparts) const
Definition monoid.cpp:386
Engine-side commutative monomial monoid: variable names, ordering, multidegree machinery,...
Definition monoid.hpp:89
Iterator beginAtLast() const
Definition monideal.hpp:278
void find_all_divisors(const_exponents exp, VECTOR(Bag *)&b) const
Definition monideal.cpp:246
int size() const
Definition monideal.hpp:186
Iterator end() const
Definition monideal.hpp:279
const PolynomialRing * get_ring() const
Definition monideal.hpp:190
Engine-side monomial ideal: a decision tree of Nmi_nodes storing the (typically minimal) generators b...
Definition monideal.hpp:136
int n_quotients() const
Definition polyring.hpp:219
const Ring * getCoefficientRing() const
Definition polyring.hpp:200
virtual ring_elem var(int v) const =0
virtual const Monoid * getMonoid() const
Definition polyring.hpp:282
virtual ring_elem lead_flat_coeff(const ring_elem f) const =0
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition polyring.hpp:304
virtual ring_elem make_flat_term(const ring_elem a, const_monomial m) const =0
Nterm * quotient_element(int i) const
Definition polyring.hpp:220
virtual vec vec_top_coefficient(const vec v, int &var, int &exp) const =0
bool is_skew_var(int v) const
Definition polyring.hpp:240
virtual const Ring * getCoefficients() const
Definition polyring.hpp:277
virtual const vecterm * vec_locate_lead_term(const FreeModule *F, vec v) const =0
CoefficientType coefficient_type() const
Definition polyring.hpp:191
int n_vars() const
Definition polyring.hpp:196
bool is_skew_commutative() const
Definition polyring.hpp:237
virtual const_monomial lead_flat_monomial(const ring_elem f) const =0
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual bool is_ZZ() const
Definition ring.hpp:171
virtual FreeModule * make_FreeModule() const
Definition ring.cpp:53
void negate_to(ring_elem &f) const
Definition ring.cpp:210
vec make_vec(int r, ring_elem a) const
Definition ring-vecs.cpp:60
virtual bool is_unit(const ring_elem f) const =0
ring_elem one() const
Definition ring.hpp:357
vec vec_divide_by_content(vec f) const
vec mult_vec_matrix(const Matrix *m, vec v, bool opposite_mult) const
void vec_sort(vecterm *&f) const
int vec_in_subring(int n, const vec v) const
virtual unsigned long get_precision() const
Definition ring.cpp:438
virtual ring_elem from_long(long n) const =0
ring_elem minus_one() const
Definition ring.hpp:358
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
virtual ring_elem copy(const ring_elem f) const =0
virtual ring_elem antipode(ring_elem f) const
Definition ring.hpp:517
vec vec_divide_by_var(int n, int d, const vec v) const
void vec_increase_maxnorm(gmp_RRmutable norm, const vec f) const
@ COEFF_ZZ
Definition ring.hpp:222
void vec_degree_of_var(int n, const vec v, int &lo, int &hi) const
ring_elem vec_content(vec f) const
virtual ring_elem random() const
Definition ring.cpp:284
vec vec_diff(vec v, int rankFw, vec w, int use_coeff) const
ring_elem vec_split_off_content(vec f, vec &result) const
virtual ring_elem power(const ring_elem f, mpz_srcptr n) const
Exponentiation. This is the default function, if a class doesn't define this.
Definition ring.cpp:109
vec copy_vec(const vecterm *v) const
Definition ring-vecs.cpp:91
vec e_sub_i(int r) const
Definition ring-vecs.cpp:85
const Monoid * degree_monoid() const
Definition ring.cpp:13
xxx xxx xxx
Definition ring.hpp:102
int mult_sign(const int *exp1, const int *exp2) const
Definition skew.cpp:91
Sign-rule helper used by every ring that has a skew-commutative subset of variables (exterior factor,...
Definition skew.hpp:54
static int concatenateSubsets(const Subset &s, const Subset &t, Subset &result)
Definition comb.cpp:163
size_t encode(const Subset &a)
Definition comb.cpp:66
void decode(size_t val, Subset &result)
Definition comb.cpp:96
size_t encodeBoundary(size_t index, const Subset &a)
Definition comb.cpp:80
Bijective integer encoding of q-subsets of {0, ..., n-1} via binomial(a_0, 1) + binomial(a_1,...
Definition comb.hpp:74
gc_vector< int > & monom()
Definition int-bag.hpp:60
std::vector< size_t > Subset
Definition comb.hpp:58
Subsets — combinatorial-number-system encoding of p-subsets of {0,...,n-1}.
void exponent_table_free(exponent_table **E)
Definition exptable.c:55
const void ** exponent_table_to_array(exponent_table *E)
Definition exptable.c:79
exponent_table * exponent_table_new(int hint, int nvars)
Definition exptable.c:45
long exponent_table_put(exponent_table *E, const exponent expon, long value)
Definition exptable.c:62
long exponent_table_get(exponent_table *E, const exponent expon)
Definition exptable.c:71
int * exponent
Definition exptable.h:34
Hash table specialisation for (exponent vector, unsigned long) pairs.
static CanonicalForm base
Definition factory.cpp:289
#define Matrix
Definition factory.cpp:14
FreeModule — finite-rank free module R^n, the type-level anchor for every Matrix.
RingZZ * globalZZ
Definition relem.cpp:13
#define monomial
Definition gb-toric.cpp:11
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
const int * const_monomial
Definition imonorder.hpp:45
int_bag Bag
Definition int-bag.hpp:70
void freemem(void *s)
Definition m2-mem.cpp:103
void size_t s
Definition m2-mem.cpp:271
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemstructtype(S)
Definition m2-mem.h:143
M2_arrayint M2_makearrayint(int n)
Definition m2-types.cpp:6
char newline[]
Definition m2-types.cpp:49
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
mpfr_srcptr gmp_RRorNull
Definition m2-types.h:149
MatrixConstructor — the mutable builder that produces an immutable Matrix.
static void get_part_of_expvector(M2_arrayint vars, exponent big, int comp, exponent result)
Definition matrix.cpp:1788
static MonomialIdeal * makemonideal(const Matrix *A)
Definition matrix.cpp:1123
Matrix * NCMonomialMatrix(ModuleMonomialSet &H, const FreeModule *target)
Definition matrix.cpp:1615
static int signdivide(int n, const_exponents a, const_exponents b, exponents_t exp)
Definition matrix.cpp:1146
static vec coeffs_of_vec(exponent_table *E, M2_arrayint vars, const FreeModule *F, vec f)
Definition matrix.cpp:1807
void NCMonomials(ModuleMonomialSet &H, const Matrix *M)
Definition matrix.cpp:1593
Matrix * NCCoefficientMatrix(ModuleMonomialSet &H, const Matrix *M)
Definition matrix.cpp:1639
Matrix — the engine's immutable homomorphism F -> G between free modules.
MonomialIdeal — exponent-vector-only representation of an ideal generated by monomials.
IntsSet< ModuleMonomDefaultConfig > ModuleMonomialSet
IntsSet<Configuration> — set of monomials with insert / lookup / insertion-ordered iteration.
typename std::vector< T, gc_allocator< T > > gc_vector
a version of the STL vector, which allocates its backing memory with gc.
Definition newdelete.hpp:76
#define VECTOR(T)
Definition newdelete.hpp:78
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
volatile int x
PolynomialRing — abstract polynomial-ring base, the engine's most-reused class.
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.
tbb::flow::graph G
Ring — the legacy abstract base class for every coefficient and polynomial ring.
ring_elem coeff
Definition ringelem.hpp:158
int monom[1]
Definition ringelem.hpp:160
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
ring_elem coeff
Definition ringelem.hpp:172
const int EQ
Definition style.hpp:40
Engine-wide stylistic constants: LT / EQ / GT codes, INTSIZE, GEOHEAP_SIZE.
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.
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.