Macaulay2 Engine
Loading...
Searching...
No Matches
gbring.cpp
Go to the documentation of this file.
1#include "gbring.hpp"
2
3#include <assert.h>
4#include <stdio.h>
5
6#include "ExponentVector.hpp"
7#include "ZZ.hpp"
8#include "ZZp.hpp"
9#include "aring-glue.hpp"
10#include "coeffrings.hpp"
11#include "freemod.hpp"
12#include "mem.hpp"
13#include "ring.hpp"
14#include "schorder.hpp"
15#include "text-io.hpp"
16#include "weylalg.hpp"
17
18#define sizeofgbvector(s, len) \
19 (sizeof(*s) - sizeof(s->monom) + (len) * sizeof(s->monom[0]))
20
22{
23 buffer o;
24 mem->stats(o);
25 emit(o.str());
26}
27
29{
30 void *p = mem->new_elem();
31 return (reinterpret_cast<gbvector *>(p));
32}
33
34/*************************
35 * Exponent handling *****
36 *************************/
37
39{
40 int *e = newarray_atomic(int, _nvars + 2); // length is nvars
41 return e;
42}
43
47{
48 delete mem; // all other things will be garbage collected
49}
55GBRing::GBRing(const Ring *K0, const Monoid *M0)
56 : _schreyer_encoded(true),
57 M(M0),
58 K(K0),
59 _coeffs_ZZ(false), // set below
60 zzp(nullptr),
61 _nvars(M->n_vars()),
62 _up_order(false),
63 _is_skew(false),
64 _skew(),
65 _skew_monoms(nullptr),
66 is_weyl(false),
67 weyl(nullptr),
68 is_solvable(false),
69 solvable(nullptr),
70 _one(K->from_long(1))
71{
73 monom_size = MONOMIAL_BYTE_SIZE(M->monomial_size());
74
75 gbvector_size = sizeofgbvector(((gbvector *)nullptr), M->monomial_size());
76 mem = new stash("gbvector", gbvector_size);
77
78 const Z_mod *Kp = K->cast_to_Z_mod();
79 if (Kp != nullptr) zzp = Kp->get_CoeffRing();
80
81 if (K == globalQQ) K = globalZZ;
82 if (K == globalZZ) _coeffs_ZZ = true;
83}
84
86// Multiplication routines for Poly, SkewPoly, Weyl, Solvable algebras //
88
90// Polynomial rings //
92
94{
95 return new GBRingPoly(K, M);
96}
97
99 const gbvector *f,
100 ring_elem u,
101 const int *monom,
102 int comp)
103{
104 (void) F;
105 // Remember: this multiplies w/o regard to any quotient elements
106 gbvector head;
107 gbvector *inresult = &head;
108 int monlen = M->monomial_size();
109
110 for (const gbvector *s = f; s != nullptr; s = s->next)
111 {
112 gbvector *t = new_raw_term();
113 t->next = nullptr;
114 t->comp = s->comp + comp;
115 t->coeff = K->mult(u, s->coeff);
116 exponents::mult(monlen, monom, s->monom, t->monom);
117 inresult->next = t;
118 inresult = inresult->next;
119 }
120 inresult->next = nullptr;
121 return head.next;
122}
123
125// Skew commutative polynomial rings //
127
129 const Monoid *M0,
130 SkewMultiplication skew0)
131 : GBRing(K0, M0)
132{
133 _is_skew = true;
134 _skew = skew0;
135 int **skew_monoms = newarray(int *, _skew.n_skew_vars());
136 exponents_t exp = newarray_atomic_clear(int, M0->n_vars());
137 for (int v = 0; v < _skew.n_skew_vars(); v++)
138 {
139 exp[_skew.skew_variable(v)]++;
140 skew_monoms[v] = M0->make_one();
141 M0->from_expvector(exp, skew_monoms[v]);
142 exp[_skew.skew_variable(v)]--;
143 }
144 _skew_monoms = skew_monoms;
145}
146
148 const Monoid *M0,
149 SkewMultiplication skew0)
150{
151 return new GBRingSkew(K0, M0, skew0);
152}
153
155 const gbvector *f,
156 const ring_elem c,
157 const int *m,
158 int comp)
159// Computes c*m*f, BUT NOT doing normal form wrt a quotient ideal..
160{
161 gbvector head;
162 gbvector *inresult = &head;
163
166
167 M->to_expvector(m, EXP1);
168
169 for (const gbvector *s = f; s != nullptr; s = s->next)
170 {
172 int sign = _skew.mult_sign(EXP1, EXP2);
173 if (sign == 0) continue;
174
175 gbvector *t = new_raw_term();
176 t->next = nullptr;
177 t->comp = s->comp + comp;
178 t->coeff = K->mult(c, s->coeff);
179 if (sign < 0) K->negate_to(t->coeff);
180
181 M->mult(m, s->monom, t->monom);
182 inresult->next = t;
183 inresult = inresult->next;
184 }
185 inresult->next = nullptr;
186 return head.next;
187}
188
190// Weyl algebra ///
192GBRingWeyl::GBRingWeyl(const Ring *K0, const Monoid *M0, const WeylAlgebra *R0)
193 : GBRing(K0, M0)
194{
195 is_weyl = true;
196 weyl = R0;
197}
198
200 const Monoid *M0,
201 const WeylAlgebra *R0)
202 : GBRingWeyl(K0, M0, R0)
203{
204 is_weyl = true;
205 weyl = R0;
206}
207
209 const Monoid *M0,
210 const WeylAlgebra *R0)
211{
212 if (K0 == globalZZ) return new GBRingWeylZZ(K0, M0, R0);
213 return new GBRingWeyl(K0, M0, R0);
214}
215
217 const gbvector *f,
218 ring_elem u,
219 const int *monom,
220 int comp)
221{
222 // Remember: this multiplies w/o regard to any quotient elements
223 gbvectorHeap result(this, F);
224 return weyl->gbvector_mult_by_term(result, f, u, monom, comp);
225}
226
228 const gbvector *f,
229 ring_elem u,
230 const int *monom,
231 int comp)
232{
233 // Remember: this multiplies w/o regard to any quotient elements
234 gbvectorHeap result(this, F);
235 return weyl->gbvector_mult_by_term(result, f, u, monom, comp);
236}
237
239// Solvable algebras //
242 const Monoid *M0,
243 const SolvableAlgebra *R0)
244 : GBRing(K0, M0)
245{
246 is_solvable = true;
247 solvable = R0;
248}
249
251 const Monoid *M0,
252 const SolvableAlgebra *R0)
253{
254 return new GBRingSolvable(K0, M0, R0);
255}
256
258 const gbvector *f,
259 ring_elem u,
260 const int *monom,
261 int comp)
262{
263 (void) F;
264 (void) f;
265 (void) u;
266 (void) monom;
267 (void) comp;
268// Remember: this multiplies w/o regard to any quotient elements
269#ifdef DEVELOPMENT
270#warning "implement GBRingSolvable::mult_by_term"
271#endif
272 return nullptr;
273}
274
276// gbvector support //
278
280{
281 // It is not clear whether we should try to free elements of K
282 f->next = nullptr;
283 f->coeff = ZERO_RINGELEM;
284 mem->delete_elem(f);
285 // GC_FREE(reinterpret_cast<char *>(f));
286}
287
289{
290 // It is not clear whether we should try to free elements of K
291 gbvector *f = f0;
292 while (f != nullptr)
293 {
294 gbvector *g = f;
295 f = f->next;
297 }
298}
299
301// Returns coeff*e_sub_i in F, the monomial is set to 1.
302{
303 gbvector *v = new_raw_term();
304 v->coeff = coeff;
305 v->comp = comp;
306 v->next = nullptr;
307 M->one(v->monom);
308
309 const SchreyerOrder *S;
310 if (comp > 0 && _schreyer_encoded && (S = F->get_schreyer_order()) != nullptr)
311 S->schreyer_up(v->monom, comp - 1, v->monom);
312
313 return v;
314}
315
316gbvector *GBRing::gbvector_raw_term(ring_elem coeff, const int *monom, int comp)
317// Returns coeff*monom*e_sub_i in a free module. If the order is a Schreyer
318// order, the 'monom' should already be encoded.
319{
320 gbvector *v = new_raw_term();
321 v->coeff = coeff;
322 v->comp = comp;
323 v->next = nullptr;
324 M->copy(monom, v->monom);
325
326 return v;
327}
328
330 ring_elem coeff,
331 const int *monom,
332 int comp)
333// Returns coeff*monom*e_sub_i in F. If comp is 0, then F is never
334// considered.
335{
336 gbvector *v = gbvector_raw_term(coeff, monom, comp);
337
338 const SchreyerOrder *S;
339 if (comp > 0 && _schreyer_encoded && (S = F->get_schreyer_order()) != nullptr)
340 S->schreyer_up(v->monom, comp - 1, v->monom);
341
342 return v;
343}
344
346 ring_elem coeff,
347 const_exponents exp,
348 int comp)
349// Returns coeff*exp*e_sub_i in F. If comp is 0, then F is never
350// considered.
351// exp should be an exponent vector of length == n_vars()
352{
353 gbvector *v = new_raw_term();
354 v->coeff = coeff;
355 v->comp = comp;
356 v->next = nullptr;
357 M->from_expvector(exp, v->monom);
358
359 const SchreyerOrder *S;
360 if (comp > 0 && _schreyer_encoded && (S = F->get_schreyer_order()) != nullptr)
361 S->schreyer_up(v->monom, comp - 1, v->monom);
362
363 return v;
364}
365
367{
368 gbvector *v = new_raw_term();
369 v->next = nullptr;
370 v->coeff = t->coeff;
371 v->comp = t->comp;
372 M->copy(t->monom, v->monom);
373 return v;
374}
375
376bool GBRing::gbvector_is_equal(const gbvector *a, const gbvector *b) const
377{
378 for (;; a = a->next, b = b->next)
379 {
380 if (a == nullptr)
381 {
382 if (b == nullptr) return true;
383 return false;
384 }
385 if (b == nullptr) return false;
386 if (a->comp != b->comp) return false;
387 if (!K->is_equal(a->coeff, b->coeff)) return false;
388 if (M->compare(a->monom, b->monom) != 0) return false;
389 }
390}
391
393{
394 int result = 0;
395 for (; v != nullptr; v = v->next) result++;
396 return result;
397}
398
400 const gbvector *f,
401 int *&result_degree)
402{
403 /* Return the multi degree of the first term of f */
405
406 gbvector_get_lead_monomial(F, f, MONOM1);
407 result_degree = M->degree_monoid()->make_one();
408 M->multi_degree(MONOM1, result_degree);
409 M->degree_monoid()->mult(
410 result_degree, F->degree(f->comp - 1), result_degree);
411}
412
414 const gbvector *f,
415 const gbvector *g) const
416// Return LT, EQ, GT depending on the monomial order of lead(f), lead(g) in F.
417{
418 int cmp;
419 const SchreyerOrder *S = F->get_schreyer_order();
420
421 if (S)
422 {
425 f->monom, f->comp - 1, g->monom, g->comp - 1);
426 else
427 cmp = S->schreyer_compare(f->monom, f->comp - 1, g->monom, g->comp - 1);
428 }
429 else
430 {
431 // At this point F doesn't have a Schreyer order
432 if (_up_order)
433 cmp = M->compare(f->monom, -f->comp, g->monom, -g->comp);
434 else
435 cmp = M->compare(f->monom, f->comp, g->monom, g->comp);
436 }
437 return cmp;
438}
439
441 const FreeModule *F,
442 const gbvector *v)
443// What should we do with Schreyer orders? This probably doesn't
444// make much sense, except to get lead monomials.
445// If nparts < 0, only take the actual lead term (i.e. one monomial
446// in one component only).
447{
448 (void) F;
449#ifdef DEVELOPMENT
450#warning "Schreyer order question"
451#endif
452 if (v == nullptr) return nullptr;
453 if (nparts < 0)
454 {
455 return gbvector_copy_term(v);
456 }
457 else
458 {
459 int nslots = M->n_slots(nparts);
460 gbvector head;
461 gbvector *result = &head;
462 for (const gbvector *t = v; t != nullptr; t = t->next)
463 {
464 if (M->compare(nslots, t->monom, v->monom) != 0) break;
465 result->next = gbvector_copy_term(t);
466 result = result->next;
467 }
468 result->next = nullptr;
469 return head.next;
470 }
471}
472
473static bool isparallel(M2_arrayint w, int *e, int *f)
474// We assume: w->len is the same as the number of variables.
475{
476 // true if e-f is a positive multiple of w
477
478 int i, j, a = 0, b;
479 int nvars = w->len;
480 for (i = 0; i < nvars; i++)
481 {
482 a = e[i] - f[i];
483 if (a) break;
484 if (w->array[i] != 0) return false;
485 }
486 // i is the first spot where e, f differ
487 for (j = i + 1; j < nvars; j++)
488 {
489 b = e[j] - f[j];
490 if (a * w->array[j] != b * w->array[i]) return false;
491 }
492 return true;
493}
494
496 const FreeModule *F,
497 const gbvector *leadv,
498 const gbvector *v)
499{
500 (void) F;
501 if (v == nullptr) return nullptr;
502
503 // loop through every term of v. Keep those t that satisfy: exp(leadv) -
504 // exp(t)
505 // is a multiple of w
506 //
507
510
511 M->to_expvector(leadv->monom, lead);
512
513 gbvector head;
514 gbvector *result = &head;
515 for (const gbvector *t = v; t != nullptr; t = t->next)
516 {
517 M->to_expvector(t->monom, e);
518 if (leadv == t || isparallel(w, lead, e))
519 {
520 result->next = gbvector_copy_term(t);
521 result = result->next;
522 }
523 }
524 result->next = nullptr;
525 return head.next;
526}
527
529 const gbvector *f,
530 int *result)
531// This copies the monomial to result. If a Schreyer order,
532// the result will NOT be the total monomial.
533{
534 const SchreyerOrder *S;
535 if (_schreyer_encoded && (S = F->get_schreyer_order()) != nullptr && f->comp > 0)
536 S->schreyer_down(f->monom, f->comp - 1, result);
537 else
538 M->copy(f->monom, result);
539}
540
542 const gbvector *f,
543 int *result)
544{
545 const SchreyerOrder *S;
546 if (_schreyer_encoded && (S = F->get_schreyer_order()) != nullptr && f->comp > 0)
547 {
549
550 S->schreyer_down(f->monom, f->comp - 1, MONOM1);
551 M->to_expvector(MONOM1, result);
552 }
553 else
554 M->to_expvector(f->monom, result);
555}
556
558{
559 for (; f != nullptr; f = f->next) K->mult_to(f->coeff, u);
560}
561
563{
564 for (; f != nullptr; f = f->next) K->negate_to(f->coeff);
565}
566
568{
569 gbvector head;
570 gbvector *result = &head;
571 for (const gbvector *t = v; t != nullptr; t = t->next)
572 {
573 result->next = gbvector_copy_term(t);
574 result = result->next;
575 K->mult_to(result->coeff, u);
576 }
577 result->next = nullptr;
578 return head.next;
579}
580
582{
583 gbvector head;
584 gbvector *b = &head;
585 for (; f != nullptr; f = f->next, b = b->next) b->next = gbvector_copy_term(f);
586 b->next = nullptr;
587 return head.next;
588}
589
591 gbvector *&f,
592 gbvector *&g)
593{
594 if (g == nullptr) return;
595 if (f == nullptr)
596 {
597 f = g;
598 g = nullptr;
599 return;
600 }
601 gbvector head;
602 gbvector *result = &head;
603 while (1)
604 {
605 int compare_result = gbvector_compare(F, f, g);
606 if (compare_result == LT)
607 {
608 result->next = g;
609 result = result->next;
610 g = g->next;
611 if (g == nullptr)
612 {
613 result->next = f;
614 f = head.next;
615 return;
616 }
617 }
618 else if (compare_result == GT)
619 {
620 result->next = f;
621 result = result->next;
622 f = f->next;
623 if (f == nullptr)
624 {
625 result->next = g;
626 f = head.next;
627 g = nullptr;
628 return;
629 }
630 }
631 else
632 {
633 gbvector *tmf = f;
634 gbvector *tmg = g;
635 f = f->next;
636 g = g->next;
637 CoefficientRingZZp::elem result_coeff;
638 zzp->init(result_coeff);
639 zzp->add(result_coeff, tmf->coeff.get_int(), tmg->coeff.get_int());
640 tmf->coeff = ring_elem(result_coeff);
641 if (zzp->is_zero(tmf->coeff.get_int()))
642 {
644 }
645 else
646 {
647 result->next = tmf;
648 result = result->next;
649 }
651 if (g == nullptr)
652 {
653 result->next = f;
654 f = head.next;
655 return;
656 }
657 if (f == nullptr)
658 {
659 result->next = g;
660 f = head.next;
661 g = nullptr;
662 return;
663 }
664 }
665 }
666}
667
669{
670 if (g == nullptr) return;
671 if (f == nullptr)
672 {
673 f = g;
674 g = nullptr;
675 return;
676 }
677 if (zzp)
678 {
679 gbvector_add_to_zzp(F, f, g);
680 return;
681 }
682 gbvector head;
683 gbvector *result = &head;
684 while (1) switch (gbvector_compare(F, f, g))
685 {
686 case LT:
687 result->next = g;
688 result = result->next;
689 g = g->next;
690 if (g == nullptr)
691 {
692 result->next = f;
693 f = head.next;
694 return;
695 }
696 break;
697 case GT:
698 result->next = f;
699 result = result->next;
700 f = f->next;
701 if (f == nullptr)
702 {
703 result->next = g;
704 f = head.next;
705 g = nullptr;
706 return;
707 }
708 break;
709 case EQ:
710 gbvector *tmf = f;
711 gbvector *tmg = g;
712 f = f->next;
713 g = g->next;
714 K->add_to(tmf->coeff, tmg->coeff);
715#if 0
716// if (R->is_ZZ_quotient)
717// {
718// ring_elem t = K->remainder(tmf->coeff, R->ZZ_quotient_value);
719// K->remove(tmf->coeff);
720// tmf->coeff = t;
721// }
722#endif
723 if (K->is_zero(tmf->coeff))
724 {
726 }
727 else
728 {
729 result->next = tmf;
730 result = result->next;
731 }
733 if (g == nullptr)
734 {
735 result->next = f;
736 f = head.next;
737 return;
738 }
739 if (f == nullptr)
740 {
741 result->next = g;
742 f = head.next;
743 g = nullptr;
744 return;
745 }
746 break;
747 }
748}
749
751{
752 // Divide f into two lists of equal length, sort each,
753 // then add them together. This allows the same monomial
754 // to appear more than once in 'f'.
755
756 if (f == nullptr || f->next == nullptr) return;
757 gbvector *f1 = nullptr;
758 gbvector *f2 = nullptr;
759 while (f != nullptr)
760 {
761 gbvector *t = f;
762 f = f->next;
763 t->next = f1;
764 f1 = t;
765
766 if (f == nullptr) break;
767 t = f;
768 f = f->next;
769 t->next = f2;
770 f2 = t;
771 }
772
773 gbvector_sort(F, f1);
774 gbvector_sort(F, f2);
775 gbvector_add_to(F, f1, f2);
776 f = f1;
777}
778
780 const FreeModule *F,
781 const gbvector *v,
782 int nterms) const
783{
784 (void) F;
785 if (v == nullptr)
786 {
787 o << "0";
788 return;
789 }
790
791 bool p_one = false;
792 bool p_plus = false;
793 bool p_parens = false;
794 int count = nterms;
795 const gbvector *t;
796 for (t = v; t != nullptr && count != 0; t = t->next, count--)
797 {
798 int isone = (M == nullptr || M->is_one(t->monom));
799 K->elem_text_out(o, t->coeff, p_one, p_plus, p_parens);
800 if (!isone) M->elem_text_out(o, t->monom, p_one);
801 if (t->comp >= 1) o << "<" << t->comp << ">";
802 p_plus = true;
803 }
804 if (t != nullptr) o << "+...";
805}
806
808 const_exponents exp2,
809 int *result) const
810{
811 for (int i = 0; i < _nvars; i++) *result++ = *exp1++ - *exp2++;
812}
813
815 const_exponents exp2,
816 exponents_t exp3,
817 exponents_t exp4)
818{
819 for (int i = 0; i < _nvars; i++)
820 {
821 int a = exp1[i] - exp2[i];
822 if (a > 0)
823 {
824 exp3[i] = 0;
825 exp4[i] = a;
826 }
827 else
828 {
829 exp3[i] = -a;
830 exp4[i] = 0;
831 }
832 }
833}
834
836// mult_by_term routines ////////////////////////////
838
840 const gbvector *f,
841 ring_elem u,
842 const int *monom,
843 int comp)
844{
845 gbvector *result = mult_by_term1(F, f, u, monom, comp);
846 const SchreyerOrder *S;
847 if (comp > 0 && _schreyer_encoded && (S = F->get_schreyer_order()) != nullptr)
848 {
849 for (gbvector *t = result; t != nullptr; t = t->next)
850 S->schreyer_up(t->monom, comp - 1, t->monom);
851 }
852 return result;
853}
854
856 const FreeModule *Fsyz,
857 ring_elem a,
858 const int *m, // element of M, a monomial
859 const gbvector *f,
860 const gbvector *fsyz,
862 gbvector *&result_syz)
863{
864 // TODO
865 // The reason this has both result,result_syz together is in case we want to
866 // reduce result_fsyz mod a quotient ideal. Do we really need to do this as
867 // we go? This will require experimentation.
868 result = mult_by_term(F, f, a, m, 0);
869 result_syz = mult_by_term(Fsyz, fsyz, a, m, 0);
870}
871
873 const gbvector *f,
874 const gbvector *g,
875 ring_elem &u,
876 ring_elem &v)
877{
878 const ring_elem a = f->coeff;
879 const ring_elem b = g->coeff;
880 K->syzygy(a, b, u, v); // If possible, u==1, anyway, u>0
881
883 {
887 gbvector_get_lead_exponents(F, f, EXP1); // Removes the Schreyer part
888 gbvector_get_lead_exponents(F, g, EXP2); // Removes the Schreyer part
889 divide_exponents(EXP1, EXP2, EXP3);
890 if (_skew.mult_sign(EXP3, EXP2) < 0) K->negate_to(v);
891 }
892}
893
895 const gbvector *f,
896 const gbvector *g,
897 ring_elem &v)
898{
899 const ring_elem a = f->coeff;
900 const ring_elem b = g->coeff;
901 ring_elem rem;
902
903 assert(globalZZ == K);
904 rem = globalZZ->remainderAndQuotient(a, b, v);
905 if (globalZZ->is_zero(v)) return false;
906 v = globalZZ->negate(v);
907
909 {
913 gbvector_get_lead_exponents(F, f, EXP1); // Removes the Schreyer part
914 gbvector_get_lead_exponents(F, g, EXP2); // Removes the Schreyer part
915 divide_exponents(EXP1, EXP2, EXP3);
916 if (_skew.mult_sign(EXP3, EXP2) < 0) K->negate_to(v);
917 }
918
919 return globalZZ->is_zero(rem);
920}
921
923 const FreeModule *F,
924 const gbvector *f,
925 const gbvector *g,
926 int &comp,
927 int *&monom) // there must be enough space here
928{
929 M->divide(f->monom, g->monom, monom);
930
931 if (g->comp == 0)
932 {
933 comp = f->comp;
934 const SchreyerOrder *S;
935 if (_schreyer_encoded && (S = F->get_schreyer_order()) != nullptr)
936 S->schreyer_down(monom, comp - 1, monom);
937 }
938 else
939 {
940 comp = 0;
941 }
942}
943
945 const FreeModule *Fsyz,
946 gbvector *flead,
947 gbvector *&f,
948 gbvector *&fsyz,
949 const gbvector *g,
950 const gbvector *gsyz,
951 bool use_denom,
952 ring_elem &denom)
953{
954 int comp;
955 ring_elem u, v;
956
958
959 find_reduction_coeffs(F, f, g, u, v);
960 find_reduction_monomial(F, f, g, comp, MONOM1);
961
962 if (!K->is_equal(u, _one))
963 {
964 gbvector_mult_by_coeff_to(f, u); // modifies f
967 if (use_denom) K->mult_to(denom, u);
968 }
969
970 gbvector *result1 = mult_by_term(F, g, v, MONOM1, comp);
971 gbvector_add_to(F, f, result1);
972 if (gsyz != nullptr)
973 {
974 gbvector *result_syz1 = mult_by_term(Fsyz, gsyz, v, MONOM1, comp);
975 gbvector_add_to(Fsyz, fsyz, result_syz1);
976 }
977}
978
980 const FreeModule *Fsyz,
981 gbvector *flead,
982 gbvector *&f,
983 gbvector *&fsyz,
984 const gbvector *ginitial,
985 const gbvector *g,
986 const gbvector *gsyz,
987 bool use_denom,
988 ring_elem &denom)
989{
990 int comp;
991 ring_elem u, v;
992
994
995 find_reduction_coeffs(F, f, ginitial, u, v);
996 find_reduction_monomial(F, f, ginitial, comp, MONOM1);
997
998 if (!K->is_equal(u, _one))
999 {
1000 gbvector_mult_by_coeff_to(f, u); // modifies f
1001 gbvector_mult_by_coeff_to(flead, u);
1003 if (use_denom) K->mult_to(denom, u);
1004 }
1005
1006 gbvector *result1 = mult_by_term(F, g, v, MONOM1, comp);
1007 gbvector_add_to(F, f, result1);
1008 if (gsyz != nullptr)
1009 {
1010 gbvector *result_syz1 = mult_by_term(Fsyz, gsyz, v, MONOM1, comp);
1011 gbvector_add_to(Fsyz, fsyz, result_syz1);
1012 }
1013}
1014
1016 const FreeModule *Fsyz,
1017 gbvector *flead,
1018 gbvector *&f,
1019 gbvector *&fsyz,
1020 const gbvector *g,
1021 const gbvector *gsyz)
1022{
1023 ring_elem junk;
1024 gbvector_reduce_lead_term(F, Fsyz, flead, f, fsyz, g, gsyz, false, junk);
1025}
1026
1028 const FreeModule *Fsyz,
1029 gbvector *&f,
1030 gbvector *&fsyz,
1031 const gbvector *g,
1032 const gbvector *gsyz)
1033// Never multiplies f by anything. IE before(f), after(f) are equiv. mod g.
1034// this should ONLY be used if K is globalZZ.
1035{
1036 int comp;
1037 ring_elem v;
1038
1040
1041 bool result = find_reduction_coeffs_ZZ(F, f, g, v);
1042 if (K->is_zero(v)) return false;
1043
1044 find_reduction_monomial(F, f, g, comp, MONOM1);
1045
1046 gbvector *result1 = mult_by_term(F, g, v, MONOM1, comp);
1047 gbvector_add_to(F, f, result1);
1048 if (gsyz != nullptr)
1049 {
1050 gbvector *result_syz1 = mult_by_term(Fsyz, gsyz, v, MONOM1, comp);
1051 gbvector_add_to(Fsyz, fsyz, result_syz1);
1052 }
1053 return result;
1054}
1055
1057 const FreeModule *Fsyz,
1058 const gbvector *f,
1059 const gbvector *fsyz,
1060 const gbvector *g,
1061 const gbvector *gsyz,
1062 gbvector *&result,
1063 gbvector *&result_syz)
1064// If u*x^A*leadmonom(f) = v*x^B*leadmonom(g) (mod lower terms),
1065// set result := u*x^A*f - v*x^B*g
1066// resultsyz := u*x^A*fsyz - v*x^B*gyz
1067// To keep in mind:
1068// (a) Schreyer orders
1069// (b) Quotient ideal
1070// Currently: this does nothing with the quotient ring
1071{
1072 int comp;
1073 const ring_elem a = f->coeff;
1074 const ring_elem b = g->coeff;
1075 ring_elem u, v;
1076
1081
1084
1085 K->syzygy(a, b, u, v); // If possible, u==1, anyway, u>0
1086 gbvector_get_lead_exponents(F, f, EXP1); // Removes the Schreyer part
1087 gbvector_get_lead_exponents(F, g, EXP2); // Removes the Schreyer part
1088 exponent_syzygy(EXP1, EXP2, EXP3, EXP4);
1089 if (g->comp == 0)
1090 comp = f->comp;
1091 else
1092 comp = 0;
1093 if (is_skew_commutative())
1094 {
1095 // Note that EXP3 * EXP1 = EXP4 * EXP2 up to sign
1096 if (_skew.mult_sign(EXP3, EXP1) != _skew.mult_sign(EXP4, EXP2))
1097 K->negate_to(v);
1098 }
1099 M->from_expvector(EXP3, MONOM1);
1100 M->from_expvector(EXP4, MONOM2);
1101 result = mult_by_term(F, f, u, MONOM1, 0);
1102 gbvector *result1 = mult_by_term(F, g, v, MONOM2, comp);
1103 gbvector_add_to(F, result, result1);
1104 if (fsyz == nullptr && gsyz == nullptr)
1105 result_syz = nullptr;
1106 else
1107 {
1108 result_syz = mult_by_term(Fsyz, fsyz, u, MONOM1, 0);
1109 gbvector *result_syz1 = mult_by_term(Fsyz, gsyz, v, MONOM2, comp);
1110 gbvector_add_to(Fsyz, result_syz, result_syz1);
1111 }
1112}
1113
1115 const FreeModule *Fsyz,
1116 gbvector *&f,
1117 gbvector *&fsyz,
1118 gbvector *&g,
1119 gbvector *&gsyz)
1120{
1121 // ASSUMPTIONS: coefficient ring is ZZ
1122 // lead monomial of f and g are the same (with possibly different coeffs)
1123 // If u * leadcoeff(f) + v * leadcoeff(g) = gd is the gcd,
1124 // then:
1125 // g <-- u * f + v * g
1126 // f <-- c * f - d * g, where c = leadcoeff(g)//gd, d = leadcoeff(f)//gd
1127 mpz_t u, v, gd;
1128 mpz_init(u);
1129 mpz_init(v);
1130 mpz_init(gd);
1131 mpz_gcdext(gd, u, v, f->coeff.get_mpz(), g->coeff.get_mpz());
1132
1133 gbvector *new_g = nullptr;
1134 gbvector *g2 = nullptr;
1135 gbvector *new_gsyz = nullptr;
1136 gbvector *gsyz2 = nullptr;
1137
1138 if (mpz_sgn(v) != 0)
1139 {
1141 gsyz2 = gbvector_mult_by_coeff(gsyz, ring_elem(v));
1142 }
1143 if (mpz_sgn(u) != 0)
1144 {
1145 new_g = gbvector_mult_by_coeff(f, ring_elem(u));
1146 new_gsyz = gbvector_mult_by_coeff(fsyz, ring_elem(u));
1147 }
1148
1149 gbvector_add_to(F, new_g, g2);
1150 gbvector_add_to(Fsyz, new_gsyz, gsyz2);
1151
1152 mpz_fdiv_q(u, g->coeff.get_mpz(), gd);
1153 mpz_fdiv_q(v, f->coeff.get_mpz(), gd);
1154 mpz_neg(v, v);
1155
1157 gbvector *new_fsyz = gbvector_mult_by_coeff(fsyz, ring_elem(u));
1159 gbvector *fsyz2 = gbvector_mult_by_coeff(gsyz, ring_elem(v));
1160
1161 gbvector_add_to(F, new_f, f2);
1162 gbvector_add_to(Fsyz, new_fsyz, fsyz2);
1163
1164 f = new_f;
1165 fsyz = new_fsyz;
1166 g = new_g;
1167 gsyz = new_gsyz;
1168
1169 mpz_clear(u);
1170 mpz_clear(v);
1171 mpz_clear(gd);
1172}
1173
1175 const FreeModule *Fsyz,
1176 const gbvector *f,
1177 const gbvector *fsyz,
1178 const gbvector *g,
1179 const gbvector *gsyz,
1180 gbvector *&result,
1181 gbvector *&result_syz)
1182// If u*x^A*leadmonom(f) + v*x^B*leadmonom(g) = gcd(u,v)*monom (mod lower
1183// terms),
1184// set result := u*x^A*f + v*x^B*g
1185// resultsyz := u*x^A*fsyz + v*x^B*gyz
1186// To keep in mind:
1187// (a) Schreyer orders
1188// (b) Quotient ideal
1189// Currently: this does nothing with the quotient ring
1190{
1191 int comp;
1192 const ring_elem a = f->coeff;
1193 const ring_elem b = g->coeff;
1194 mpz_t gab, u1, v1;
1195
1200
1203
1204 mpz_init(gab);
1205 mpz_init(u1);
1206 mpz_init(v1);
1207 mpz_gcdext(gab, u1, v1, a.get_mpz(), b.get_mpz());
1208 mpz_clear(gab);
1209 //these ring_elem must not escape the function, because they aren't allocated on
1210 //the gc heap
1211 ring_elem u = ring_elem(u1);
1212 ring_elem v = ring_elem(v1);
1213 if (globalZZ->is_zero(u) || globalZZ->is_zero(v))
1214 {
1215 result = nullptr;
1216 result_syz = nullptr;
1217 mpz_clear(u1);
1218 mpz_clear(v1);
1219 return;
1220 }
1221 gbvector_get_lead_exponents(F, f, EXP1); // Removes the Schreyer part
1222 gbvector_get_lead_exponents(F, g, EXP2); // Removes the Schreyer part
1223 exponent_syzygy(EXP1, EXP2, EXP3, EXP4);
1224 if (g->comp == 0)
1225 comp = f->comp;
1226 else
1227 comp = 0;
1228 if (is_skew_commutative())
1229 {
1230 // Note that EXP3 * EXP1 = EXP4 * EXP2 up to sign
1231 if (_skew.mult_sign(EXP3, EXP1) != _skew.mult_sign(EXP4, EXP2))
1232 K->negate_to(v);
1233 }
1234 M->from_expvector(EXP3, MONOM1);
1235 M->from_expvector(EXP4, MONOM2);
1236 result = mult_by_term(F, f, u, MONOM1, 0);
1237 gbvector *result1 = mult_by_term(F, g, v, MONOM2, comp);
1238 gbvector_add_to(F, result, result1);
1239 if (fsyz == nullptr && gsyz == nullptr)
1240 result_syz = nullptr;
1241 else
1242 {
1243 result_syz = mult_by_term(Fsyz, fsyz, u, MONOM1, 0);
1244 gbvector *result_syz1 = mult_by_term(Fsyz, gsyz, v, MONOM2, comp);
1245 gbvector_add_to(Fsyz, result_syz, result_syz1);
1246 }
1247 mpz_clear(u1);
1248 mpz_clear(v1);
1249}
1250
1252 const FreeModule *Fsyz,
1253 gbvector *&f,
1254 gbvector *&fsyz,
1255 const gbvector *gsyz,
1256 const gbvector **elems,
1257 const gbvector **elems_syz,
1258 const gbvector **quotients)
1259{
1260 // modifies (f,fsyz)
1261 // gsyz is allowed to have negative elements. These refer to
1262 // quotient ring elements. In this case, the component that
1263 // is used is the lead component of f. (i.e. this is designed for
1264 // cancelling lead terms).
1265 // [combines: freemod::apply_quotient_ring_elements,
1266 // GBZZ_comp::apply_gb_elements]
1267
1268 for (; gsyz != nullptr; gsyz = gsyz->next)
1269 {
1270 if (gsyz->comp < 0)
1271 {
1273 F, quotients[-1 - gsyz->comp], gsyz->coeff, gsyz->monom, f->comp);
1274 gbvector_add_to(F, f, v);
1275 }
1276 else
1277 {
1278 gbvector *v =
1279 mult_by_term(F, elems[gsyz->comp], gsyz->coeff, gsyz->monom, 0);
1280 gbvector_add_to(F, f, v);
1281 gbvector *vsyz = mult_by_term(
1282 Fsyz, elems_syz[gsyz->comp], gsyz->coeff, gsyz->monom, 0);
1283 gbvector_add_to(Fsyz, fsyz, vsyz);
1284 }
1285 }
1286}
1287
1289// Content removal //
1292{
1293 mpz_t a;
1294 mpz_init(a);
1295 for (; f != nullptr; f = f->next)
1296 {
1297 mpz_divexact(a, f->coeff.get_mpz(), u);
1298 f->coeff = globalZZ->RingZZ::from_int(a);
1299 }
1300 mpz_clear(a);
1301}
1302
1303void GBRing::lower_content_ZZ(gbvector *f, mpz_ptr content) const
1304// content should be a positive number. Modify this value
1305// so that new value of content = gcd(old-content, content(f)).
1306{
1307 if (f == nullptr) return;
1308 for (; f != nullptr; f = f->next)
1309 {
1310 mpz_gcd(content, content, f->coeff.get_mpz());
1311 if (mask_mpz_cmp_si(content, 1) == 0) return;
1312 }
1313}
1314
1316 gbvector *fsyz,
1317 bool use_denom,
1318 ring_elem &denom) const
1319// let c = gcd(content(f),content(fsyz)).
1320// set f := f/c, fsyz := fsyz/c.
1321// denom *= c
1322{
1323 // This routine assumes that the coeff ring is ZZ (originally QQ).
1324 gbvector *g = f;
1325 gbvector *gsyz = fsyz;
1326 mpz_t content;
1327 int leadsign;
1328 if (g != nullptr)
1329 {
1330 leadsign = mpz_sgn(g->coeff.get_mpz());
1331 mpz_init_set(content, g->coeff.get_mpz());
1332 g = g->next;
1333 }
1334 else if (gsyz != nullptr)
1335 {
1336 leadsign = mpz_sgn(gsyz->coeff.get_mpz());
1337 mpz_init_set(content, gsyz->coeff.get_mpz());
1338 gsyz = gsyz->next;
1339 }
1340 else
1341 return;
1342
1343 lower_content_ZZ(g, content);
1344 lower_content_ZZ(gsyz, content);
1345
1346 mpz_abs(content, content);
1347 if (mask_mpz_cmp_si(content, 1) == 0)
1348 {
1349 mpz_clear(content);
1350
1351 if (leadsign < 0)
1352 {
1354 gbvector_negate_to(fsyz);
1355 }
1356 return;
1357 }
1358
1359 if (leadsign < 0) mpz_neg(content, content);
1360 divide_coeff_exact_to_ZZ(f, content);
1361 divide_coeff_exact_to_ZZ(fsyz, content);
1362 if (use_denom)
1363 {
1364 denom = globalZZ->mult(denom, ring_elem(content));
1365 }
1366 mpz_clear(content);
1367}
1368
1370 gbvector *fsyz,
1371 bool use_denom,
1372 ring_elem &denom)
1373// let c = gcd(content(f),content(fsyz)).
1374// set f := f/c, fsyz := fsyz/c, denom *= c.
1375// If K is not ZZ, then c is set to make f monic.
1376//
1377{
1378 if (_coeffs_ZZ)
1379 {
1380 gbvector_remove_content_ZZ(f, fsyz, use_denom, denom);
1381 return;
1382 }
1383 // At this point, our coefficient ring is a field (What about
1384 // finite extensions of ZZ?)
1385 ring_elem c, cinv;
1386 if (f != nullptr)
1387 c = f->coeff;
1388 else if (fsyz != nullptr)
1389 c = fsyz->coeff;
1390 else
1391 return;
1392 cinv = K->invert(c);
1394 gbvector_mult_by_coeff_to(fsyz, cinv);
1395 if (use_denom) K->mult_to(denom, c);
1396}
1397
1399// let c = gcd(content(f),content(fsyz)).
1400// set f := f/c, fsyz := fsyz/c.
1401{
1402 ring_elem junk;
1403 gbvector_remove_content(f, fsyz, false, junk);
1404}
1405
1407// Auto-reduction //
1410 const gbvector *f,
1411 const gbvector *g) const
1412/* If the monomial (g->monom,g->comp) appears exactly in f,
1413 then return a pointer to that term, if not, return 0. */
1414{
1415 while (f != nullptr)
1416 {
1417 int cmp = gbvector_compare(F, f, g);
1418 if (cmp == LT)
1419 break;
1420 else if (cmp == EQ)
1421 return f;
1422 else
1423 f = f->next;
1424 }
1425 return nullptr;
1426}
1427
1429 const FreeModule *Fsyz,
1430 gbvector *&f,
1431 gbvector *&fsyz,
1432 const gbvector *g,
1433 const gbvector *gsyz)
1434// If g = a*x^A*ei + lower terms
1435// and if f = ... + b*x^A*ei + ...
1436// and if u*a + v*b = 0
1437// then set f := u*f - v*g, fsyz := u*fsyz - v*gsyz
1438{
1439 const gbvector *t;
1440 if ((t = find_coeff(F, f, g)) != nullptr)
1441 {
1442 ring_elem u, v;
1443 K->syzygy(t->coeff, g->coeff, u, v);
1444 if (!K->is_equal(u, _one))
1445 {
1448 }
1449 gbvector *g1 = gbvector_mult_by_coeff(g, v);
1450 gbvector *gsyz1 = gbvector_mult_by_coeff(gsyz, v);
1451 gbvector_add_to(F, f, g1);
1452 gbvector_add_to(Fsyz, fsyz, gsyz1);
1453 gbvector_remove_content(f, fsyz);
1454
1455 if (M2_gbTrace == 10)
1456 {
1457 buffer o;
1458 o << "auto reducing by ";
1459 gbvector_text_out(o, F, g);
1460 o << "\n -- giving ";
1461 gbvector_text_out(o, F, f);
1462 emit_line(o.str());
1463 }
1464 }
1465}
1466
1468 const FreeModule *Fsyz,
1469 gbvector *&f,
1470 gbvector *&fsyz,
1471 const gbvector *g,
1472 const gbvector *gsyz)
1473// If g = a*x^A*ei + lower terms
1474// and if f = ... + b*x^A*ei + ...
1475// and if v*a + b is the balanced remainder of b by a
1476// then set f := f + v*g, fsyz := fsyz + v*gsyz
1477// No content is removed.
1478{
1479 assert(globalZZ == K);
1480 const gbvector *t;
1481 if ((t = find_coeff(F, f, g)) != nullptr)
1482 {
1483 ring_elem v = globalZZ->quotient(t->coeff, g->coeff);
1484 if (globalZZ->is_zero(v)) return;
1485 v = globalZZ->negate(v);
1486 gbvector *g1 = gbvector_mult_by_coeff(g, v);
1487 gbvector *gsyz1 = gbvector_mult_by_coeff(gsyz, v);
1488 gbvector_add_to(F, f, g1);
1489 gbvector_add_to(Fsyz, fsyz, gsyz1);
1490
1491 if (M2_gbTrace == 10)
1492 {
1493 buffer o;
1494 o << "auto reducing by ";
1495 gbvector_text_out(o, F, g);
1496 o << "\n -- giving ";
1497 gbvector_text_out(o, F, f);
1498 emit_line(o.str());
1499 }
1500 }
1501}
1502
1504// gbvector heap operations //
1506
1508 : GR(GR0),
1509 F(FF),
1510 K(GR0->get_flattened_coefficients()),
1511 top_of_heap(-1),
1512 mLead(-1)
1513{
1514 // set K
1515 int i;
1516 for (i = 0; i < GEOHEAP_SIZE; i++) heap[i] = nullptr;
1517}
1518
1520{
1521 // The user of this class must insure that all 'vecterm's
1522 // have been removed first. Thus, we don't need to
1523 // do anything here.
1524}
1525
1527{
1528 for (int i = top_of_heap; i >= 0; i--)
1529 if (heap[i] != nullptr) GR->gbvector_mult_by_coeff_to(heap[i], a);
1530}
1531
1533{
1534 mLead = -1;
1535 int len = GR->gbvector_n_terms(p);
1536 int i = 0;
1537 while (len >= heap_size[i]) i++;
1538 GR->gbvector_add_to(F, heap[i], p);
1539 len = GR->gbvector_n_terms(heap[i]);
1540 p = nullptr;
1541 while (len >= heap_size[i])
1542 {
1543 i++;
1544 GR->gbvector_add_to(F, heap[i], heap[i - 1]);
1545 len = GR->gbvector_n_terms(heap[i]);
1546 heap[i - 1] = nullptr;
1547 }
1548 if (i > top_of_heap) top_of_heap = i;
1549}
1550
1552{
1553 int lead_so_far = -1;
1554 for (int i = 0; i <= top_of_heap; i++)
1555 {
1556 if (heap[i] == nullptr) continue;
1557 if (lead_so_far < 0)
1558 {
1559 lead_so_far = i;
1560 continue;
1561 }
1562 int cmp = GR->gbvector_compare(F, heap[lead_so_far], heap[i]);
1563 if (cmp == GT) continue;
1564 if (cmp == LT)
1565 {
1566 lead_so_far = i;
1567 continue;
1568 }
1569 // At this point we have equality
1570 K->add_to(heap[lead_so_far]->coeff, heap[i]->coeff);
1571 gbvector *tmp = heap[i];
1572 heap[i] = tmp->next;
1573 tmp->next = nullptr;
1574 GR->gbvector_remove(tmp);
1575
1576 if (K->is_zero(heap[lead_so_far]->coeff))
1577 {
1578 // Remove, and start over
1579 tmp = heap[lead_so_far];
1580 heap[lead_so_far] = tmp->next;
1581 tmp->next = nullptr;
1582 GR->gbvector_remove(tmp);
1583 lead_so_far = -1;
1584 i = -1;
1585 }
1586 }
1587 mLead = lead_so_far;
1588 if (lead_so_far < 0) return nullptr;
1589 gbvector *result = heap[lead_so_far];
1590 return result;
1591}
1593{
1594 if (mLead < 0) get_lead_term();
1595 if (mLead < 0) return nullptr;
1597 heap[mLead] = result->next;
1598 result->next = nullptr;
1599 mLead = -1;
1600 return result;
1601}
1602
1604{
1605 gbvector *result = nullptr;
1606 for (int i = 0; i <= top_of_heap; i++)
1607 {
1608 if (heap[i] == nullptr) continue;
1609 GR->gbvector_add_to(F, result, heap[i]);
1610 heap[i] = nullptr;
1611 }
1612 top_of_heap = -1;
1613 return result;
1614}
1615
1617{
1618 gbvector *result = nullptr;
1619 for (int i = 0; i <= top_of_heap; i++)
1620 {
1621 if (heap[i] == nullptr) continue;
1622 gbvector *tmp = GR->gbvector_copy(heap[i]);
1623 GR->gbvector_add_to(F, result, tmp);
1624 }
1625 return result;
1626}
1627
1628#include "debug.hpp"
1630{
1631 for (int i = 0; i <= top_of_heap; i++)
1632 {
1633 if (heap[i] == nullptr) continue;
1634 printf("%d ", i);
1635 dgbvec(GR, heap[i]);
1636 printf("\n");
1637 }
1638}
1639
1641 const FreeModule *F,
1642 const FreeModule *Fsyz,
1643 const gbvector *fcurrent_lead,
1644 const_exponents exp, // exponents of fcurrent_lead
1645 gbvector *flead,
1646 gbvectorHeap &f,
1647 gbvectorHeap &fsyz,
1648 const gbvector
1649 *marked_in_g, // lead term of g to use to determine multipliers
1650 const gbvector *g,
1651 const gbvector *gsyz)
1652{
1653 int comp;
1654 ring_elem u, v;
1655
1657
1658 (void) exp;
1659 find_reduction_coeffs(F, fcurrent_lead, marked_in_g, u, v);
1660 find_reduction_monomial(F, fcurrent_lead, marked_in_g, comp, MONOM1);
1661
1662 if (!K->is_equal(u, _one))
1663 {
1664 gbvector_mult_by_coeff_to(flead, u);
1665 f.mult_by_coeff(u);
1666 fsyz.mult_by_coeff(u);
1667 }
1668
1669 gbvector *result1 = mult_by_term(F, g, v, MONOM1, comp);
1670 f.add(result1);
1671 if (gsyz != nullptr)
1672 {
1673 gbvector *result_syz1 = mult_by_term(Fsyz, gsyz, v, MONOM1, comp);
1674 fsyz.add(result_syz1);
1675 }
1676}
1677
1679 const FreeModule *F,
1680 const FreeModule *Fsyz,
1681 const gbvector *fcurrent_lead,
1682 const_exponents exp, // exponents of fcurrent_lead
1683 gbvector *flead,
1684 gbvectorHeap &f,
1685 gbvectorHeap &fsyz,
1686 const gbvector *g,
1687 const gbvector *gsyz)
1688{
1690 F, Fsyz, fcurrent_lead, exp, flead, f, fsyz, g, g, gsyz);
1691}
1692
1693// Local Variables:
1694// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1695// indent-tabs-mode: nil
1696// End:
exponents::ConstExponents const_exponents
exponents::Exponents exponents_t
Dense exponent-vector template [e_0, ..., e_{nvars-1}] for monomial operations.
int mask_mpz_cmp_si(mpz_srcptr x, long int i)
Definition ZZ.hpp:53
Legacy RingZZ — a Ring-derived integer ring backed by GMP mpz_t.
Legacy Z_mod — a Ring-derived Z/p with log / exp tables.
const RingQQ * globalQQ
Definition aring.cpp:24
ConcreteRing<RingType> — the templated bridge between aring and the legacy Ring API.
static void mult(int nvars, ConstExponents a, ConstExponents b, Exponents result)
const_monomial degree(int i) const
Definition freemod.hpp:104
const SchreyerOrder * get_schreyer_order() const
Definition freemod.hpp:103
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
void gbvector_mult_by_coeff_to(gbvector *f, ring_elem u)
Definition gbring.cpp:557
CoefficientRingZZp * zzp
Definition gbring.hpp:141
static GBRing * create_WeylAlgebra(const Ring *K0, const Monoid *M0, const WeylAlgebra *W0)
Definition gbring.cpp:208
void exponents_delete(exponents_t e)
Definition gbring.cpp:44
gbvector * gbvector_copy(const gbvector *f)
Definition gbring.cpp:581
friend class WeylAlgebra
Definition gbring.hpp:122
const WeylAlgebra * weyl
Definition gbring.hpp:158
static GBRing * create_SkewPolynomialRing(const Ring *K0, const Monoid *M0, SkewMultiplication skew0)
Definition gbring.cpp:147
gbvector * mult_by_term(const FreeModule *F, const gbvector *f, ring_elem u, const int *monom, int comp)
Definition gbring.cpp:839
bool gbvector_reduce_lead_term_ZZ(const FreeModule *F, const FreeModule *Fsyz, gbvector *&f, gbvector *&fsyz, const gbvector *g, const gbvector *gsyz)
Definition gbring.cpp:1027
void gbvector_remove(gbvector *f)
Definition gbring.cpp:288
stash * mem
Definition gbring.hpp:144
static GBRing * create_PolynomialRing(const Ring *K, const Monoid *M)
Definition gbring.cpp:93
ring_elem _one
Definition gbring.hpp:164
void gbvector_remove_content_ZZ(gbvector *f, gbvector *fsyz, bool use_denom, ring_elem &denom) const
Definition gbring.cpp:1315
bool is_weyl
Definition gbring.hpp:157
bool is_skew_commutative() const
Definition gbring.hpp:240
bool _schreyer_encoded
Definition gbring.hpp:136
bool _coeffs_ZZ
Definition gbring.hpp:140
void gbvector_get_lead_monomial(const FreeModule *F, const gbvector *f, int *result)
Definition gbring.cpp:528
void gbvector_add_to_zzp(const FreeModule *F, gbvector *&f, gbvector *&g)
Definition gbring.cpp:590
size_t monom_size
Definition gbring.hpp:170
bool gbvector_is_equal(const gbvector *f, const gbvector *g) const
Definition gbring.cpp:376
void gbvector_text_out(buffer &o, const FreeModule *F, const gbvector *f, int nterms=-1) const
Definition gbring.cpp:779
GBRing(const Ring *K0, const Monoid *M0)
Definition gbring.cpp:55
bool _is_skew
Definition gbring.hpp:150
void divide_exponents(const int *exp1, const int *exp2, int *result) const
Definition gbring.cpp:807
const SolvableAlgebra * solvable
Definition gbring.hpp:161
size_t exp_size
Definition gbring.hpp:169
void gbvector_cancel_lead_terms(const FreeModule *F, const FreeModule *Fsyz, const gbvector *f, const gbvector *fsyz, const gbvector *g, const gbvector *gsyz, gbvector *&result, gbvector *&result_syz)
Definition gbring.cpp:1056
gbvector * gbvector_parallel_lead_terms(M2_arrayint w, const FreeModule *F, const gbvector *leadv, const gbvector *v)
Definition gbring.cpp:495
void reduce_marked_lead_term_heap(const FreeModule *F, const FreeModule *Fsyz, const gbvector *fcurrent_lead, const_exponents exp, gbvector *flead, gbvectorHeap &f, gbvectorHeap &fsyz, const gbvector *marked_in_g, const gbvector *g, const gbvector *gsyz)
Definition gbring.cpp:1640
void gbvector_mult_by_term(const FreeModule *F, const FreeModule *Fsyz, ring_elem a, const int *m, const gbvector *f, const gbvector *fsyz, gbvector *&result, gbvector *&esult_syz)
Definition gbring.cpp:855
bool is_solvable
Definition gbring.hpp:160
gbvector * gbvector_term(const FreeModule *F, ring_elem coeff, int comp)
Definition gbring.cpp:300
SkewMultiplication _skew
Definition gbring.hpp:151
int _nvars
Definition gbring.hpp:146
gbvector * gbvector_raw_term(ring_elem coeff, const int *monom, int comp)
Definition gbring.cpp:316
void find_reduction_monomial(const FreeModule *F, const gbvector *f, const gbvector *g, int &comp, int *&monom)
Definition gbring.cpp:922
void reduce_lead_term_heap(const FreeModule *F, const FreeModule *Fsyz, const gbvector *fcurrent_lead, const_exponents exp, gbvector *flead, gbvectorHeap &f, gbvectorHeap &fsyz, const gbvector *g, const gbvector *gsyz)
Definition gbring.cpp:1678
void gbvector_replace_2by2_ZZ(const FreeModule *F, const FreeModule *Fsyz, gbvector *&f, gbvector *&fsyz, gbvector *&g, gbvector *&gsyz)
Definition gbring.cpp:1114
void gbvector_remove_content(gbvector *f, gbvector *fsyz, bool use_denom, ring_elem &denom)
Definition gbring.cpp:1369
void find_reduction_coeffs(const FreeModule *F, const gbvector *f, const gbvector *g, ring_elem &u, ring_elem &v)
Definition gbring.cpp:872
void gbvector_combine_lead_terms_ZZ(const FreeModule *F, const FreeModule *Fsyz, const gbvector *f, const gbvector *fsyz, const gbvector *g, const gbvector *gsyz, gbvector *&result, gbvector *&result_syz)
Definition gbring.cpp:1174
const Monoid * M
Definition gbring.hpp:137
gbvector * new_raw_term()
Definition gbring.cpp:28
gbvector * gbvector_lead_term(int n, const FreeModule *F, const gbvector *f)
Definition gbring.cpp:440
virtual ~GBRing()
Definition gbring.cpp:46
void memstats()
Definition gbring.cpp:21
void gbvector_reduce_with_marked_lead_term(const FreeModule *F, const FreeModule *Fsyz, gbvector *flead, gbvector *&f, gbvector *&fsyz, const gbvector *ginitial, const gbvector *g, const gbvector *gsyz, bool use_denom, ring_elem &denom)
Definition gbring.cpp:979
void lower_content_ZZ(gbvector *f, mpz_ptr content) const
Definition gbring.cpp:1303
void gbvector_negate_to(gbvector *f) const
Definition gbring.cpp:562
int gbvector_compare(const FreeModule *F, const gbvector *f, const gbvector *g) const
Definition gbring.cpp:413
const Ring * K
Definition gbring.hpp:138
static GBRing * create_SolvableAlgebra(const Ring *K0, const Monoid *M0, const SolvableAlgebra *R)
Definition gbring.cpp:250
void gbvector_add_to(const FreeModule *F, gbvector *&f, gbvector *&g)
Definition gbring.cpp:668
void gbvector_auto_reduce(const FreeModule *F, const FreeModule *Fsyz, gbvector *&f, gbvector *&fsyz, const gbvector *g, const gbvector *gsyz)
Definition gbring.cpp:1428
const gbvector * find_coeff(const FreeModule *F, const gbvector *f, const gbvector *g) const
Definition gbring.cpp:1409
bool _up_order
Definition gbring.hpp:148
gbvector * gbvector_copy_term(const gbvector *t)
Definition gbring.cpp:366
void gbvector_sort(const FreeModule *F, gbvector *&f)
Definition gbring.cpp:750
size_t gbvector_size
Definition gbring.hpp:143
int n_vars() const
Definition gbring.hpp:232
void gbvector_apply(const FreeModule *F, const FreeModule *Fsyz, gbvector *&f, gbvector *&fsyz, const gbvector *gsyz, const gbvector **elems, const gbvector **elems_syz, const gbvector **quotients)
Definition gbring.cpp:1251
void gbvector_multidegree(const FreeModule *F, const gbvector *f, int *&result_degree)
Definition gbring.cpp:399
void gbvector_auto_reduce_ZZ(const FreeModule *F, const FreeModule *Fsyz, gbvector *&f, gbvector *&fsyz, const gbvector *g, const gbvector *gsyz)
Definition gbring.cpp:1467
void gbvector_remove_term(gbvector *f)
Definition gbring.cpp:279
void gbvector_get_lead_exponents(const FreeModule *F, const gbvector *f, int *result)
Definition gbring.cpp:541
void exponent_syzygy(const int *exp1, const int *exp2, int *exp3, int *exp4)
Definition gbring.cpp:814
exponents_t exponents_make()
Definition gbring.cpp:38
gbvector * gbvector_term_exponents(const FreeModule *F, ring_elem coeff, const int *exp, int comp)
Definition gbring.cpp:345
void divide_coeff_exact_to_ZZ(gbvector *f, gmp_ZZ u) const
Definition gbring.cpp:1291
int gbvector_n_terms(const gbvector *f) const
Definition gbring.cpp:392
bool find_reduction_coeffs_ZZ(const FreeModule *F, const gbvector *f, const gbvector *g, ring_elem &v)
Definition gbring.cpp:894
void gbvector_reduce_lead_term(const FreeModule *F, const FreeModule *Fsyz, gbvector *flead, gbvector *&f, gbvector *&fsyz, const gbvector *g, const gbvector *gsyz, bool use_denom, ring_elem &denom)
Definition gbring.cpp:944
int *const * _skew_monoms
Definition gbring.hpp:153
virtual gbvector * mult_by_term1(const FreeModule *F, const gbvector *f, ring_elem u, const int *monom, int comp)=0
gbvector * gbvector_mult_by_coeff(const gbvector *f, ring_elem u)
Definition gbring.cpp:567
Polynomial-ring view tuned for the inner loop of classical Buchberger Groebner-basis computations.
Definition gbring.hpp:120
virtual gbvector * mult_by_term1(const FreeModule *F, const gbvector *f, ring_elem u, const int *monom, int comp)
Definition gbring.cpp:98
virtual ~GBRingPoly()
Definition gbring.cpp:50
GBRing specialisation for ordinary commutative polynomial rings.
Definition gbring.hpp:572
virtual ~GBRingSkew()
Definition gbring.cpp:53
GBRingSkew(const Ring *K0, const Monoid *M0, SkewMultiplication skew0)
Definition gbring.cpp:128
virtual gbvector * mult_by_term1(const FreeModule *F, const gbvector *f, ring_elem u, const int *monom, int comp)
Definition gbring.cpp:154
friend class GBRing
Definition gbring.hpp:647
GBRing specialisation for skew-commutative (exterior-like) polynomial rings.
Definition gbring.hpp:645
GBRingSolvable(const Ring *K0, const Monoid *M0, const SolvableAlgebra *R0)
Definition gbring.cpp:241
virtual gbvector * mult_by_term1(const FreeModule *F, const gbvector *f, ring_elem u, const int *monom, int comp)
Definition gbring.cpp:257
friend class GBRing
Definition gbring.hpp:673
virtual ~GBRingSolvable()
Definition gbring.cpp:54
GBRing specialisation for solvable polynomial algebras (PBW-style non-commutative rings whose relatio...
Definition gbring.hpp:671
virtual ~GBRingWeyl()
Definition gbring.cpp:51
GBRingWeyl(const Ring *K0, const Monoid *M0, const WeylAlgebra *R0)
Definition gbring.cpp:192
friend class GBRing
Definition gbring.hpp:598
virtual gbvector * mult_by_term1(const FreeModule *F, const gbvector *f, ring_elem u, const int *monom, int comp)
Definition gbring.cpp:216
GBRing specialisation for Weyl algebras over a field.
Definition gbring.hpp:596
virtual ~GBRingWeylZZ()
Definition gbring.cpp:52
GBRingWeylZZ(const Ring *K0, const Monoid *M0, const WeylAlgebra *R0)
Definition gbring.cpp:199
virtual gbvector * mult_by_term1(const FreeModule *F, const gbvector *f, ring_elem u, const int *monom, int comp)
Definition gbring.cpp:227
GBRingWeyl specialisation for Weyl algebras over ZZ.
Definition gbring.hpp:620
int n_vars() const
Definition monoid.hpp:207
monomial make_one() const
Definition monoid.cpp:455
void from_expvector(const_exponents exp, monomial result) const
Definition monoid.cpp:742
Engine-side commutative monomial monoid: variable names, ordering, multidegree machinery,...
Definition monoid.hpp:89
xxx xxx xxx
Definition ring.hpp:102
int schreyer_compare_encoded(const_monomial m, int m_comp, const_monomial n, int n_comp) const
Definition schorder.cpp:356
int schreyer_compare(const_monomial m, int m_comp, const_monomial n, int n_comp) const
Definition schorder.cpp:337
void schreyer_up(const_monomial m, int comp, monomial result) const
Definition schorder.hpp:107
void schreyer_down(const_monomial m, int comp, monomial result) const
Definition schorder.hpp:113
Per-component tie-breaker data for a Schreyer monomial order on a FreeModule.
Definition schorder.hpp:68
Sign-rule helper used by every ring that has a skew-commutative subset of variables (exterior factor,...
Definition skew.hpp:54
PolyRing subclass for solvable polynomial algebras (PBW-type non-commutative rings where each pair of...
Definition solvable.hpp:57
CoefficientRingZZp * get_CoeffRing() const
Definition ZZp.hpp:93
Engine-side Z/p ring for small primes (p < 32767), using a discrete-log (Zech) representation.
Definition ZZp.hpp:63
char * str()
Definition buffer.hpp:72
void show() const
Definition gbring.cpp:1629
gbvector * heap[GEOHEAP_SIZE]
Definition gbring.hpp:693
gbvector * remove_lead_term()
Definition gbring.cpp:1592
const Ring * K
Definition gbring.hpp:692
gbvector * value()
Definition gbring.cpp:1603
const FreeModule * F
Definition gbring.hpp:691
int top_of_heap
Definition gbring.hpp:695
void add(gbvector *p)
Definition gbring.cpp:1532
gbvector * current_value() const
Definition gbring.cpp:1616
gbvectorHeap(GBRing *GR, const FreeModule *F)
Definition gbring.cpp:1507
const gbvector * get_lead_term()
Definition gbring.cpp:1551
GBRing * GR
Definition gbring.hpp:690
void mult_by_coeff(ring_elem a)
Definition gbring.cpp:1526
Definition mem.hpp:78
Two SimpleARing-style coefficient adapters: CoefficientRingZZp and CoefficientRingR.
void dgbvec(const GBRing *R, gbvector *v)
Definition debug.cpp:95
Debugger-callable d* helpers that pretty-print engine values to stderr.
const int heap_size[GEOHEAP_SIZE]
Definition engine.cpp:53
FreeModule — finite-rank free module R^n, the type-level anchor for every Matrix.
RingZZ * globalZZ
Definition relem.cpp:13
#define sizeofgbvector(s, len)
Definition gbring.cpp:18
static bool isparallel(M2_arrayint w, int *e, int *f)
Definition gbring.cpp:473
int * monomial
Definition gbring.hpp:102
GBRing and gbvector — the GB-tuned polynomial-ring view used by classical Buchberger code.
int p
void freemem(void *s)
Definition m2-mem.cpp:103
void size_t s
Definition m2-mem.cpp:271
VALGRIND_MAKE_MEM_DEFINED & result(result)
int M2_gbTrace
Definition m2-types.cpp:52
mpz_srcptr gmp_ZZ
Definition m2-types.h:141
stash and doubling_stash — legacy size-class allocator interfaces, now stubbed to plain GC allocation...
#define MONOMIAL_BYTE_SIZE(mon_size)
Definition monoid.hpp:66
#define ALLOCATE_EXPONENTS(byte_len)
Definition monoid.hpp:62
#define EXPONENT_BYTE_SIZE(nvars)
Definition monoid.hpp:63
#define ALLOCATE_MONOMIAL(byte_len)
Definition monoid.hpp:65
#define newarray_atomic_clear(T, len)
Definition newdelete.hpp:93
#define newarray(T, len)
Definition newdelete.hpp:82
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
#define ZERO_RINGELEM
Definition ring.hpp:677
Ring — the legacy abstract base class for every coefficient and polynomial ring.
SchreyerOrder — per-basis-element data backing the Schreyer order on a free module.
ring_elem coeff
Definition gbring.hpp:81
gbvector * next
Definition gbring.hpp:80
int monom[1]
Definition gbring.hpp:83
int comp
Definition gbring.hpp:82
const int EQ
Definition style.hpp:40
const int GT
Definition style.hpp:41
#define GEOHEAP_SIZE
Definition style.hpp:46
const int LT
Definition style.hpp:39
void emit_line(const char *s)
Definition text-io.cpp:47
void emit(const char *s)
Definition text-io.cpp:41
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.
mpz_srcptr get_mpz() const
Definition ringelem.hpp:127
int get_int() const
Definition ringelem.hpp:124
WeylAlgebra — ring of polynomial differential operators with [d_i, x_i] = 1.