Macaulay2 Engine
Loading...
Searching...
No Matches
ring-vecs.cpp
Go to the documentation of this file.
1// Copyright 2003 Michael E. Stillman
2
42
43#include "ring.hpp"
44#include "text-io.hpp"
45#include <vector>
46#include "matrix.hpp"
47#include "geovec.hpp"
48#include "ringmap.hpp"
49#include "poly.hpp"
50// Notes: ring_elem's are treated as immutable objects: they are not changed,
51// and
52// the fact that one cannot change is used throughout.
53
54vec Ring::new_vec() const { return new vecterm; }
55void Ring::remove_vec_node(vec n) const
56{
57 freemem(n);
58}
59
60vec Ring::make_vec(int r, ring_elem a) const
61{
62 if (is_zero(a)) return nullptr;
63 vec result = new_vec();
64 result->next = nullptr;
65 result->comp = r;
66 result->coeff = a;
67 return result;
68}
69
70vec Ring::make_vec_from_array(int len, Nterm **array) const
71{
72 vec result = nullptr;
73 for (int i = 0; i < len; i++)
74 {
75 if (array[i] != nullptr)
76 {
77 vec v = make_vec(i, array[i]);
78 v->next = result;
79 result = v;
80 }
81 }
82 return result;
83}
84
85vec Ring::e_sub_i(int i) const
86{
87 ring_elem a = from_long(1);
88 return make_vec(i, a);
89}
90
91vec Ring::copy_vec(const vecterm *v) const
92{
93 vecterm head;
94 vec result = &head;
95 for (const vecterm *p = v; p != nullptr; p = p->next)
96 {
97 vec w = new_vec();
98 result->next = w;
99 result = w;
100 w->comp = p->comp;
101 w->coeff = p->coeff; // copy is not done
102 }
103 result->next = nullptr;
104 return head.next;
105}
106
107void Ring::remove_vec(vec v) const
108{
109 while (v != nullptr)
110 {
111 vec tmp = v;
112 v = v->next;
113 remove_vec_node(tmp);
114 }
115}
116
118// Routines which do not modify vecs //
120
121bool Ring::is_equal(const vecterm *a, const vecterm *b) const
122{
123 for (;; a = a->next, b = b->next)
124 {
125 if (a == nullptr)
126 {
127 if (b == nullptr) return true;
128 return false;
129 }
130 if (b == nullptr) return false;
131 if (a->comp != b->comp) return false;
132 if (!this->is_equal(a->coeff, b->coeff)) return false;
133 }
134}
135
136int Ring::compare_vecs(vec v, vec w) const
137{
138 for (;; v = v->next, w = w->next)
139 {
140 if (v == nullptr)
141 {
142 if (w == nullptr) return 0;
143 return -1;
144 }
145 if (w == nullptr) return 1;
146 int cmp = v->comp - w->comp;
147 if (cmp > 0) return cmp;
148 if (cmp < 0) return cmp;
149 cmp = this->compare_elems(v->coeff, w->coeff);
150 if (cmp > 0) return cmp;
151 if (cmp < 0) return cmp;
152 }
153}
154
155bool Ring::get_entry(const vecterm *v, int r, ring_elem &result) const
156{
157 for (const vecterm *p = v; p != nullptr; p = p->next)
158 if (p->comp < r)
159 break;
160 else if (p->comp == r)
161 {
162 result = p->coeff;
163 return true;
164 }
165 return false;
166}
167
168ring_elem Ring::get_entry(vec v, int r) const
169{
170 while (v != nullptr)
171 {
172 if (v->comp == r) return v->coeff;
173 if (v->comp < r) return from_long(0);
174 v = v->next;
175 }
176 return from_long(0);
177}
178
180{
181 int result = 0;
182 for (; v != nullptr; v = v->next) result++;
183 return result;
184}
185
186vec Ring::negate_vec(vec v) const
187{
189 vecterm *b = &result;
190 for (vecterm *a = v; a != nullptr; a = a->next)
191 {
192 b->next = make_vec(a->comp, negate(a->coeff));
193 b = b->next;
194 }
195 b->next = nullptr;
196 return result.next;
197}
198
199vec Ring::add_vec(vec v, vec w) const
200{
201 vec f = copy_vec(v);
202 vec g = copy_vec(w);
203 add_vec_to(f, g);
204 return f;
205}
206
207vec Ring::subtract_vec(vec v, vec w) const
208{
209 vec f = copy_vec(v);
210 vec g = negate_vec(w);
211 add_vec_to(f, g);
212 return f;
213}
214
215vec Ring::mult_vec(int n, vec v) const
216{
217 ring_elem f = from_long(n);
218 vec result = mult_vec(f, v);
219 return result;
220}
221
222vec Ring::mult_vec(const ring_elem f, const vec w) const
223{
224 if (is_zero(f)) return nullptr;
225 vecterm head;
226 vec result = &head;
227 for (vec v = w; v != nullptr; v = v->next)
228 {
229 ring_elem a = mult(f, v->coeff);
230 if (!is_zero(a))
231 {
232 vec t = make_vec(v->comp, a);
233 result->next = t;
234 result = t;
235 }
236 }
237 result->next = nullptr;
238 return head.next;
239}
240
241vec Ring::rightmult_vec(const vec w, const ring_elem f) const
242{
243 if (is_zero(f)) return nullptr;
244 vecterm head;
245 vec result = &head;
246 for (vec v = w; v != nullptr; v = v->next)
247 {
248 ring_elem a = mult(v->coeff, f);
249 if (!is_zero(a))
250 {
251 vec t = make_vec(v->comp, a);
252 result->next = t;
253 result = t;
254 }
255 }
256 result->next = nullptr;
257 return head.next;
258}
259
261{
262 if (v == nullptr) return nullptr;
263 // Largest component which occurs in v occurs first.
264 VECTOR(int) trans(v->comp + 1);
265 for (int i = 0; i < v->comp; i++) trans.push_back(-1);
266
267 for (unsigned j = 0; j < r->len; j++)
268 if (r->array[j] >= 0 && r->array[j] <= v->comp) trans[r->array[j]] = j;
269
270 vecterm head;
271 vecterm *result = &head;
272 for (; v != nullptr; v = v->next)
273 if (trans[v->comp] != -1)
274 {
275 result->next = new_vec();
276 result = result->next;
277 result->next = nullptr;
278 result->coeff = v->coeff;
279 result->comp = trans[v->comp];
280 }
281 result->next = nullptr;
282 result = head.next;
283
285 return result;
286}
287
288vec Ring::component_shift(int n, vec v) const
289{
290 vecterm head;
291 vec result = &head;
292 for (const vecterm *p = v; p != nullptr; p = p->next)
293 {
294 vec w = new_vec();
295 result->next = w;
296 result = w;
297 w->comp = p->comp + n;
298 w->coeff = p->coeff; // copy is not done
299 }
300 result->next = nullptr;
301 return head.next;
302}
303
304vec Ring::tensor_shift(int n, int m, vec v) const
305{
306 vecterm head;
307 vecterm *result = &head;
308
309 for (; v != nullptr; v = v->next)
310 {
311 vec w = new_vec();
312 result->next = w;
313 result = w;
314 w->comp = n * v->comp + m;
315 w->coeff = v->coeff; // copy is not done
316 }
317 result->next = nullptr;
318 return head.next;
319}
320
321vec Ring::tensor(const FreeModule *F, vec v, const FreeModule *G, vec w) const
322{
323 vecHeap H(F);
324 for (; v != nullptr; v = v->next)
325 {
326 vec w1 = component_shift(v->comp * G->rank(), w);
327 mult_vec_to(w1, v->coeff, false);
328 H.add(w1);
329 }
330 return H.value();
331}
332
334 const vecterm *v,
335 bool p_one,
336 bool p_plus,
337 bool p_parens) const
338{
339 if (v == nullptr)
340 {
341 o << "0";
342 return;
343 }
344
345 p_one = false;
346 for (const vecterm *t = v; t != nullptr; t = t->next)
347 {
348 this->elem_text_out(o, t->coeff, p_one, p_plus, p_parens);
349 o << "<" << t->comp << ">";
350 p_plus = true;
351 }
352}
353
354vec Ring::vec_eval(const RingMap *map, const FreeModule *F, const vec v) const
355// v is a vector over 'this'
356{
357 (void) F;
358 const Ring *targetRing = map->get_ring();
359
360 vecterm head;
361 vec result = &head;
362
363 for (vec t = v; t != nullptr; t = t->next)
364 {
365 ring_elem a = eval(map, t->coeff, 0); // a is now in the target ring
366 if (!targetRing->is_zero(a))
367 {
368 result->next = targetRing->make_vec(t->comp, a);
369 result = result->next;
370 }
371 }
372 result->next = nullptr;
373 return head.next;
374}
375
376vec Ring::vec_zeroize_tiny(gmp_RR epsilon, const vec v) const
377{
378 vecterm head;
379 vec result = &head;
380 for (const vecterm *p = v; p != nullptr; p = p->next)
381 {
382 ring_elem a = zeroize_tiny(epsilon, p->coeff);
383 if (!is_zero(a))
384 {
385 vec w = new_vec();
386 result->next = w;
387 result = w;
388 w->comp = p->comp;
389 w->coeff = a;
390 }
391 }
392 result->next = nullptr;
393 return head.next;
394}
395
396void Ring::vec_increase_maxnorm(gmp_RRmutable norm, const vec v) const
397// If any real number appearing in f has larger absolute value than norm,
398// replace norm.
399// Default for rings not over RRR or CCC is to do nothing.
400{
401 for (const vecterm *p = v; p != nullptr; p = p->next)
402 increase_maxnorm(norm, p->coeff);
403}
404
405// Routines which modify a vec ////////
407
408void Ring::mult_vec_to(vec &v, const ring_elem r, bool opposite_mult) const
409{
410 if (this->is_zero(r))
411 {
412 remove_vec(v);
413 v = nullptr;
414 return;
415 }
416 vecterm head;
417 head.next = v;
418 vec p = &head;
419 while (p->next != nullptr)
420 {
421 // old version: this->mult_to(p->next->coeff, a);
422 ring_elem c;
423 if (opposite_mult)
424 c = this->mult(p->next->coeff, r);
425 else
426 c = this->mult(r, p->next->coeff);
427 p->next->coeff = c;
428 if (this->is_zero(p->next->coeff))
429 {
430 vec tmp = p->next;
431 p->next = tmp->next;
432 remove_vec_node(tmp);
433 }
434 else
435 p = p->next;
436 }
437 v = head.next;
438}
439
440void Ring::mult_row(vec &v, const ring_elem r, int i, bool opposite_mult) const
441{
442 vecterm head;
443 head.next = v;
444 for (vec p = &head; p->next != nullptr; p = p->next)
445 if (p->next->comp < i)
446 break;
447 else if (p->next->comp == i)
448 {
449 ring_elem c;
450 if (opposite_mult)
451 c = mult(p->next->coeff, r);
452 else
453 c = mult(r, p->next->coeff);
454 p->next->coeff = c;
455 if (this->is_zero(p->next->coeff))
456 {
457 vec tmp = p->next;
458 p->next = tmp->next;
459 remove_vec_node(tmp);
460 }
461 break;
462 }
463 v = head.next;
464}
465
466vec Ring::mult_vec_matrix(const Matrix *m, vec v, bool opposite_mult) const
467{
468 // Multiply m * v, using left or right mult for each scalar mult.
469
470 // Each loop below should read
471 // result = 0
472 // for each non-zero term f e[component] of the vector v
473 // result += f M[v]
474 vec result = nullptr;
475 for (; v != nullptr; v = v->next)
476 {
477 vec w = this->copy_vec(m->elem(v->comp));
478 mult_vec_to(w, v->coeff, !opposite_mult);
479 this->add_vec_to(result, w);
480 }
481 return result;
482}
483
484void Ring::divide_vec_to(vec &v, const ring_elem a) const
485{
486 if (this->is_zero(a))
487 {
488 remove_vec(v);
489 v = nullptr;
490 }
491 vecterm head;
492 head.next = v;
493 vec p = &head;
494 while (p->next != nullptr)
495 {
496 // old version: this->mult_to(p->next->coeff, a);
497 ring_elem c =
498 this->divide(p->next->coeff, a); // exact or quotient?? MES MES
499 p->next->coeff = c;
500 if (this->is_zero(p->next->coeff))
501 {
502 vec tmp = p->next;
503 p->next = tmp->next;
504 remove_vec_node(tmp);
505 }
506 else
507 p = p->next;
508 }
509 v = head.next;
510}
511
512void Ring::divide_row(vec &v, int r, const ring_elem a) const
513{
514 vecterm head;
515 head.next = v;
516 for (vec p = &head; p->next != nullptr; p = p->next)
517 if (p->next->comp < r)
518 break;
519 else if (p->next->comp == r)
520 {
521 ring_elem c =
522 this->divide(p->next->coeff, a); // exact or quotient?? MES MES
523 p->next->coeff = c;
524 if (this->is_zero(p->next->coeff))
525 {
526 vec tmp = p->next;
527 p->next = tmp->next;
528 remove_vec_node(tmp);
529 }
530 break;
531 }
532}
533
534void Ring::negate_vec_to(vec &v) const
535{
536 vec w = v;
537 while (w != nullptr)
538 {
539 negate_to(w->coeff);
540 w = w->next;
541 }
542}
543
544void Ring::subtract_vec_to(vec &v, vec &w) const
545{
546 negate_vec_to(w);
547 add_vec_to(v, w);
548}
549
550void Ring::add_vec_to(vec &v, vec &w) const
551{
552 if (w == nullptr) return;
553 if (v == nullptr)
554 {
555 v = w;
556 w = nullptr;
557 return;
558 }
559 vecterm head;
560 vec result = &head;
561 while (true)
562 if (v->comp < w->comp)
563 {
564 result->next = w;
565 result = result->next;
566 w = w->next;
567 if (w == nullptr)
568 {
569 result->next = v;
570 v = head.next;
571 return;
572 }
573 }
574 else if (v->comp > w->comp)
575 {
576 result->next = v;
577 result = result->next;
578 v = v->next;
579 if (v == nullptr)
580 {
581 result->next = w;
582 v = head.next;
583 w = nullptr;
584 return;
585 }
586 }
587 else
588 {
589 vec tmv = v;
590 vec tmw = w;
591 v = v->next;
592 w = w->next;
593 tmv->coeff = this->add(tmv->coeff, tmw->coeff);
594 if (this->is_zero(tmv->coeff))
595 {
596 remove_vec_node(tmv);
597 }
598 else
599 {
600 result->next = tmv;
601 result = result->next;
602 }
603 remove_vec_node(tmw);
604 if (w == nullptr)
605 {
606 result->next = v;
607 v = head.next;
608 return;
609 }
610 if (v == nullptr)
611 {
612 result->next = w;
613 v = head.next;
614 w = nullptr;
615 return;
616 }
617 }
618}
619
621{
622 ring_elem result = this->from_long(0);
623 while (true)
624 {
625 if (v == nullptr) return result;
626 if (w == nullptr) return result;
627 if (v->comp > w->comp)
628 v = v->next;
629 else if (v->comp < w->comp)
630 w = w->next;
631 else
632 {
633 ring_elem a = this->mult(v->coeff, w->coeff);
634 result = this->add(result, a);
635 v = v->next;
636 w = w->next;
637 }
638 }
639}
640
641void Ring::set_entry(vec &v, int r, ring_elem a) const
642{
643 vec p;
644 bool iszero = this->is_zero(a);
645 vecterm head;
646 head.next = v;
647 for (p = &head; p->next != nullptr; p = p->next)
648 if (p->next->comp <= r) break;
649
650 if (p->next == nullptr || p->next->comp < r)
651 {
652 if (iszero) return;
653 vec w = new_vec();
654 w->next = p->next;
655 w->comp = r;
656 w->coeff = a;
657 p->next = w;
658 }
659 else if (p->next->comp == r)
660 {
661 if (iszero)
662 {
663 // delete node
664 vec tmp = p->next;
665 p->next = tmp->next;
666 remove_vec_node(tmp);
667 }
668 else
669 p->next->coeff = a;
670 }
671 v = head.next;
672}
673
674void Ring::vec_sort(vecterm *&f) const
675{
676 // Internal routine to place the elements back in order after
677 // an operation such as subvector.
678 // Divide f into two lists of equal length, sort each,
679 // then add them together. This allows the same monomial
680 // to appear more than once in 'f'.
681
682 if (f == nullptr || f->next == nullptr) return;
683 vecterm *f1 = nullptr;
684 vecterm *f2 = nullptr;
685 while (f != nullptr)
686 {
687 vecterm *t = f;
688 f = f->next;
689 t->next = f1;
690 f1 = t;
691
692 if (f == nullptr) break;
693 t = f;
694 f = f->next;
695 t->next = f2;
696 f2 = t;
697 }
698
699 vec_sort(f1);
700 vec_sort(f2);
701 add_vec_to(f1, f2);
702 f = f1;
703}
704
705vec Ring::vec_lead_term(int nparts, const FreeModule *F, vec v) const
706{
707 (void) nparts;
708 (void) F;
709 // May be over-ridden by subclasses. In particular, by polynomial classes.
710 if (v == nullptr) return nullptr;
711 return make_vec(v->comp, v->coeff);
712}
713
714vec Ring::vec_diff(vec v, int rankFw, vec w, int use_coeff) const
715// rankFw is the rank of the free module corresponding to w.
716{
717 vec result = nullptr;
718 for (; v != nullptr; v = v->next)
719 for (vecterm *p = w; p != nullptr; p = p->next)
720 {
721 ring_elem a = diff(v->coeff, p->coeff, use_coeff);
722 if (is_zero(a))
723 {
724 remove(a);
725 continue;
726 }
727 vecterm *t = new_vec();
728 t->comp = rankFw * v->comp + p->comp;
729 t->coeff = a;
730 t->next = result;
731 result = t;
732 }
734 return result;
735}
736
737int Ring::vec_in_subring(int nslots, const vec v) const
738{
740 if (PR == nullptr || v == nullptr) return true;
741 const Monoid *M = PR->getMonoid();
742 for (vec w = v; w != nullptr; w = w->next)
743 if (!M->in_subring(nslots, PR->lead_flat_monomial(w->coeff))) return false;
744 return true;
745}
746
747void Ring::vec_degree_of_var(int n, const vec v, int &lo, int &hi) const
748{
749 if (v == nullptr)
750 {
751 ERROR("attempting to find degree of zero vector");
752 return;
753 }
754 degree_of_var(n, v->coeff, lo, hi);
755 for (vec w = v->next; w != nullptr; w = w->next)
756 {
757 int lo1, hi1;
758 degree_of_var(n, w->coeff, lo1, hi1);
759 if (lo1 < lo) lo = lo1;
760 if (hi1 > hi) hi = hi1;
761 }
762}
763
764vec Ring::vec_divide_by_var(int n, int d, const vec v) const
765{
766 vecterm head;
767 vecterm *result = &head;
768 for (vec w = v; w != nullptr; w = w->next)
769 {
770 ring_elem a = divide_by_var(n, d, w->coeff);
771 if (!is_zero(a))
772 {
773 vec t = make_vec(w->comp, a);
774 result->next = t;
775 result = t;
776 }
777 }
778 result->next = nullptr;
779 return head.next;
780}
781
783{
784 vecterm head;
785 vecterm *result = &head;
786 for (vec w = v; w != nullptr; w = w->next)
787 {
788 ring_elem a = divide_by_expvector(exp, w->coeff);
789 if (!is_zero(a))
790 {
791 vec t = make_vec(w->comp, a);
792 result->next = t;
793 result = t;
794 }
795 }
796 result->next = nullptr;
797 return head.next;
798}
799
801// Homogeneity and the grading //////////////
803
804bool Ring::vec_multi_degree(const FreeModule *F, const vec f, monomial degf) const
805// Returns true if the element is homogeneous
806// Sets degf to be the highest degree found (actually, the join of the
807// degree vectors occurring).
808{
809 monomial degv;
810 degree_monoid()->one(degf);
811 if (f == nullptr) return true;
812 bool result = multi_degree(f->coeff, degf);
813 degree_monoid()->mult(degf, F->degree(f->comp), degf);
814 degv = degree_monoid()->make_one();
815
816 for (vec v = f->next; v != nullptr; v = v->next)
817 {
818 bool ishom = multi_degree(v->coeff, degv);
819 result = result && ishom;
820 degree_monoid()->mult(degv, F->degree(v->comp), degv);
821
822 if (0 != degree_monoid()->compare(degf, degv))
823 {
824 result = false;
825 degree_monoid()->lcm(degf, degv, degf);
826 }
827 }
828 degree_monoid()->remove(degv);
829 return result;
830}
831
832bool Ring::vec_is_homogeneous(const FreeModule *F, const vec f) const
833{
834 if (!this->is_graded()) return false;
835 if (f == nullptr) return true;
838 bool result = multi_degree(f->coeff, d);
839 if (result)
840 {
841 degree_monoid()->mult(d, F->degree(f->comp), d);
842 for (vecterm *t = f->next; (t != nullptr) && result; t = t->next)
843 {
844 bool ishom = multi_degree(t->coeff, e);
845 result = result && ishom;
846 if (result)
847 {
848 degree_monoid()->mult(e, F->degree(t->comp), e);
849 if (0 != degree_monoid()->compare(d, e)) result = false;
850 }
851 }
852 }
853 degree_monoid()->remove(d);
854 degree_monoid()->remove(e);
855 return result;
856}
857
859 const vec f,
860 const std::vector<int> &wts,
861 int &lo,
862 int &hi) const
863{
864 vecterm *t = f;
865 if (t == nullptr)
866 {
867 lo = hi = 0;
868 return;
869 }
870 degree_weights(t->coeff, wts, lo, hi);
871 lo += F->primary_degree(t->comp);
872 hi += F->primary_degree(t->comp);
873 for (t = t->next; t != nullptr; t = t->next)
874 {
875 int lo1, hi1;
876 degree_weights(t->coeff, wts, lo1, hi1);
877 lo1 += F->primary_degree(t->comp);
878 hi1 += F->primary_degree(t->comp);
879 if (hi1 > hi) hi = hi1;
880 if (lo1 < lo) lo = lo1;
881 }
882}
883
885 const vec f,
886 int v,
887 int d,
888 const std::vector<int> &wts) const
889// Any terms which can't be homogenized are silently set to 0
890{
891 vecterm head;
892 vecterm *result = &head;
893 assert(wts[v] != 0);
894 // If an error occurs, then return 0, and set ERROR
895
896 for (vec w = f; w != nullptr; w = w->next)
897 {
898 int e = F->primary_degree(w->comp);
899 ring_elem a = homogenize(w->coeff, v, d - e, wts);
900 if (!is_zero(a))
901 {
902 result->next = make_vec(w->comp, a);
903 result = result->next;
904 }
905 }
906 result->next = nullptr;
907 return head.next;
908}
909
911 const vec f,
912 int v,
913 const std::vector<int> &wts) const
914{
915 vecterm *result = nullptr;
916 if (f == nullptr) return result;
917 int lo, hi;
918 vec_degree_weights(F, f, wts, lo, hi);
919 assert(wts[v] != 0);
920 int d = (wts[v] > 0 ? hi : lo);
921 return vec_homogenize(F, f, v, d, wts);
922}
923
925// Divisibility checks ////////
926// ////////
928
929bool static check_nterm_multiples(const PolyRing *R,
930 ring_elem f1, // in R
931 ring_elem g1, // in R
932 ring_elem c, // in flat coeffs of R
933 ring_elem d) // in flat coeffs of R
934{
935 Nterm *f;
936 Nterm *g;
937 const Monoid *M = R->getMonoid();
938 const Ring *K = R->getCoefficients();
939 for (f = f1, g = g1; f != nullptr && g != nullptr; f = f->next, g = g->next)
940 {
941 if (M->compare(f->monom, g->monom) != 0) return false;
942 ring_elem c1 = K->mult(c, g->coeff);
943 ring_elem d1 = K->mult(d, f->coeff);
944 int isequal = K->is_equal(c1, d1);
945 if (!isequal) return false;
946 }
947 if (f == nullptr && g == nullptr) return true;
948 return false;
949}
950
951bool Ring::vec_is_scalar_multiple(vec f, vec g) const
952// is df = cg, some scalars c,d?
953// These scalars are over the very bottom base field/ZZ.
954{
955 if (f == nullptr) return true;
956 if (g == nullptr) return true;
958 if (PR == nullptr) return true;
959 const PolyRing *PR1 = PR->getNumeratorRing();
960#ifdef DEVELOPMENT
961#warning "use numerator only"
962#endif
963 if (f->comp != g->comp) return false;
964 Nterm *f1 = f->coeff;
965 Nterm *g1 = g->coeff;
966 ring_elem c = f1->coeff;
967 ring_elem d = g1->coeff;
968 vec p, q;
969 for (p = f, q = g; p != nullptr && q != nullptr; p = p->next, q = q->next)
970 {
971 if (p->comp != q->comp) return 0;
972 if (!check_nterm_multiples(PR1, p->coeff, q->coeff, c, d)) return false;
973 }
974 if (q == nullptr && p == nullptr) return true;
975 return false;
976}
977
978vec Ring::vec_remove_monomial_factors(vec f, bool make_squarefree_only) const
979{
981 if (PR == nullptr) return copy_vec(f);
982 if (f == nullptr) return nullptr;
983
984 exponents_t exp = newarray_atomic(int, PR->n_vars());
985
986 Nterm *t = f->coeff;
987 PR->getMonoid()->to_expvector(t->monom, exp); // Get the process started
988
989 for (vec a = f; a != nullptr; a = a->next) monomial_divisor(a->coeff, exp);
990
991 if (make_squarefree_only)
992 // Now divide each term by exp[i]-1, if exp[i] >= 2
993 for (int i = 0; i < PR->n_vars(); i++)
994 if (exp[i] >= 1) exp[i]--;
995
996 vec result = vec_divide_by_expvector(exp, f);
997
998 freemem(exp);
999 return result;
1000}
1001
1003{
1004 if (f == nullptr) return zero();
1005 ring_elem c = content(f->coeff);
1006 for (vec t = f->next; t != nullptr; t = t->next) lower_content(c, t->coeff);
1007 return c;
1008}
1009
1011{
1012 if (f == nullptr) return nullptr;
1013 vecterm head;
1014 vec result = &head;
1015 for (const vecterm *p = f; p != nullptr; p = p->next)
1016 {
1017 vec w = new_vec();
1018 result->next = w;
1019 result = w;
1020 w->comp = p->comp;
1021 w->coeff = divide_by_given_content(p->coeff, c);
1022 }
1023 result->next = nullptr;
1024 return head.next;
1025}
1026
1028{
1029 if (f == nullptr) return nullptr;
1030 ring_elem c = vec_content(f);
1031 return vec_divide_by_given_content(f, c);
1032}
1033
1035{
1036 ring_elem c = vec_content(f);
1037 if (f == nullptr)
1038 result = nullptr;
1039 else
1041 return c;
1042}
1043
1044// Local Variables:
1045// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1046// indent-tabs-mode: nil
1047// End:
exponents::ConstExponents const_exponents
exponents::Exponents exponents_t
const_monomial degree(int i) const
Definition freemod.hpp:104
int primary_degree(int i) const
Definition freemod.cpp:440
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
ring_elem elem(int i, int j) const
Definition matrix.cpp:307
void to_expvector(const_monomial m, exponents_t result_exp) const
Definition monoid.cpp:747
bool in_subring(int nslots, const_monomial m) const
Definition monoid.cpp:395
monomial make_one() const
Definition monoid.cpp:455
int compare(int nslots, const_monomial m, const_monomial n) const
Definition monoid.hpp:226
void remove(monomial d) const
Definition monoid.cpp:462
void mult(const_monomial m, const_monomial n, monomial result) const
Definition monoid.cpp:363
Engine-side commutative monomial monoid: variable names, ordering, multidegree machinery,...
Definition monoid.hpp:89
Concrete PolyRingFlat subclass implementing ordinary commutative polynomial rings K[x_1,...
Definition poly.hpp:64
virtual const Monoid * getMonoid() const
Definition polyring.hpp:282
virtual const Ring * getCoefficients() const
Definition polyring.hpp:277
virtual const PolyRing * getNumeratorRing() const
Definition polyring.hpp:259
int n_vars() const
Definition polyring.hpp:196
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 ring_elem divide_by_expvector(const_exponents exp, const ring_elem a) const
Definition ring.cpp:383
vec mult_vec(int n, vec v) const
virtual void remove(ring_elem &f) const =0
vec component_shift(int n, vec v) const
virtual void monomial_divisor(const ring_elem a, exponents_t exp) const
Definition ring.cpp:349
virtual ring_elem content(ring_elem f) const
Definition ring.cpp:316
bool vec_multi_degree(const FreeModule *F, const vec f, monomial degf) const
vec vec_homogenize(const FreeModule *F, const vec f, int v, int deg, const std::vector< int > &wts) const
vec sub_vector(const vecterm *v, M2_arrayint r) const
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 ring_elem divide(const ring_elem f, const ring_elem g) const =0
vec add_vec(vec v, vec w) const
vec tensor(const FreeModule *F, vec v, const FreeModule *G, vec w) const
virtual void increase_maxnorm(gmp_RRmutable norm, const ring_elem f) const
Definition ring.cpp:446
void remove_vec_node(vec n) const
Definition ring-vecs.cpp:55
virtual void degree_weights(const ring_elem f, const std::vector< int > &wts, int &lo, int &hi) const
Definition ring.cpp:415
int n_nonzero_terms(const vecterm *v) const
void vec_text_out(buffer &o, const vecterm *v, bool p_one=true, bool p_plus=false, bool p_parens=false) const
virtual ring_elem add(const ring_elem f, const ring_elem g) const =0
virtual ring_elem divide_by_given_content(ring_elem f, ring_elem c) const
Definition ring.cpp:329
bool get_entry(const vecterm *v, int r, ring_elem &result) const
virtual void degree_of_var(int n, const ring_elem a, int &lo, int &hi) const
Definition ring.cpp:368
vec vec_divide_by_content(vec f) const
vec vec_zeroize_tiny(gmp_RR epsilon, const vec f) const
vec mult_vec_matrix(const Matrix *m, vec v, bool opposite_mult) const
virtual bool is_equal(const ring_elem f, const ring_elem g) const =0
void divide_row(vec &v, int r, const ring_elem a) const
void remove_vec(vec v) const
vec tensor_shift(int n, int m, vec v) const
ring_elem zero() const
Definition ring.hpp:359
void set_entry(vec &v, int i, ring_elem r) const
void vec_sort(vecterm *&f) const
virtual ring_elem homogenize(const ring_elem f, int v, int deg, const std::vector< int > &wts) const
Definition ring.cpp:389
int vec_in_subring(int n, const vec v) const
vec vec_remove_monomial_factors(vec f, bool make_squarefree_only) const
vec negate_vec(vec v) const
virtual void lower_content(ring_elem &c, ring_elem g) const
Definition ring.cpp:308
virtual ring_elem from_long(long n) const =0
virtual ring_elem negate(const ring_elem f) const =0
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
virtual void elem_text_out(buffer &o, const ring_elem f, bool p_one=true, bool p_plus=false, bool p_parens=false) const =0
vec make_vec_from_array(int len, Nterm **array) const
Definition ring-vecs.cpp:70
void divide_vec_to(vec &v, const ring_elem a) const
void subtract_vec_to(vec &v, vec &w) const
void mult_vec_to(vec &v, const ring_elem r, bool opposite_mult) const
vec rightmult_vec(const vec w, const ring_elem f) const
vec subtract_vec(vec v, vec w) const
virtual vec vec_lead_term(int nparts, const FreeModule *F, vec v) const
vec vec_divide_by_given_content(vec f, ring_elem c) const
virtual ring_elem divide_by_var(int n, int d, const ring_elem a) const
Definition ring.cpp:376
bool vec_is_homogeneous(const FreeModule *F, const vec f) const
virtual bool multi_degree(const ring_elem f, monomial d) const
Definition ring.cpp:407
vec vec_divide_by_var(int n, int d, const vec v) const
void vec_increase_maxnorm(gmp_RRmutable norm, const vec f) const
vec vec_eval(const RingMap *map, const FreeModule *F, const vec v) const
virtual ring_elem zeroize_tiny(gmp_RR epsilon, const ring_elem f) const
Definition ring.cpp:439
void negate_vec_to(vec &v) const
void vec_degree_of_var(int n, const vec v, int &lo, int &hi) const
virtual bool is_zero(const ring_elem f) const =0
virtual ring_elem diff(ring_elem a, ring_elem b, int use_coeff) const
Definition ring.cpp:355
void vec_degree_weights(const FreeModule *F, const vec f, const std::vector< int > &wts, int &lo, int &hi) const
bool vec_is_scalar_multiple(vec f, vec g) const
ring_elem vec_content(vec f) const
void add_vec_to(vec &v, vec &w) const
virtual int compare_elems(const ring_elem f, const ring_elem g) const =0
int compare_vecs(vec v, vec w) const
vec vec_diff(vec v, int rankFw, vec w, int use_coeff) const
void mult_row(vec &v, const ring_elem r, int i, bool opposite_mult) const
ring_elem vec_split_off_content(vec f, vec &result) const
virtual ring_elem mult(const ring_elem f, const ring_elem g) const =0
virtual bool is_graded() const
Definition ring.hpp:208
vec vec_divide_by_expvector(const_exponents exp, const vec v) const
ring_elem dot_product(const vecterm *v, const vecterm *w) const
virtual ring_elem eval(const RingMap *map, const ring_elem f, int first_var) const =0
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
Ring()
Definition ring.hpp:136
vec new_vec() const
vector operations ////////////////////
Definition ring-vecs.cpp:54
xxx xxx xxx
Definition ring.hpp:102
Engine-side ring homomorphism: stores, for each source-ring variable, the target-ring element it maps...
Definition ringmap.hpp:60
vecterm * value()
Definition geovec.hpp:172
void add(vecterm *p)
Definition geovec.hpp:93
#define Matrix
Definition factory.cpp:14
#define monomial
Definition gb-toric.cpp:11
static int compare(const vecterm *t, const vecterm *s)
Definition geovec.hpp:112
vecHeap — geometric heap specialised for accumulating vec values.
int p
void freemem(void *s)
Definition m2-mem.cpp:103
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
mpfr_srcptr gmp_RR
Definition m2-types.h:148
mpfr_ptr gmp_RRmutable
Definition m2-types.h:150
Matrix — the engine's immutable homomorphism F -> G between free modules.
#define VECTOR(T)
Definition newdelete.hpp:78
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
Concrete commutative PolyRing — standard polynomial ring inheriting from PolyRingFlat.
tbb::flow::graph G
static bool check_nterm_multiples(const PolyRing *R, ring_elem f1, ring_elem g1, ring_elem c, ring_elem d)
Ring — the legacy abstract base class for every coefficient and polynomial ring.
RingMap — engine representation of a ring homomorphism.
Nterm * next
Definition ringelem.hpp:157
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
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.