Macaulay2 Engine
Loading...
Searching...
No Matches
poly.cpp
Go to the documentation of this file.
1// Copyright 1996 Michael E. Stillman
2
3#include <iostream>
4
5#include "ExponentVector.hpp"
6#include "poly.hpp"
7#include "text-io.hpp"
8#include "monoid.hpp"
9#include "ringmap.hpp"
10#include "matrix.hpp"
11#include "ZZ.hpp"
12#include "gbring.hpp"
13#include "frac.hpp"
14#include "geopoly.hpp"
15#include "ZZ.hpp"
16#include "monomial.hpp"
17#include "relem.hpp"
18
19#include "aring-glue.hpp" // for globalQQ
20
21#include "debug.hpp"
22
23#define POLY(q) ((q).poly_val)
24
25PolyRing *PolyRing::trivial_poly_ring = nullptr; // Will be ZZ[]
26
28{
30 delete gb_ring_;
31 gb_ring_ = nullptr;
32}
33
36{
37 if (trivial_poly_ring == nullptr)
38 {
40 }
41
42 return trivial_poly_ring;
43}
44
45// Order of initialization of trivial monoid M, and trivial ring ZZ[].
46//
47// (a) make ZZ ring. Sets degree_ring, D_ to be 0.
48// (b) make trivial monoid M, with M->info->degree_ring = 0.
49// (c) make trivial poly R = ring(ZZ,M).
50// (d) set ZZ's degree ring to be R
51// (e) set M's degree ring to be R
52// (f) set R's degree ring to be R.
53
55{
56 if (trivial_poly_ring != nullptr) return;
57
58 // globalZZ = new RingZZ;
62
64 globalZZ->initialize_ZZ(trivial_poly_ring);
65 trivial_poly_ring->initialize_poly_ring(globalZZ, M, trivial_poly_ring);
66
67 const PolyRing *flatR = trivial_poly_ring;
69 flatR->getCoefficientRing(), flatR->getMonoid());
70}
71
73 const Monoid *M,
74 const PolynomialRing *deg_ring)
75// This version is to be called directly ONLY by initialize_poly_ring
76// and make_trivial_ZZ_poly_ring.
77{
79
80 initialize_PolynomialRing(K, M, this, this, nullptr);
81 poly_size_ = sizeof(Nterm) + sizeof(int) * (M_->monomial_size() - 1);
82
83 gb_ring_ = nullptr;
84
85 // A polynomial ring is ALWAYS graded (if the coeff vars, if any,
86 // all have degree 0, which is the case with our flattened poly rings
87 this->setIsGraded(true);
88
90
91 zeroV = from_long(0);
92 oneV = from_long(1);
94}
95
97{
99}
100
101const PolyRing *PolyRing::create(const Ring *K, const Monoid *M)
102{
103 PolyRing *R = new PolyRing;
104 R->initialize_poly_ring(K, M);
106 return R;
107}
108
109#if 0
110// const PolyRing *PolyRing::create(const Ring *K, const Monoid *M)
111// // Create the ring K[M].
112// // K must be either a basic ring, or an ambient polynomial ring,
113// // possibly non-commutative of some sort.
114// {
115// const PolynomialRing *A = K->cast_to_PolynomialRing();
116// if (A == 0 || K->is_basic_ring())
117// {
118// // K is a basic ring
119// return create_poly_ring(K,M);
120// }
121// const PolyRing *B = A->getAmbientRing();
122// return B->createPolyRing(M);
123// }
124//
125//
126// const PolyRing *PolyRing::createPolyRing(const Monoid *M) const
127// // creates this[M], which is commutative in M variables, but possible skew or Weyl
128// // commutative in (some of) the variables of this
129// {
130// const Monoid *newM = Monoid::tensor_product(M, getMonoid());
131// if (newM == 0) return 0;
132//
133// return create_poly_ring(getCoefficients(),
134// newM,
135// this,
136// M);
137// }
138#endif
139
141{
142 K_->text_out(o);
143 M_->text_out(o);
144}
145
147{
149 result->next = nullptr;
150 result->coeff = 0; // This value is never used, one hopes...
151 // In fact, it gets used in the line below: K->remove(tmp->coeff);
152 // which is called from the line below: remove(idiotic);
153 // and it crashes there, because this assignment only sets the integer
154 // part of the union, so on a machine with 4 byte ints and 8 byte pointers,
155 // the
156 // pointer part is not NULL!
157 result->coeff.poly_val = nullptr; // so I added this line
158 return result;
159}
160
162{
163 Nterm *result = new_term();
164 result->coeff = K_->copy(t->coeff);
165 M_->copy(t->monom, result->monom);
166 return result;
167}
168
170{
171 ring_elem a = K_->from_long(n);
172 if (K_->is_zero(a))
173 {
174 return ZERO_RINGELEM;
175 }
176 Nterm *result = new_term();
177 result->coeff = a;
178 M_->one(result->monom);
179 return result;
180}
181ring_elem PolyRing::from_int(mpz_srcptr n) const
182{
183 ring_elem a = K_->from_int(n);
184 if (K_->is_zero(a))
185 {
186 return ZERO_RINGELEM;
187 }
188 Nterm *result = new_term();
189 result->coeff = a;
190 M_->one(result->monom);
191 return result;
192}
193
194bool PolyRing::from_rational(mpq_srcptr q, ring_elem &result) const
195{
196 ring_elem a;
197 bool ok = K_->from_rational(q, a);
198 if (not ok) return false;
199 if (K_->is_zero(a))
200 {
202 }
203 else
204 {
205 Nterm *resultpoly = new_term();
206 resultpoly->coeff = a;
207 M_->one(resultpoly->monom);
208 result = resultpoly;
209 }
210 return true;
211}
212
214{
215 Nterm *result;
216 if (K_->is_zero(coeff))
217 {
219 return result;
220 }
221 result = new_term();
222 result->coeff = coeff;
223 M_->one(result->monom);
224 return result;
225}
227{
228 ring_elem a;
229 if (!K_->from_BigComplex(z, a))
230 {
232 return false;
233 }
235 return true;
236}
237
239{
240 ring_elem a;
241 if (!K_->from_BigReal(z, a))
242 {
244 return false;
245 }
247 return true;
248}
249
251{
252 ring_elem a;
253 if (!K_->from_Interval(z, a))
254 {
256 return false;
257 }
259 return true;
260}
261
263{
264 ring_elem a;
265 if (!K_->from_ComplexInterval(z, a))
266 {
268 return false;
269 }
271 return true;
272}
273
275{
276 ring_elem a;
277 if (!K_->from_double(z, a))
278 {
280 return false;
281 }
283 return true;
284}
286 double im,
287 ring_elem &result) const
288{
289 ring_elem a;
290 if (!K_->from_complex_double(re, im, a))
291 {
293 return false;
294 }
296 return true;
297}
298
300{
302 for (int i = 0; i < nvars_; i++) EXP1[i] = 0;
303 if (v >= 0 && v < nvars_)
304 EXP1[v] = 1;
305 else
306 {
307 std::cerr << "internal error: PolyRing::var(int v) with v = " << v
308 << " nvars = " << nvars_ << std::endl;
309 std::cerr << "aborting" << std::endl;
310 abort();
311 return ZERO_RINGELEM;
312 }
313 Nterm *result = new_term();
314 result->coeff = K_->from_long(1);
315 M_->from_expvector(EXP1, result->monom);
316 return result;
317}
318
320{
321 Nterm *f = a;
322 if (f == nullptr || f->next != nullptr) return -1;
323 if (!K_->is_equal(f->coeff, K_->from_long(1))) return -1;
324 int result = -1;
326 M_->to_expvector(f->monom, EXP1);
327 for (int i = 0; i < n_vars(); i++)
328 if (EXP1[i] > 1)
329 return -1;
330 else if (EXP1[i] == 1)
331 {
332 if (result >= 0) return -1;
333 result = i;
334 }
335 return result;
336}
337
338// TODO: remove only M2_arrayint in this file
340{
343 for (int i = 0; i < n_vars(); i++) EXP1[i] = 0;
344 for (Nterm& t : f)
345 {
346 M_->to_expvector(t.monom, EXP2);
347 exponents::lcm(n_vars(), EXP1, EXP2, EXP1);
348 }
349 int nelems = 0;
350 for (int i = 0; i < n_vars(); i++)
351 if (EXP1[i] > 0) nelems++;
353 int next = 0;
354 for (int i = 0; i < n_vars(); i++)
355 if (EXP1[i] > 0) result->array[next++] = i;
356 return result;
357}
358
359int check_coeff_ring(const Ring *coeffR, const PolyRing *P)
360// returns the following:
361// if coeffR is K_, then n_vars()
362// if coeffR is a poly ring, then the difference in #vars
363// otherwise returns -1.
364// If a negative number is returned, then an error is set.
365{
366 int nvars = P->n_vars();
367 if (coeffR != P->getCoefficients())
368 {
369 const PolynomialRing *P0 = coeffR->cast_to_PolynomialRing();
370 if (P0 == nullptr)
371 nvars = -1;
372 else
373 nvars -= P0->n_vars();
374 }
375 if (nvars < 0) ERROR("expected coefficient ring");
376 return nvars;
377}
378
379bool PolyRing::promote(const Ring *Rf,
380 const ring_elem f,
381 ring_elem &result) const
382{
383 // case 1: Rf = A[x]/J ---> A[x]/I is one of the 'base_ring's of 'this'.
384 // case 2: Rf = A ---> A[x]/I is the ring of scalars
385
386 // Cases:
387 // Rf is a poly ring (or quotient of one), with the same coeff ring as this.
388 // Rf is a poly ring (or quotient) with the same monoid as this (but coeffs
389 // are maybe different).
390 // Rf is the coeff ring of this
391 // Rf is not the coeff ring K of this, but is a base ring of K (e.g. ZZ -->
392 // QQ, A --> frac(A), any others?)
393 // Rf is a poly ring in a smaller number of variables
394
395 int nvars0 = n_vars();
396 if (Rf != K_)
397 {
398 const PolynomialRing *Rf1 = Rf->cast_to_PolynomialRing();
399 if (Rf1 != nullptr)
400 nvars0 -= Rf1->n_vars();
401 else
402 return false;
403 if (Rf1 && nvars0 == 0)
404 {
405 result = copy(f);
406 return true;
407 }
408 }
409
410 exponents_t exp = newarray_atomic_clear(int, nvars0);
411 result = make_logical_term(Rf, f, exp);
412 return true;
413}
414
415bool PolyRing::lift(const Ring *Rg, const ring_elem f, ring_elem &result) const
416{
417 // case 1: Rf = A[x]/J ---> A[x]/I is one of the 'base_ring's of 'this'.
418 // case 2: Rf = A ---> A[x]/I is the ring of scalars
419
420 // We assume that Rg is one of the coefficient rings of 'this'
421
422 Nterm *t = f;
423 if (t == nullptr)
424 {
425 result = Rg->zero();
426 return true;
427 }
428
429 int nvars0 = n_vars();
430 if (Rg != K_)
431 {
432 const PolynomialRing *Rg1 = Rg->cast_to_PolynomialRing();
433 if (Rg1 != nullptr)
434 nvars0 -= Rg1->n_vars();
435 else
436 return false;
437 }
438
439 exponents_t exp = newarray_atomic(int, nvars0);
440 lead_logical_exponents(nvars0, f, exp);
441 if (!exponents::is_one(nvars0, exp)) return false;
442 if (n_logical_terms(nvars0, f) > 1) return false;
443 result = lead_logical_coeff(Rg, f);
444 return true;
445}
446
448{
449 Nterm *f = ff;
450 if (f == nullptr) return from_long(1);
451 ring_elem c = K_->preferred_associate(f->coeff);
452 Nterm *t = new_term();
453 t->coeff = c;
454 M_->one(t->monom);
455 t->next = nullptr;
456 return t;
457}
458
460// f is an element of 'this'.
461// result is in the coefficient ring
462// If the coefficient ring of this is
463// ZZ -- gcd of all, same sign as lead coeff
464// QQ -- gcd(numerators)/lcm(denominators)
465// basic field -- lead coeff
466// frac(poly ring) -- gcd(numerators)/lcm(denominators)
467// frac(quotient of a poly ring) -- error
468{
469 ring_elem result = getCoefficients()->zero();
471 for (Nterm& t : f)
473 // ie it cannot change, no matter what next coeff is
474 return result;
475 return result;
476}
477
478bool PolyRing::is_unit(const ring_elem f) const
479{
480 Nterm *t = f;
481 if (begin(f) == end(f)) return false;
482 if (t->next == nullptr && M_->is_one(t->monom) && K_->is_unit(t->coeff))
483 return true;
484 return false;
485}
486
487bool PolyRing::is_zero(const ring_elem f) const
488{
489 Nterm *a = f;
490 return a == nullptr;
491}
492
493bool PolyRing::is_equal(const ring_elem f, const ring_elem g) const
494{
495 Nterm *a = f;
496 Nterm *b = g;
497 for (;; a = a->next, b = b->next)
498 {
499 if (a == nullptr)
500 {
501 if (b == nullptr) return true;
502 return false;
503 }
504 if (b == nullptr) return false;
505 if (!K_->is_equal(a->coeff, b->coeff)) return false;
506 if (nvars_ > 0 && (M_->compare(a->monom, b->monom) != 0)) return false;
507 }
508}
509
510int PolyRing::compare_elems(const ring_elem f, const ring_elem g) const
511{
512 int cmp;
513 Nterm *a = f;
514 Nterm *b = g;
515 for (;; a = a->next, b = b->next)
516 {
517 if (a == nullptr)
518 {
519 if (b == nullptr) return 0;
520 return -1;
521 }
522 if (b == nullptr) return 1;
523 if (nvars_ > 0)
524 {
525 cmp = M_->compare(a->monom, b->monom);
526 if (cmp != 0) return cmp;
527 }
528 cmp = K_->compare_elems(a->coeff, b->coeff);
529 if (cmp != 0) return cmp;
530 }
531}
532
534{
535 if (!is_graded()) return false;
536 if (begin(f) == end(f)) return true;
537 auto D = degree_monoid();
538 auto degf = D->make_one();
539 Nterm& t = *begin(f);
540 M_->multi_degree(t.monom, degf);
541 for (Nterm& t : f)
542 {
543 auto e = D->make_one();
544 M_->multi_degree(t.monom, e);
545 if (EQ != D->compare(degf, e))
546 return false;
547 }
548 return true;
549}
550
551// TODO: what's the relationship between PolyRing and PolynomialRing?
552// PolyRing has no M_, but PolynomialRing has no multi_degree implemented
554{
555 auto D = degree_monoid();
556 if (begin(f) == end(f) || M_->n_vars() == 0)
557 {
558 D->one(degf);
559 return true;
560 }
561 bool result = true;
562 Nterm& t = *begin(f);
563 M_->multi_degree(t.monom, degf);
564 for (Nterm& t : f)
565 {
566 auto e = D->make_one();
567 M_->multi_degree(t.monom, e);
568 if (EQ != D->compare(degf, e))
569 {
570 result = false;
571 D->lcm(degf, e, degf);
572 }
573 }
574 // for (int i = 0; i < D->monomial_size(); i++)
575 // std::cout << degf[i] << " , ";
576 // std::cout << std::endl;
577 return result;
578}
579
581 const std::vector<int> &wts,
582 int &lo,
583 int &hi) const
584{
585 Nterm *t = f;
586 if (t == nullptr)
587 {
588 lo = hi = 0;
589 return;
590 }
591 int e = M_->degree_weights(t->monom, wts);
592 lo = hi = e;
593 for (t = t->next; t != nullptr; t = t->next)
594 {
595 e = M_->degree_weights(t->monom, wts);
596 if (e > hi)
597 hi = e;
598 else if (e < lo)
599 lo = e;
600 }
601}
602
604 int v,
605 int d,
606 const std::vector<int> &wts) const
607{
608 // assert(wts[v] != 0);
609 // If an error occurs, then return 0, and set gError.
610
612 Nterm head;
613 Nterm *result = &head;
614 for (Nterm& a : f)
615 {
616 M_->to_expvector(a.monom, exp);
617 auto e = exponents::weight(n_vars(), exp, wts);
618 if (((d - e) % wts[v]) != 0)
619 {
620 // We cannot homogenize, so clean up and exit.
621 result->next = nullptr;
622 ERROR("homogenization impossible");
623 result = nullptr;
624 return result;
625 }
626 exp[v] += (d - e) / wts[v];
627 if (is_skew_ && skew_.is_skew_var(v) && exp[v] > 1) continue;
628 result->next = new_term();
629 result = result->next;
630 result->coeff = K_->copy(a.coeff);
631 M_->from_expvector(exp, result->monom);
632 }
633 result->next = nullptr;
634 sort(head.next); // The monomial order, etc. might all have changed.
635 // Some terms might even drop out
636 freemem(exp);
637 return head.next;
638}
639
641 int v,
642 const std::vector<int> &wts) const
643{
644 Nterm *result = nullptr;
645 if (POLY(f) == nullptr) return result;
646 int lo, hi;
647 degree_weights(f, wts, lo, hi);
648 assert(wts[v] != 0);
649 int d = (wts[v] > 0 ? hi : lo);
650 return homogenize(f, v, d, wts);
651}
652
654{
655 Nterm *a = f;
656 Nterm head;
657 Nterm *result = &head;
658 for (; a != nullptr; a = a->next, result = result->next)
659 result->next = copy_term(a);
660 result->next = nullptr;
661 return head.next;
662}
663
664void PolyRing::remove(ring_elem &f) const { (void) f; }
666{
667 Nterm *v = f;
668 while (v != nullptr)
669 {
670 K_->negate_to(v->coeff);
671 v = v->next;
672 }
673}
674
676{
677 Nterm *f = ff;
678 Nterm *g = gg;
679 gg = ZERO_RINGELEM;
680 if (g == nullptr) return;
681 if (f == nullptr)
682 {
683 ff = g;
684 return;
685 }
686 Nterm head;
687 Nterm *result = &head;
688 while (1) switch (M_->compare(f->monom, g->monom))
689 {
690 case -1:
691 result->next = g;
692 result = result->next;
693 g = g->next;
694 if (g == nullptr)
695 {
696 result->next = f;
697 ff = head.next;
698 return;
699 }
700 break;
701 case 1:
702 result->next = f;
703 result = result->next;
704 f = f->next;
705 if (f == nullptr)
706 {
707 result->next = g;
708 ff = head.next;
709 return;
710 }
711 break;
712 case 0:
713 Nterm *tmf = f;
714 Nterm *tmg = g;
715 f = f->next;
716 g = g->next;
717 K_->add_to(tmf->coeff, tmg->coeff);
718 if (is_ZZ_quotient_)
719 {
720 ring_elem t = globalZZ->remainder(tmf->coeff, ZZ_quotient_value_);
721 tmf->coeff = t;
722 }
723 if (!K_->is_zero(tmf->coeff))
724 {
725 result->next = tmf;
726 result = result->next;
727 }
728 if (g == nullptr)
729 {
730 result->next = f;
731 ff = head.next;
732 return;
733 }
734 if (f == nullptr)
735 {
736 result->next = g;
737 ff = head.next;
738 return;
739 }
740 break;
741 }
742}
743
749
751{
752 Nterm head;
753 Nterm *result = &head;
754 for (Nterm& a : f)
755 {
756 result->next = new_term();
757 result = result->next;
758 result->coeff = K_->negate(a.coeff);
759 M_->copy(a.monom, result->monom);
760 }
761 result->next = nullptr;
762 return head.next;
763}
764
766{
767 ring_elem a = copy(f);
768 ring_elem b = copy(g);
769 internal_add_to(a, b);
770 return a;
771}
772
774{
775 ring_elem a = copy(f);
776 ring_elem b = negate(g);
777 internal_add_to(a, b);
778 return a;
779}
780
782 const ring_elem c,
783 const_monomial m) const
784// return f*c*m
785{
786 Nterm head;
787 Nterm *result = &head;
788 for (Nterm& a : f)
789 {
790 result->next = new_term();
791 result = result->next;
792 result->coeff = K_->mult(a.coeff, c);
793 M_->mult(m, a.monom, result->monom);
794 }
795 result->next = nullptr;
796 return head.next;
797}
798
800{
801 Nterm *t = f;
802 if (t == nullptr) return;
803 for (; t != nullptr; t = t->next)
804 {
805 ring_elem tmp = t->coeff;
806 t->coeff = K_->mult(a, tmp);
807 }
808}
810// f is in this, a is in base coefficient ring
811{
812 Nterm *t = f;
813 if (t == nullptr) return;
814 for (; t != nullptr; t = t->next)
815 {
816 ring_elem tmp = t->coeff;
817 t->coeff = K_->divide(tmp, a);
818 }
819}
820
822{
823 polyheap H(this);
824 for (Nterm& a : f)
825 H.add(mult_by_term(g, a.coeff, a.monom));
826 return H.value();
827}
828
829ring_elem PolyRing::power(const ring_elem f0, mpz_srcptr n) const
830{
831 ring_elem ff, result;
832
833 if (mpz_sgn(n) == 0) return from_long(1);
834 if (is_zero(f0)) return ZERO_RINGELEM;
835
836 mpz_t abs_n;
837 mpz_init(abs_n);
838 mpz_abs(abs_n, n);
839 if (mpz_sgn(n) > 0)
840 ff = f0;
841 else
842 ff = invert(f0);
843
844 Nterm *f = ff;
845
846 // In this case, the computation may only be formed in two
847 // cases: (1) f is a constant, or (2) n is small enough
848 std::pair<bool, int> n1 = RingZZ::get_si(abs_n);
849 if (n1.first)
850 {
851 result = power(f, n1.second);
852 }
853 else if (is_unit(f)) // really want a routine 'is_scalar'...
854 {
855 ring_elem a = K_->power(f->coeff, abs_n);
856 result = make_flat_term(a, f->monom);
857 }
858 else
859 {
860 ERROR("exponent too large");
862 }
863
864 mpz_clear(abs_n);
865 return result;
866}
867
869{
870 ring_elem result, g, rest, h, tmp;
871 ring_elem coef1, coef2, coef3;
872
873 Nterm *lead = ff;
874 if (lead == nullptr) return ZERO_RINGELEM;
875
876 rest = lead->next;
877 g = from_long(1);
878
879 // Start the result with the n th power of the lead term
880 Nterm *t = new_term();
881 t->coeff = K_->power(lead->coeff, n);
882 M_->power(lead->monom, n, t->monom);
883 t->next = nullptr;
884 // if (_base_ring != NULL) normal_form(t); NOT NEEDED
885 result = t;
886
887 if (POLY(rest) == nullptr) return result;
888 monomial m = M_->make_one();
889
890 mpz_t bin_c;
891
892 mpz_init_set_ui(bin_c, 1);
893
894 for (int i = 1; i <= n; i++)
895 {
896 tmp = mult(g, rest);
897 g = tmp;
898
899 mpz_mul_ui(bin_c, bin_c, n - i + 1);
900 mpz_fdiv_q_ui(bin_c, bin_c, i);
901
902 coef1 = K_->from_int(bin_c);
903
904 if (!K_->is_zero(coef1))
905 {
906 coef2 = K_->power(lead->coeff, n - i);
907 coef3 = K_->mult(coef1, coef2);
908 M_->power(lead->monom, n - i, m);
909
910 h = mult_by_term(g, coef3, m);
911 add_to(result, h);
912 }
913 }
914 mpz_clear(bin_c);
915 return result;
916}
917
918ring_elem PolyRing::power(const ring_elem f0, int n) const
919{
920 ring_elem ff;
921
922 if (n > 0)
923 ff = f0;
924 else if (n < 0)
925 {
926 ff = invert(f0);
927 n = -n;
928 }
929 else
930 return from_long(1);
931
932 if(!characteristic())
933 {
934 return power_direct(ff, n);
935 }
936 else
937 {
938 long p=characteristic(), pk=1;
940 ring_elem gg = copy(ff), temp; // no need to copy, just the correct number of terms
941
942 while(n)
943 {
944 for(Nterm *it=ff, *jt=gg; it!=nullptr; it=it->next, jt=jt->next)
945 {
946 jt->coeff = K_->power(it->coeff, pk);
947 M_->power(it->monom, pk, jt->monom);
948 }
949
950 temp = power_direct(gg, n%p);
951 result = mult(result, temp);
952
953 pk *= p;
954 n /= p;
955 }
956
957 return result;
958 }
959}
960
962{
963 Nterm *ft = f;
964 if (is_zero(f))
965 {
966 ERROR("cannot divide by zero");
967 return ZERO_RINGELEM;
968 }
969 if (ft->next == nullptr)
970 {
971 if (M_->is_one(ft->monom))
972 {
973 Nterm *t = new_term();
974 t->coeff = K_->invert(ft->coeff);
975 M_->one(t->monom);
976 return t;
977 }
978 else if (M_->is_invertible(ft->monom))
979 {
980 Nterm *t = new_term();
981 t->coeff = K_->invert(ft->coeff);
982 M_->power(ft->monom, -1, t->monom);
983 return t;
984 }
985 }
986
987 ERROR("element is not invertible in this ring");
988 return ZERO_RINGELEM;
989}
990
992// It returns the remainder on division.
994{
995 ring_elem rem, d;
996 rem = remainderAndQuotient(f, g, d);
997 return d;
998}
999
1001 ring_elem a,
1003 const ring_elem g) const
1004{
1005 ring_elem b = K_->negate(a);
1006 ring_elem h = mult_by_term(g, b, m);
1007 add_to(f, h);
1008}
1009
1011 ring_elem g,
1012 ring_elem &coeff,
1013 monomial monom) const
1014{
1015 bool result;
1016 Nterm *t = f;
1017 Nterm *s = g;
1018 if (t == nullptr || s == nullptr) return true;
1019 if (K_->is_field())
1020 {
1021 coeff = K_->divide(t->coeff, s->coeff);
1022 result = true;
1023 }
1024 else if (K_ == globalZZ)
1025 {
1026 ring_elem r = globalZZ->remainderAndQuotient(t->coeff, s->coeff, coeff);
1027 result =
1028 (globalZZ->is_zero(r)); // true means lead term will be cancelled.
1029 }
1030 else
1031 {
1032 throw exc::internal_error("should not get to this code in imp_attempt_to_cancel_lead_term");
1033 coeff = K_->zero();
1034 result = false;
1035 // What do we do here?? Call divide, and hope for the best?
1036 }
1037 if (!K_->is_zero(coeff))
1038 {
1039 if (is_skew_)
1040 {
1044 M_->to_expvector(t->monom, EXP1);
1045 M_->to_expvector(s->monom, EXP2);
1046 int sign = skew_.divide(EXP1, EXP2, EXP3);
1047 M_->from_expvector(EXP3, monom);
1048 if (sign < 0) K_->negate_to(coeff);
1049 imp_subtract_multiple_to(f, coeff, monom, g);
1050 }
1051 else
1052 {
1053 M_->divide(t->monom, s->monom, monom);
1054 imp_subtract_multiple_to(f, coeff, monom, g);
1055 }
1056 }
1057 return result;
1058}
1059
1061{
1062 if (nvars_ != 1)
1063 {
1064 ERROR("multivariate gcd not yet implemented");
1065 return ZERO_RINGELEM;
1066 }
1067 ring_elem f = copy(ff);
1068 ring_elem g = copy(gg);
1069 ring_elem s, rem;
1070 while (!is_zero(g))
1071 {
1072 rem = remainderAndQuotient(f, g, s);
1073 f = g;
1074 g = rem;
1075 }
1076#if 0
1077// #warning commented out make monic in gcd
1078// make_monic(f);
1079#endif
1080 return f;
1081}
1082
1084 const ring_elem g,
1085 ring_elem &u,
1086 ring_elem &v) const
1087// result == gcd(f,g) = u f + v g
1088{
1089 u = from_long(1);
1090 ring_elem result = copy(f);
1091
1092 if (is_zero(g))
1093 {
1094 v = from_long(0);
1095 return result;
1096 }
1098 ring_elem v3 = copy(g);
1099 ring_elem t1, t3;
1100 ring_elem temp1, temp2, temp3;
1101 while (!is_zero(v3))
1102 {
1103 ring_elem q;
1104 t3 = remainderAndQuotient(result, v3, q);
1105
1106 // The following is: t1 = u - q*v1
1107 temp1 = mult(q, v1);
1108 subtract_to(u, temp1);
1109 t1 = u;
1110
1111 u = v1;
1112 result = v3;
1113 v1 = t1;
1114 v3 = t3;
1115 }
1116
1117 // make 'result' monic. (and divide 'u' by this as well)
1118 if (!is_zero(result))
1119 {
1120 Nterm *t = result;
1121 ring_elem c = K_->invert(t->coeff);
1123 mult_coeff_to(c, u);
1124 }
1125
1126 // The following is v = (result - f*u)/g
1127 temp1 = mult(f, u);
1128 temp2 = subtract(result, temp1);
1129 temp3 = remainderAndQuotient(temp2, g, v);
1130
1131 return result;
1132}
1133
1135{
1136 // Determines the minimal monomial which divides each term of f.
1137 // This monomial is placed into 'monom'.
1138
1139 Nterm *t = f;
1140 if (t == nullptr) return;
1141 M_->copy(t->monom, monom);
1142 for (t = t->next; t != nullptr; t = t->next) M_->gcd(t->monom, monom, monom);
1143}
1144
1146{
1147 ring_elem quot;
1148 ring_elem rem;
1149 if (is_zero(g)) throw exc::internal_error("cannot use division algorithm dividing by zero");
1150 rem = remainderAndQuotient(f, g, quot);
1151 return rem;
1152}
1153
1155{
1156 ring_elem quot;
1157 ring_elem rem;
1158 if (is_zero(g)) throw exc::internal_error("cannot use division algorithm dividing by zero");
1159 rem = remainderAndQuotient(f, g, quot);
1160 return quot;
1161}
1162
1164 const ring_elem g,
1165 ring_elem &quot) const
1166{
1167 if (K_->get_precision() > 0)
1168 {
1169 throw exc::engine_error(
1170 "polynomial division not yet implemented for RR or CC coefficients");
1171 }
1172 Nterm *q, *r;
1173 ring_elem rem;
1174 if (is_zero(f))
1175 {
1176 // In this case both the remainder and quotient are 0.
1177 quot = from_long(0);
1178 return from_long(0);
1179 }
1180 if (is_zero(g))
1181 {
1182 quot = from_long(0);
1183 return copy(f);
1184 }
1185 else
1186 {
1187 bool has_negative_exponent_variables = getMonoid()->numInvertibleVariables() > 0;
1188 bool has_vars_lt_one = getMonoid()->numNonTermOrderVariables() > 0;
1189
1190 if (has_negative_exponent_variables and not has_vars_lt_one)
1191 {
1192 Nterm* f1 = f;
1193 Nterm* g1 = g;
1195 quot = q;
1196 return r;
1197 }
1198 else if (has_vars_lt_one)
1199 {
1200 Nterm *f1 = f;
1201 Nterm *g1 = g;
1202 r = powerseries_division_algorithm(f1, g1, q);
1203 quot = q;
1204 return r;
1205 }
1206 else
1207 {
1208 rem = division_algorithm(f, g, q);
1209 quot = q;
1210 return rem;
1211 }
1212 }
1213 quot = from_long(0);
1214 return from_long(0);
1215}
1216
1218 const ring_elem b,
1219 ring_elem &x,
1220 ring_elem &y) const
1221{
1222 // Do some special cases first. After that: compute a GB
1223
1224 // For the GB, we need to make a 1 by 2 matrix, and compute until one syzygy
1225 // is found.
1226 // create the matrix
1227 // create the gb comp
1228 // compute until one syz is found
1229 // grab the answer from the syz matrix.
1230
1231 // Special situations:
1232 if (PolyRing::is_equal(b, one()))
1233 {
1234 x = PolyRing::copy(b);
1235 y = PolyRing::negate(a);
1236 }
1237 else if (PolyRing::is_equal(b, minus_one()))
1238 {
1239 x = one();
1240 y = PolyRing::copy(a);
1241 }
1242 else
1243 {
1244#if 0
1245// // MES Aug 2002 ifdef'ed because gb_comp is not back yet
1246// intarray syzygy_stop_conditions;
1247// syzygy_stop_conditions.append(0); // ngb
1248// syzygy_stop_conditions.append(1); // nsyz
1249// syzygy_stop_conditions.append(0); // npairs
1250// syzygy_stop_conditions.append(0);
1251// syzygy_stop_conditions.append(0);
1252// syzygy_stop_conditions.append(0); // subring limit
1253// syzygy_stop_conditions.append(0);
1254//
1255// const FreeModule *F = make_FreeModule(1);
1256// Matrix *m = new Matrix(F);
1257// m->append(F->raw_term(a,0));
1258// m->append(F->raw_term(b,0));
1259// #if 0
1260// // buffer o;
1261// // o << "constructing syzygy on ";
1262// // elem_text_out(o,a);
1263// // o << " and ";
1264// // elem_text_out(o,b);
1265// // emit_line(o.str());
1266// // o.reset();
1267// // o << "matrix is" << newline;
1268// // m->text_out(o);
1269// // emit_line(o.str());
1270// // o.reset();
1271// #endif
1272//
1273// gb_comp *g = gb_comp::make(m,true,-1,0);
1274// g->calc(0, syzygy_stop_conditions);
1275// Matrix *s = g->syz_matrix();
1276//
1277// #if 0
1278// // if (s.n_cols() != 1)
1279// // {
1280// // o << "found " << s.n_cols() << " syzygies";
1281// // emit_line(o.str());
1282// // }
1283// #endif
1284// x = s->elem(0,0);
1285// y = s->elem(1,0);
1286// ring_elem c = preferred_associate(x);
1287// ring_elem x1 = mult(c,x);
1288// ring_elem y1 = mult(c,y);
1289// x = x1;
1290// y = y1;
1291// #if 0
1292// // o << "result: x = ";
1293// // elem_text_out(o,x);
1294// // o << " and y = ";
1295// // elem_text_out(o,y);
1296// // emit_line(o.str());
1297// #endif
1298// freemem(g);
1299#endif
1300 }
1301}
1302
1304{
1305 return make_flat_term(K_->random(), M_->make_one());
1306}
1307
1309 const ring_elem f,
1310 bool p_one,
1311 bool p_plus,
1312 bool p_parens) const
1313{
1314 Nterm *t = f;
1315 if (t == nullptr)
1316 {
1317 o << '0';
1318 return;
1319 }
1320
1321 int two_terms = (t->next != nullptr);
1322
1323 int needs_parens = p_parens && two_terms;
1324 if (needs_parens)
1325 {
1326 if (p_plus) o << '+';
1327 o << '(';
1328 p_plus = false;
1329 }
1330
1331 for (t = f; t != nullptr; t = t->next)
1332 {
1333 int isone = M_->is_one(t->monom);
1334 p_parens = !isone;
1335 bool p_one_this = (isone && needs_parens) || (isone && p_one);
1336 K_->elem_text_out(o, t->coeff, p_one_this, p_plus, p_parens);
1337 if (!isone)
1338 {
1339 M_->elem_text_out(o, t->monom, p_one_this);
1340 }
1341 p_plus = true;
1342 }
1343 if (needs_parens) o << ')';
1344}
1345
1347 const ring_elem f,
1348 int first_var) const
1349{
1350 // The way we collect the result depends on whether the target ring
1351 // is a polynomial ring: if so, use a heap structure. If not, just add to the
1352 // result.
1353 gc_vector<int> vp;
1354 const Ring *target = map->get_ring();
1355 SumCollector *H = target->make_SumCollector();
1356
1357 for (Nterm& t : f)
1358 {
1359 M_->to_varpower(t.monom, vp);
1360 H->add(map->eval_term(K_, t.coeff, vp.data(), first_var, n_vars()));
1361 }
1362 ring_elem result = H->getValue();
1363 delete H;
1364 return result;
1365}
1366
1368{
1369 Nterm head;
1370 Nterm *result = &head;
1371 for (Nterm& a : f)
1372 {
1373 ring_elem c = K_->zeroize_tiny(epsilon, a.coeff);
1374 if (!K_->is_zero(c))
1375 {
1376 result->next = new_term();
1377 result = result->next;
1378 result->coeff = c;
1379 M_->copy(a.monom, result->monom);
1380 }
1381 }
1382 result->next = nullptr;
1383 return head.next;
1384}
1386{
1387 for (Nterm& a : f) K_->increase_maxnorm(norm, a.coeff);
1388}
1389
1391// Useful division algorithm routines ///
1393// These are private routines, called from remainder
1394// or remainderAndQuotient or quotient.
1396
1400
1402{
1403 exponents_t exp = new int[n_vars()];
1404 std::vector<int> result(n_vars(), 0);
1405 Nterm* t = f;
1406 getMonoid()->to_expvector(t->monom, exp);
1407 for (int i=0; i<n_vars(); i++)
1408 if (getMonoid()->isLaurentVariable(i))
1409 result[i] = exp[i];
1410
1411 for (t = t->next; t != nullptr; t = t->next)
1412 {
1413 getMonoid()->to_expvector(t->monom, exp);
1414 for (int i=0; i<n_vars(); i++)
1415 if (getMonoid()->isLaurentVariable(i) and exp[i] < result[i])
1416 result[i] = exp[i];
1417 }
1418 delete [] exp;
1419 return result;
1420}
1421
1423{
1424 // Step 1: replace f with f1, m1 (f = m1 * f1, f1 has only exponents >= 0, and no monomial factors)
1425 // Same: g = n1 * g1.
1426 // then if f1 = q * g1 + r, (q, r polynomials with only non-negative exponents)
1427 // then f = (q*m1*n1^(-1)) * g + m1*r
1428 //std::pair<Nterm*, int*> factor_out_inverse_variables(f);
1429 auto expf = setNegativeExponentMonomial(f);
1430 auto expg = setNegativeExponentMonomial(g);
1431 monomial m = getMonoid()->make_one();
1432 monomial n = getMonoid()->make_one();
1433 getMonoid()->from_expvector(expf.data(), m);
1434 getMonoid()->from_expvector(expg.data(), n);
1435
1436 for (auto& a : expf) a = -a;
1437 for (auto& a : expg) a = -a;
1438 monomial minv = getMonoid()->make_one();
1439 monomial ninv = getMonoid()->make_one();
1440 getMonoid()->from_expvector(expf.data(), minv);
1441 getMonoid()->from_expvector(expg.data(), ninv);
1442
1443 for (int i=0; i<n_vars(); ++i)
1444 expf[i] = -expf[i] + expg[i];
1445 monomial mninv = getMonoid()->make_one();
1446 getMonoid()->from_expvector(expf.data(), mninv);
1447
1449 Nterm* f1 = mult_by_term(f, c, minv); // f1 = m^-1 * f, m only involves the variables which allow negative exponents
1450 Nterm* g1 = mult_by_term(g, c, ninv); // g1 = n^-1 * g.
1451 Nterm* quot1 = nullptr;
1452 Nterm* rem1 = division_algorithm(f1, g1, quot1);
1453 Nterm* rem = mult_by_term(rem1, c, m);
1454 quot = mult_by_term(quot1, c, mninv);
1455 return rem;
1456}
1457
1459{
1460 // This returns the remainder, and sets quot to be the quotient.
1461
1462 // This does standard division by one polynomial.
1463 // However, it does work for Weyl algebra, skew commutative algebra,
1464 // This works if the coefficient ring is a field, or ZZ.
1465
1466 ring_elem a = copy(f);
1467 Nterm *t = a;
1468 Nterm *b = g;
1469 Nterm divhead;
1470 Nterm remhead;
1471 Nterm *divt = &divhead;
1472 Nterm *remt = &remhead;
1473 Nterm *nextterm = new_term();
1474
1475 // buffer o;
1476 while (t != nullptr)
1477 if (M_->divides_partial_order(b->monom, t->monom))
1478 {
1479 // o << "t = "; elem_text_out(o,t); o << newline;
1480 a = t;
1481 bool cancelled = imp_attempt_to_cancel_lead_term(
1482 a, g, nextterm->coeff, nextterm->monom);
1483 t = a;
1484 // o << " new t = "; elem_text_out(o,t); o << newline;
1485 // o << " cancelled = " << (cancelled ? "true" : "false") <<
1486 // newline;
1487 // o << " coeff = "; K_->elem_text_out(o,nextterm->coeff); o <<
1488 // newline;
1489 // emit(o.str());
1490 if (!K_->is_zero(nextterm->coeff))
1491 {
1492 divt->next = nextterm;
1493 divt = divt->next;
1494 nextterm = new_term();
1495 }
1496 if (!cancelled)
1497 {
1498 remt->next = t;
1499 remt = remt->next;
1500 t = t->next;
1501 }
1502 }
1503 else
1504 {
1505 remt->next = t;
1506 remt = remt->next;
1507 t = t->next;
1508 }
1509
1510 nextterm = nullptr;
1511 remt->next = nullptr;
1512 divt->next = nullptr;
1513 quot = divhead.next;
1514 return remhead.next;
1515}
1516
1518{
1519 // This does standard division by one polynomial, returning the remainder.
1520 // However, it does work for Weyl algebra, skew commutative algebra,
1521 // as long as the coefficient ring is a field.
1522 ring_elem a = copy(f);
1523 Nterm *t = a;
1524 Nterm *b = g;
1525 Nterm remhead;
1526 Nterm *remt = &remhead;
1527 ring_elem c;
1528 monomial m = M_->make_one();
1529 while (t != nullptr)
1530 if (M_->divides_partial_order(b->monom, t->monom))
1531 {
1532 a = t;
1533 bool cancelled = imp_attempt_to_cancel_lead_term(a, g, c, m);
1534 t = a;
1535 if (!cancelled)
1536 {
1537 remt->next = t;
1538 remt = remt->next;
1539 t = t->next;
1540 }
1541 }
1542 else
1543 {
1544 remt->next = t;
1545 remt = remt->next;
1546 t = t->next;
1547 }
1548
1549 remt->next = nullptr;
1550 return remhead.next;
1551}
1552
1554 Nterm *g,
1555 Nterm *&quot) const
1556{
1557 // This is intended for use when there is one variable, inverses are present,
1558 // and the coefficient ring is a field, or is ZZ.
1559 // The algorithm used is as follows.
1560 // Given a non-zero polynomial f = f(t,t^-1), let v(f) = top - bottom
1561 // where top is the largest exponent in f, and bottom is the smallest.
1562 // So if f is a monomial, v(f) = 0. Also, v(fg) = v(f)+v(g) (at least if
1563 // the
1564 // coefficient ring is a domain), and v(f) >= 0 always.
1565 // The algorithm is as follows:
1566 // Reduce f = f0 by lt(g) to obtain f1, then again to obtain f2, etc.
1567 // So v(f1) >= v(f2) >= ... >= v(fi),
1568 // and either fi = 0, v(fi) < v(g), or v(f(i+1)) > v(fi).
1569 // In this case, the remainder returned is fi.
1570 // (Note: the last case won't happen if the coefficients are a field, or the
1571 // lead coefficient of g is a unit).
1572
1573 // This is intended for use when the monomial order has an initial weight
1574 // vector and the first
1575 // term of the divisor's weight value is strictly greater than the other
1576 // terms.
1577 // AND where (all) inverses are present,
1578 // and the coefficient ring is a field, or is ZZ.
1579 // The algorithm used is as follows.
1580 // Given a non-zero polynomial f = f(t,t^-1), let v(f) = top - bottom
1581 // where top is the weight vec value of the first monomial of f, and bottom
1582 // is the weight vec value
1583 // for the last term of f.
1584 // So if f is a monomial, v(f) = 0. Also, v(fg) = v(f)+v(g) (at least if
1585 // the
1586 // coefficient ring is a domain), and v(f) >= 0 always.
1587 // The algorithm is as follows:
1588 // Reduce f = f0 by lt(g) to obtain f1, then again to obtain f2, etc.
1589 // So v(f1) >= v(f2) >= ... >= v(fi),
1590 // and either fi = 0, v(fi) < v(g), or v(f(i+1)) > v(fi).
1591 // In this case, the remainder returned is fi.
1592 // (Note: the last case won't happen if the coefficients are a field, or the
1593 // lead coefficient of g is a unit).
1594
1595 // This returns the remainder, and sets quot to be the quotient.
1596
1597 ring_elem a = copy(f);
1598 Nterm *t = a;
1599 Nterm *b = g;
1600
1601 if (!M_->weight_value_exists())
1602 {
1603 throw exc::engine_error("no method for division in this ring");
1604 }
1605
1606 Nterm divhead;
1607 Nterm remhead;
1608 Nterm *divt = &divhead;
1609 Nterm *remt = &remhead;
1610 Nterm *nextterm = new_term();
1611 long gval = 0, flast = 0;
1612
1613 if (t != nullptr)
1614 {
1615 Nterm *z = t;
1616 for (; z->next != nullptr; z = z->next)
1617 ;
1618
1619 flast = M_->first_weight_value(z->monom);
1620 }
1621
1622 if (b != nullptr)
1623 {
1624 long gfirst, glast;
1625 Nterm *z = b;
1626
1627 if (z->next == nullptr)
1628 gval = 0;
1629 else
1630 {
1631 gfirst = M_->first_weight_value(z->monom);
1632 long gsecond = M_->first_weight_value(z->next->monom);
1633 if (gfirst == gsecond)
1634 {
1635 // In this case, we return silently
1636 throw exc::internal_error("division algorithm for this element is not implemented");
1637 }
1638 for (; z->next != nullptr; z = z->next)
1639 ;
1640 glast = M_->first_weight_value(z->monom);
1641 gval = gfirst - glast;
1642 }
1643 }
1644
1645 // buffer o;
1646 while (t != nullptr)
1647 {
1648 long ffirst;
1649
1650 ffirst = M_->first_weight_value(t->monom);
1651 long fval = ffirst - flast;
1652
1653 // std::cout << "f: "; dNterm(this, t); std::cout << std::endl;
1654 // std::cout << "g: "; dNterm(this, g); std::cout << std::endl;
1655 if (fval >= gval and M_->divides(g->monom, t->monom))
1656 //if (fval >= gval)
1657 {
1658 // o << "t = "; elem_text_out(o,t); o << newline;
1659 a = t;
1660 bool cancelled = imp_attempt_to_cancel_lead_term(
1661 a, g, nextterm->coeff, nextterm->monom);
1662 t = a;
1663 // o << " new t = "; elem_text_out(o,t); o << newline;
1664 // o << " cancelled = " << (cancelled ? "true" : "false") <<
1665 // newline;
1666 // o << " coeff = "; K_->elem_text_out(o,nextterm->coeff); o <<
1667 // newline;
1668 // emit(o.str());
1669 if (!K_->is_zero(nextterm->coeff))
1670 {
1671 divt->next = nextterm;
1672 divt = divt->next;
1673 nextterm = new_term();
1674 }
1675 if (!cancelled)
1676 {
1677 remt->next = t;
1678 remt = remt->next;
1679 t = t->next;
1680 }
1681 }
1682 else
1683 {
1684 remt->next = t;
1685 remt = remt->next;
1686 t = t->next;
1687 }
1688 }
1689
1690 nextterm = nullptr;
1691 remt->next = nullptr;
1692 divt->next = nullptr;
1693 quot = divhead.next;
1694 return remhead.next;
1695}
1696
1698// Working with logical terms //////
1700
1701ring_elem PolyRing::get_logical_coeff(const Ring *coeffR, const Nterm *&f) const
1702// coeffR needs to be either:
1703// (a) the actual coeff ring K_ of this, or
1704// (b) one of the poly rings used to construct this, in the front end.
1705// This function DOES NOT check this!
1706// Given an Nterm f, return the coeff of its logical monomial, in the
1707// polynomial ring coeffR. f is modified, in that it is replaced by
1708// the pointer to the first term of f not used (possibly 0).
1709// coeffR should be a coefficient ring of 'this'.
1710{
1711 if (f == nullptr) return coeffR->zero();
1712 if (coeffR == K_)
1713 {
1714 ring_elem result = f->coeff;
1715 f = f->next;
1716 return result;
1717 }
1718 const PolynomialRing *KR = coeffR->cast_to_PolynomialRing();
1719 assert(KR);
1720 const PolyRing *K = KR->getNumeratorRing();
1721 Nterm head;
1722 Nterm *inresult = &head;
1723 inresult->next = nullptr;
1724 exponents_t exp = newarray_atomic(int, n_vars());
1725 exponents_t exp2 = newarray_atomic(int, n_vars());
1726 int nvars = n_vars() - K->n_vars();
1727 M_->to_expvector(f->monom, exp);
1728 exponents::copy(n_vars(), exp, exp2);
1729 do
1730 {
1731 Nterm *t = K->new_term();
1732 inresult->next = t;
1733 inresult = t;
1734 t->coeff = f->coeff;
1735 K->getMonoid()->from_expvector(exp2 + nvars, t->monom);
1736
1737 f = f->next;
1738 if (f == nullptr) break;
1739 M_->to_expvector(f->monom, exp2);
1740 }
1741 while (EQ == exponents::lex_compare(nvars, exp, exp2));
1742 inresult->next = nullptr;
1743 return head.next;
1744}
1745
1747 const ring_elem f,
1748 exponents_t result_exp) const
1749{
1750 Nterm *g = f;
1751 assert(g != NULL);
1752 exponents_t exp = newarray_atomic(int, n_vars());
1753 M_->to_expvector(g->monom, exp);
1754 exponents::copy(nvars0, exp, result_exp);
1755}
1756
1758 const ring_elem f) const
1759{
1760 const Nterm *t = f;
1761 return get_logical_coeff(coeffR, t);
1762}
1763
1764int PolyRing::n_logical_terms(int nvars0, const ring_elem f) const
1765{
1766 // nvars0 is the number of variables in the outer monoid
1767 if (nvars0 == n_vars()) return n_terms(f);
1768 Nterm *t = f;
1769 if (t == nullptr) return 0;
1770 exponents_t exp1 = newarray_atomic(int, n_vars());
1771 exponents_t exp2 = newarray_atomic(int, n_vars());
1772 M_->to_expvector(t->monom, exp1);
1773 int result = 1;
1774 for (; t != nullptr; t = t->next)
1775 {
1776 M_->to_expvector(t->monom, exp2);
1777 if (EQ == exponents::lex_compare(nvars0, exp1, exp2)) continue;
1778 // TODO: use std::swap?
1779 exponents_t temp = exp1;
1780 exp1 = exp2;
1781 exp2 = temp;
1782 result++;
1783 }
1784 freemem(exp1);
1785 freemem(exp2);
1786 return result;
1787}
1788
1790 const ring_elem f) const
1791{
1792 // Either coeffR should be the actual coefficient ring (possible a "toField"ed
1793 // ring)
1794 // or a polynomial ring. If not, NULL is returned and an error given
1795 // In the latter case, the last set of variables are part of
1796 // the coefficients.
1797 int nvars0 = check_coeff_ring(coeffR, this);
1798 if (nvars0 < 0) return nullptr;
1799 int n = n_logical_terms(nvars0, f);
1800 engine_RawMonomialArray monoms =
1801 GETMEM(engine_RawMonomialArray, sizeofarray(monoms, n));
1802 engine_RawRingElementArray coeffs =
1803 GETMEM(engine_RawRingElementArray, sizeofarray(coeffs, n));
1804 monoms->len = n;
1805 coeffs->len = n;
1806 engine_RawArrayPair result = newitem(struct engine_RawArrayPair_struct);
1807 result->monoms = monoms;
1808 result->coeffs = coeffs;
1809
1810 exponents_t exp = newarray_atomic(int, n_vars());
1811 gc_vector<int> resultvp;
1812 const Nterm *t = f;
1813 for (int next = 0; next < n; next++)
1814 {
1815 getMonoid()->to_expvector(t->monom, exp);
1816 ring_elem c =
1817 get_logical_coeff(coeffR, t); // increments t to the next term of f.
1818 varpower::from_expvector(nvars0, exp, resultvp);
1819 monoms->array[next] = EngineMonomial::make(resultvp.data());
1820 coeffs->array[next] = RingElement::make_raw(coeffR, c);
1821 resultvp.resize(0);
1822
1823 assert(monoms->array[next] != NULL);
1824 assert(coeffs->array[next] != NULL);
1825 }
1826 freemem(exp);
1827 return result;
1828}
1829
1837
1838ring_elem *PolyRing::get_parts(const std::vector<int> &wts,
1839 const ring_elem f,
1840 long &result_len) const
1841{
1842 // (1) Make a hashtable: keys are weight values, values are indices into an
1843 // array
1844 // (2) Loop over all terms, inserting a copy of each term at the correct
1845 // weight value
1846 // (3) Sort the array, by increasing weight values.
1847 // (4) Make an array, copy the elems to it.
1848
1849 (void) wts;
1850 (void) f;
1851 (void) result_len;
1852 return nullptr;
1853}
1854
1855ring_elem PolyRing::get_part(const std::vector<int> &wts,
1856 const ring_elem f,
1857 bool lobound_given,
1858 bool hibound_given,
1859 long lobound,
1860 long hibound) const
1861{
1862 Nterm head;
1863 Nterm *inresult = &head;
1864
1865 exponents_t exp = newarray_atomic(int, M_->n_vars());
1866
1867 for (Nterm& t : f)
1868 {
1869 M_->to_expvector(t.monom, exp);
1870 long wt = exponents::weight(M_->n_vars(), exp, wts);
1871 if (lobound_given && wt < lobound) continue;
1872 if (hibound_given && wt > hibound) continue;
1873 inresult->next = copy_term(&t);
1874 inresult = inresult->next;
1875 }
1876
1877 inresult->next = nullptr;
1878 freemem(exp);
1879 return head.next;
1880}
1881
1883 const ring_elem a,
1884 const_exponents exp0) const
1885{
1886 const PolynomialRing *logicalK = coeffR->cast_to_PolynomialRing();
1887
1888 int nvars0 = n_vars();
1889 if (K_ == coeffR)
1890 {
1891 monomial m = M_->make_one();
1892 M_->from_expvector(exp0, m);
1893 return make_flat_term(a, m);
1894 }
1895 if (logicalK == nullptr)
1896 {
1897 ERROR("expected actual coefficient ring");
1898 return from_long(0);
1899 }
1900 nvars0 -= logicalK->n_vars();
1901
1902 Nterm head;
1903 Nterm *inresult = &head;
1904 exponents_t exp = newarray_atomic(int, M_->n_vars());
1905 exponents::copy(nvars0, exp0, exp); // Sets the first part of exp
1906 for (Nterm& f : a)
1907 {
1908 Nterm *t = new_term();
1909 inresult->next = t;
1910 inresult = t;
1911 t->coeff = f.coeff;
1912 logicalK->getMonoid()->to_expvector(f.monom, exp + nvars0);
1913 M_->from_expvector(exp, t->monom);
1914 }
1915 inresult->next = nullptr;
1916 return head.next;
1917}
1918
1920 const ring_elem f,
1921 int lo,
1922 int hi) const
1923{
1924 int nterms = n_logical_terms(nvars0, f);
1925 if (lo < 0) lo = nterms + lo;
1926 if (hi < 0) hi = nterms + hi;
1927
1928 Nterm *t = f;
1929 if (t == nullptr) return t;
1930 Nterm head;
1931 Nterm *result = &head;
1932
1933 exponents_t exp1 = newarray_atomic(int, n_vars());
1934 exponents_t exp2 = newarray_atomic(int, n_vars());
1935 M_->to_expvector(t->monom, exp1);
1936 int n = 0;
1937 while (t != nullptr)
1938 {
1939 if (n > hi) break;
1940 if (n >= lo)
1941 {
1942 result->next = copy_term(t);
1943 result = result->next;
1944 }
1945 t = t->next;
1946 if (t == nullptr) break;
1947 M_->to_expvector(t->monom, exp2);
1948 if (EQ == exponents::lex_compare(nvars0, exp1, exp2)) continue;
1949 exponents_t temp = exp1;
1950 exp1 = exp2;
1951 exp2 = temp;
1952 n++;
1953 }
1954 result->next = nullptr;
1955 return head.next;
1956}
1957
1959{
1960 int result = 0;
1961 for ([[maybe_unused]] Nterm& a : f) result++;
1962 return result;
1963}
1964
1966{
1967 if (K_->is_zero(a)) return ZERO_RINGELEM;
1968 Nterm *t = new_term();
1969 t->coeff = K_->copy(a);
1970 M_->copy(m, t->monom);
1971 t->next = nullptr;
1972 return t;
1973}
1974
1976{
1977 Nterm *t = f;
1978 if (t == nullptr) return K_->from_long(0);
1979 return K_->copy(t->coeff);
1980}
1981
1983{
1984 Nterm *t = f;
1985 assert(t != NULL);
1986 return t->monom;
1987}
1988
1990 const ring_elem f,
1991 const_varpower vp) const
1992{
1993 int nvars0 = check_coeff_ring(coeffR, this);
1994 if (nvars0 < 0) return from_long(0);
1995
1996 exponents_t exp = newarray_atomic(int, nvars0);
1997 exponents_t exp2 = newarray_atomic(int, n_vars()); // FLAT number of variables
1998 varpower::to_expvector(nvars0, vp, exp);
1999
2000 // Now loop thru f until exponents match up.
2001 const Nterm *t = f;
2002 for (; t != nullptr; t = t->next)
2003 {
2004 M_->to_expvector(t->monom, exp2);
2005 if (EQ == exponents::lex_compare(nvars0, exp, exp2)) break;
2006 }
2007
2008 ring_elem result = get_logical_coeff(coeffR, t);
2009 freemem(exp2);
2010 freemem(exp);
2011 return result;
2012}
2013
2015{
2016 polyheap H(this);
2017 Nterm *d = new_term();
2018 for (Nterm& s : a)
2019 {
2020 for (Nterm& t : b)
2021 {
2022 d->coeff = diff_term(s.monom, t.monom, d->monom, use_coeff);
2023 if (!K_->is_zero(d->coeff))
2024 {
2025 K_->mult_to(d->coeff, s.coeff);
2026 K_->mult_to(d->coeff, t.coeff);
2027 d->next = nullptr;
2028 H.add(d);
2029 d = new_term();
2030 }
2031 }
2032 }
2033 return H.value();
2034}
2035
2038 monomial resultmon,
2039 int use_coeff) const
2040{
2041 int sign = 0;
2042 if (!M_->divides(m, n)) return K_->from_long(0);
2043 if (is_skew_ && use_coeff)
2044 {
2048 M_->to_expvector(m, EXP1);
2049 M_->to_expvector(n, EXP2);
2050 sign = skew_.diff(EXP1, EXP2, EXP3);
2051 M_->from_expvector(EXP3, resultmon);
2052 }
2053 else
2054 M_->divide(n, m, resultmon);
2055 ring_elem result = K_->from_long(1);
2056 if (!use_coeff) return result;
2057 gc_vector<int> e1(n_vars()), e2(n_vars());
2058 exponents_t exp1 = e1.data();
2059 exponents_t exp2 = e2.data();
2060 M_->to_expvector(m, exp1);
2061 M_->to_expvector(n, exp2);
2062
2063 if (is_skew_ && sign < 0) K_->negate_to(result);
2064
2065 for (int i = 0; i < n_vars(); i++)
2066 {
2067 for (int j = exp1[i] - 1; j >= 0; j--)
2068 {
2069 ring_elem g = K_->from_long(exp2[i] - j);
2070 K_->mult_to(result, g);
2071 if (K_->is_zero(result)) return result;
2072 }
2073 }
2074 return result;
2075}
2076
2077void PolyRing::sort(Nterm *&f) const
2078{
2079 // Divide f into two lists of equal length, sort each,
2080 // then add them together. This allows the same monomial
2081 // to appear more than once in 'f'.
2082
2083 if (f == nullptr || f->next == nullptr) return;
2084 Nterm *f1 = nullptr;
2085 Nterm *f2 = nullptr;
2086 while (f != nullptr)
2087 {
2088 Nterm *t = f;
2089 f = f->next;
2090 t->next = f1;
2091 f1 = t;
2092
2093 if (f == nullptr) break;
2094 t = f;
2095 f = f->next;
2096 t->next = f2;
2097 f2 = t;
2098 }
2099
2100 sort(f1);
2101 sort(f2);
2102 ring_elem g = f1;
2103 ring_elem h = f2;
2104 add_to(g, h);
2105 f = g;
2106}
2107
2108bool PolyRing::in_subring(int nslots, const ring_elem a) const
2109{
2110 for (Nterm& t : a)
2111 if (!M_->in_subring(nslots, t.monom)) return false;
2112 return true;
2113}
2114
2115void PolyRing::degree_of_var(int n, const ring_elem a, int &lo, int &hi) const
2116{
2117 Nterm *t = a;
2118 if (t == nullptr)
2119 {
2120 ERROR("attempting to find degree of a zero element");
2121 return;
2122 }
2123 exponents_t exp = newarray_atomic(int, n_vars());
2124 M_->to_expvector(t->monom, exp);
2125 lo = hi = exp[n];
2126 for (t = t->next; t != nullptr; t = t->next)
2127 {
2128 M_->to_expvector(t->monom, exp);
2129 if (exp[n] < lo)
2130 lo = exp[n];
2131 else if (exp[n] > hi)
2132 hi = exp[n];
2133 }
2134 freemem(exp);
2135}
2136
2138// Replaces the flat exponent vector 'exp' with its gcd with the gcd of all
2139// monomials of 'a'.
2140{
2141 exponents_t exp1 = newarray_atomic(int, n_vars());
2142 for (Nterm& t : a)
2143 {
2144 M_->to_expvector(t.monom, exp1);
2145 exponents::gcd(n_vars(), exp1, exp, exp);
2146 }
2147}
2148
2149ring_elem PolyRing::divide_by_var(int n, int d, const ring_elem a) const
2150// Divide each monomial of 'a' by x^d, where x is the n th variable.
2151// If a monomial is not divisible by x^d, then that monomial is not put
2152// into the result.
2153{
2154 if (d == 0) return a;
2155 Nterm head;
2156 Nterm *result = &head;
2157 exponents_t exp = newarray_atomic(int, n_vars());
2158 for (Nterm& t : a)
2159 {
2160 M_->to_expvector(t.monom, exp);
2161 if (exp[n] >= d)
2162 exp[n] -= d;
2163 else
2164 continue;
2165 result->next = new_term();
2166 result = result->next;
2167 result->coeff = t.coeff;
2168 M_->from_expvector(exp, result->monom);
2169 }
2170 freemem(exp);
2171 result->next = nullptr;
2172 return head.next;
2173}
2174
2176{
2177 Nterm *result = nullptr;
2178 exponents_t exp0 = newarray_atomic(int, n_vars());
2179 for (Nterm& t : a)
2180 {
2181 M_->to_expvector(t.monom, exp0);
2182 exponents::quotient(n_vars(), exp0, exp, exp0);
2183 Nterm *u = new_term();
2184 u->coeff = t.coeff;
2185 M_->from_expvector(exp0, u->monom);
2186 u->next = result;
2187 result = u;
2188 }
2189 freemem(exp0);
2190 sort(result);
2191 return result;
2192}
2193
2195// c is a content elem, g is in ring
2196{
2197 for (Nterm& t : g) K_->lower_content(c, t.coeff);
2198}
2199
2201{
2202 Nterm *t = f;
2203 if (t == nullptr) return K_->zero();
2204 ring_elem c = t->coeff;
2205 for (t = t->next; t != nullptr; t = t->next) K_->lower_content(c, t->coeff);
2206 return c;
2207}
2208
2210{
2211 Nterm *t = f;
2212 if (t == nullptr) return K_->zero();
2213 ring_elem c = t->coeff;
2214 for (t = t->next; t != nullptr; t = t->next) K_->lower_content(c, t->coeff);
2215 for (t = g; t != nullptr; t = t->next) K_->lower_content(c, t->coeff);
2216 return c;
2217}
2218
2220{
2221 Nterm *a = f;
2222 if (a == nullptr) return f;
2223
2224 Nterm head;
2225 Nterm *result = &head;
2226 for (; a != nullptr; a = a->next)
2227 {
2228 result->next = new_term();
2229 result = result->next;
2230 result->coeff = K_->divide(a->coeff, c);
2231 M_->copy(a->monom, result->monom);
2232 }
2233 result->next = nullptr;
2234 return head.next;
2235}
2236
2238// Translation to/from arrays //////
2240const PolyRing * /* or null */ isUnivariateOverPrimeField(const Ring *R)
2241{
2242 const PolyRing *P = R->cast_to_PolyRing();
2243 if (P == nullptr) return nullptr;
2244 if (P->n_vars() != 1) return nullptr;
2245 if (P->characteristic() == 0) return nullptr;
2246 return P;
2247}
2248
2250 const std::vector<long> &coeffs,
2251 int var) const
2252{
2253 // create a poly
2256 n_vars())); // deallocates automatically at end of block
2257 exponents::one(n_vars(), exp);
2258 for (long i = 0; i < coeffs.size(); i++)
2259 {
2260 exp[var] = static_cast<int>(i);
2261 ring_elem c = K_->from_long(coeffs[i]);
2262 if (K_->is_zero(c)) continue;
2263 Nterm *t = new_term();
2264 t->coeff = c;
2265 t->next = nullptr;
2266 M_->from_expvector(exp, t->monom);
2267 H->add(t);
2268 }
2269 ring_elem result = H->getValue();
2270 delete H;
2271 return result;
2272}
2273
2275// vec routines for polynomials ///
2277ring_elem PolyRing::lead_term(int nparts, const ring_elem f) const
2278{
2279 Nterm *lead = f;
2280 Nterm head;
2281 Nterm *result = &head;
2282 int nslots = M_->n_slots(nparts);
2283 for (Nterm& a : f)
2284 {
2285 if (M_->compare(nslots, lead->monom, a.monom) != EQ) break;
2286 result->next = new_term();
2287 result = result->next;
2288 result->coeff = a.coeff;
2289 M_->copy(a.monom, result->monom);
2290 }
2291 result->next = nullptr;
2292 return head.next;
2293}
2294
2296// Returns a pointer to the lead vector of v.
2297// This works if F has a Schreyer order, or an up/down order.
2298{
2299 if (v == nullptr) return v;
2300 const vecterm *lead = v;
2301 const SchreyerOrder *S = F->get_schreyer_order();
2302 if (S)
2303 {
2304 for (vec w = v->next; w != nullptr; w = w->next)
2305 {
2306 if (S->schreyer_compare(POLY(lead->coeff)->monom,
2307 lead->comp,
2308 POLY(w->coeff)->monom,
2309 w->comp) == LT)
2310 {
2311 lead = w;
2312 }
2313 }
2314 }
2315 else
2316 {
2317 for (vec w = v->next; w != nullptr; w = w->next)
2318 {
2319 if (M_->compare(POLY(lead->coeff)->monom,
2320 lead->comp,
2321 POLY(w->coeff)->monom,
2322 w->comp) == LT)
2323 {
2324 lead = w;
2325 }
2326 }
2327 }
2328 return lead;
2329}
2330
2331vec PolyRing::vec_lead_term(int nparts, const FreeModule *F, vec v) const
2332{
2333 // The first step is to find the lead monomial.
2334
2335 if (v == nullptr) return nullptr;
2336 const vecterm *lead = vec_locate_lead_term(F, v);
2337
2338 // Now that we have the lead term, use the first n parts of the monomial
2339 // ordering
2340
2341 ring_elem r = PolyRing::lead_term(nparts, lead->coeff);
2342 return make_vec(lead->comp, r);
2343}
2344
2345vec PolyRing::vec_coefficient_of_var(vec v, int x, int e) const
2346// Find the coefficient of x^e in v.
2347{
2348 exponents_t exp = newarray_atomic(int, n_vars());
2349 vecterm vec_head;
2350 vecterm *vec_result = &vec_head;
2351 for (vecterm *t = v; t != nullptr; t = t->next)
2352 {
2353 Nterm head;
2354 Nterm *result = &head;
2355 for (Nterm& f : t->coeff)
2356 {
2357 M_->to_expvector(f.monom, exp);
2358 if (exp[x] != e) continue;
2359 exp[x] = 0;
2360 result->next = new_term();
2361 result = result->next;
2362 result->coeff = f.coeff;
2363 M_->from_expvector(exp, result->monom);
2364 }
2365 result->next = nullptr;
2366 vec_result->next = make_vec(t->comp, head.next);
2367 vec_result = vec_result->next;
2368 }
2369 freemem(exp);
2370 vec_result->next = nullptr;
2371 return vec_head.next;
2372}
2373
2374vec PolyRing::vec_top_coefficient(const vec v, int &x, int &e) const
2375// find the smallest index variable x which occurs in v, and also find e s.t.
2376// x^e is
2377// the largest power of x occurring in v. Set x and e accordingly.
2378// Return the coefficient of x^e.
2379// IF v has no variables occurring in it, then set x to be #vars, e to be 0 and
2380// return v.
2381// If v is 0, then set x to -1, e to 0, and v to 0.
2382{
2383 x = n_vars();
2384 e = 0;
2385 if (v == nullptr)
2386 {
2387 return nullptr;
2388 }
2389
2390 exponents_t exp = newarray_atomic(int, n_vars());
2391 for (vec t = v; t != nullptr; t = t->next)
2392 for (Nterm& f : t->coeff)
2393 {
2394 M_->to_expvector(f.monom, exp);
2395 for (int i = 0; i < x; i++)
2396 {
2397 if (exp[i] > 0)
2398 {
2399 x = i;
2400 e = exp[i];
2401 break;
2402 }
2403 }
2404 if (x < n_vars() && exp[x] > e) e = exp[x];
2405 }
2406
2407 // Now we have the variable, and its exponent.
2408 freemem(exp);
2409 if (x == n_vars()) return v;
2410 return vec_coefficient_of_var(v, x, e);
2411}
2412
2414// translation gbvector <--> vec //
2416#include "geovec.hpp"
2417
2419 mpz_ptr denom_so_far) const
2420{
2421 // We assume that 'this' is QQ[M].
2422 if (getCoefficients() != globalQQ) return;
2423
2424 for (Nterm& t : f)
2425 {
2426 mpq_srcptr a = MPQ_VAL(t.coeff);
2427 mpz_lcm(denom_so_far, denom_so_far, mpq_denref(a));
2428 }
2429}
2430
2432// returns an element c of getCoefficients(), s.t. f = c*g, and g has:
2433// over QQ: content(g)=1, leadmonomial(g) is positive, g has no denominators in
2434// QQ
2435// over ZZ: c is the content, leadmonomial(g) is positive.
2436// over a basic field: leadmonomial(g) is 1.
2437{
2438 assert(tpoly(f) != 0);
2439 assert(getCoefficients() == globalQQ);
2440
2441 mpz_t denom;
2442 mpz_init_set_si(denom, 1);
2443
2445 ring_elem result = globalZZ->RingZZ::from_int(denom);
2446 mpz_clear(denom);
2447 return result;
2448}
2449
2451// returns an element c of getCoefficients(), s.t. f = c*g, and g has:
2452// over QQ: content(g)=1, leadmonomial(g) is positive, g has no denominators in
2453// QQ
2454// over ZZ: c is the content, leadmonomial(g) is positive.
2455// over a basic field: leadmonomial(g) is 1.
2456{
2457 assert(f != 0);
2458 assert(getCoefficients() == globalQQ);
2459
2460 mpz_t denom;
2461 mpz_init_set_si(denom, 1);
2462
2463 for (vec w = f; w != nullptr; w = w->next)
2464 determine_common_denominator_QQ(w->coeff, denom);
2465 ring_elem result = globalZZ->RingZZ::from_int(denom);
2466 mpz_clear(denom);
2467 return result;
2468}
2469
2471{
2472 // We assume that the ring elements here have no denominators
2473 GBRing *GR = get_gb_ring();
2474 gbvector head;
2475 gbvector *inresult = &head;
2476 for (Nterm& t : coeff)
2477 {
2478 // make a gbvector node.
2479 ring_elem a = globalZZ->RingZZ::from_int(mpq_numref(MPQ_VAL(t.coeff)));
2480 gbvector *g = GR->gbvector_term(nullptr, a, t.monom, 0);
2481 inresult->next = g;
2482 inresult = inresult->next;
2483 }
2484 return head.next;
2485}
2486
2488{
2489 if (getCoefficients() == globalQQ)
2491 GBRing *GR = get_gb_ring();
2492 gbvector head;
2493 gbvector *inresult = &head;
2494 for (Nterm& t : coeff)
2495 {
2496 // make a gbvector node.
2497 gbvector *g = GR->gbvector_term(nullptr, t.coeff, t.monom, 0);
2498 inresult->next = g;
2499 inresult = inresult->next;
2500 }
2501 return head.next;
2502}
2503
2505 const FreeModule *F,
2506 const vec v,
2507 ring_elem &result_denominator) const
2508{
2509 if (v == nullptr)
2510 {
2511 result_denominator = globalZZ->one();
2512 return nullptr;
2513 }
2514 GBRing *GR = get_gb_ring();
2515 result_denominator = vec_get_denominator_QQ(v);
2516 gbvectorHeap H(GR, F);
2517 gbvector head;
2518 gbvector *inresult;
2519 mpz_t a;
2520 mpz_init(a);
2521 for (vec w = v; w != nullptr; w = w->next)
2522 {
2523 inresult = &head;
2524 int comp = w->comp + 1;
2525 for (Nterm& t : w->coeff)
2526 {
2527 // make a gbvector node.
2528 mpq_srcptr b = MPQ_VAL(t.coeff);
2529 mpz_mul(a, result_denominator.get_mpz(), mpq_numref(b));
2530 mpz_divexact(a, a, mpq_denref(b));
2531 gbvector *g = GR->gbvector_term(
2532 F, globalZZ->RingZZ::from_int(a), t.monom, comp);
2533 inresult->next = g;
2534 inresult = inresult->next;
2535 }
2536 H.add(head.next);
2537 }
2538 mpz_clear(a);
2539 return H.value();
2540}
2541
2543 const FreeModule *F,
2544 const vec v,
2545 ring_elem &result_denominator) const
2546{
2547 if (getCoefficients() == globalQQ)
2548 return translate_gbvector_from_vec_QQ(F, v, result_denominator);
2549 result_denominator = getCoefficients()->one();
2550 if (v == nullptr) return nullptr;
2551 GBRing *GR = get_gb_ring();
2552 gbvectorHeap H(GR, F);
2553 gbvector head;
2554 gbvector *inresult;
2555 for (vec w = v; w != nullptr; w = w->next)
2556 {
2557 inresult = &head;
2558 int comp = w->comp + 1;
2559 for (Nterm& t : w->coeff)
2560 {
2561 // make a gbvector node.
2562 gbvector *g = GR->gbvector_term(F, t.coeff, t.monom, comp);
2563 inresult->next = g;
2564 inresult = inresult->next;
2565 }
2566 H.add(head.next);
2567 }
2568
2569 return H.value();
2570}
2571
2572// This next routine was physically lifted from the one right below it, and
2573// only a couple of lines changed. Very poor programming on my part (MES),
2574// and I need to fix that
2575
2577 const gbvector *v,
2578 const ring_elem denom) const
2579{
2580 if (v == nullptr) return nullptr;
2581
2582 GBRing *GR = get_gb_ring();
2583
2584 int firstcomp = v->comp;
2585 int lastcomp = firstcomp;
2586 for (const gbvector *t = v->next; t != nullptr; t = t->next)
2587 {
2588 if (firstcomp > t->comp)
2589 firstcomp = t->comp;
2590 else if (lastcomp < t->comp)
2591 lastcomp = t->comp;
2592 }
2593
2594 Nterm **vec_comps = newarray(Nterm *, lastcomp - firstcomp + 1);
2595 Nterm **vec_last = newarray(Nterm *, lastcomp - firstcomp + 1);
2596 for (int i = 0; i < lastcomp - firstcomp + 1; i++)
2597 {
2598 vec_comps[i] = nullptr;
2599 vec_last[i] = nullptr;
2600 }
2601
2602 // Now make a list of Nterm's, copy gbvectors in (except comps)
2603 for (const gbvector *t = v; t != nullptr; t = t->next)
2604 {
2605 Nterm *s = new_term();
2606 GR->gbvector_get_lead_monomial(F, t, s->monom);
2607 s->coeff = globalQQ->fraction(t->coeff, denom);
2608 s->next = nullptr;
2609 int x = t->comp - firstcomp;
2610 if (!vec_comps[x])
2611 {
2612 vec_comps[x] = s;
2613 vec_last[x] = s;
2614 }
2615 else
2616 {
2617 vec_last[x]->next = s;
2618 vec_last[x] = s;
2619 }
2620 }
2621
2622 // Now create the vecs
2623 vec result = nullptr;
2624 for (int x = 0; x < lastcomp - firstcomp + 1; x++)
2625 if (vec_comps[x])
2626 {
2627 vec w = make_vec(x + firstcomp - 1, vec_comps[x]);
2628 w->next = result;
2629 result = w;
2630 }
2631
2632 // Finally, free vec_last, vec_comps;
2633 freemem(vec_comps);
2634 freemem(vec_last);
2635
2636 return result;
2637}
2638
2640 const gbvector *v) const
2641{
2642 if (v == nullptr) return nullptr;
2643
2644 if (getCoefficients() == globalQQ)
2645 return translate_gbvector_to_vec_QQ(F, v, globalZZ->one());
2646 GBRing *GR = get_gb_ring();
2647
2648 int firstcomp = v->comp;
2649 int lastcomp = firstcomp;
2650 for (const gbvector *t = v->next; t != nullptr; t = t->next)
2651 {
2652 if (firstcomp > t->comp)
2653 firstcomp = t->comp;
2654 else if (lastcomp < t->comp)
2655 lastcomp = t->comp;
2656 }
2657
2658 Nterm **vec_comps = newarray(Nterm *, lastcomp - firstcomp + 1);
2659 Nterm **vec_last = newarray(Nterm *, lastcomp - firstcomp + 1);
2660 for (int i = 0; i < lastcomp - firstcomp + 1; i++)
2661 {
2662 vec_comps[i] = nullptr;
2663 vec_last[i] = nullptr;
2664 }
2665
2666 // Now make a list of Nterm's, copy gbvectors in (except comps)
2667 for (const gbvector *t = v; t != nullptr; t = t->next)
2668 {
2669 Nterm *s = new_term();
2670 GR->gbvector_get_lead_monomial(F, t, s->monom);
2671 s->coeff = t->coeff;
2672 s->next = nullptr;
2673 int x = t->comp - firstcomp;
2674 if (!vec_comps[x])
2675 {
2676 vec_comps[x] = s;
2677 vec_last[x] = s;
2678 }
2679 else
2680 {
2681 vec_last[x]->next = s;
2682 vec_last[x] = s;
2683 }
2684 }
2685
2686 // Now create the vecs
2687 vec result = nullptr;
2688 for (int x = 0; x < lastcomp - firstcomp + 1; x++)
2689 if (vec_comps[x])
2690 {
2691 vec w = make_vec(x + firstcomp - 1, vec_comps[x]);
2692 w->next = result;
2693 result = w;
2694 }
2695
2696 // Finally, free vec_last, vec_comps;
2697 freemem(vec_comps);
2698 freemem(vec_last);
2699
2700 return result;
2701}
2702
2704 const gbvector *v,
2705 const ring_elem denom) const
2706{
2707 if (getCoefficients() == globalQQ)
2708 return translate_gbvector_to_vec_QQ(F, v, denom);
2709 GBRing *GR = get_gb_ring();
2710 const ring_elem c = K_->invert(denom);
2711 gbvector *w = GR->gbvector_mult_by_coeff(v, c);
2713 GR->gbvector_remove(w);
2714 return result;
2715}
2716
2717// Local Variables:
2718// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
2719// indent-tabs-mode: nil
2720// End:
varpower::ConstExponents const_varpower
exponents::ConstExponents const_exponents
exponents::Exponents exponents_t
Dense exponent-vector template [e_0, ..., e_{nvars-1}] for monomial operations.
Legacy RingZZ — a Ring-derived integer ring backed by GMP mpz_t.
const RingQQ * globalQQ
Definition aring.cpp:24
ConcreteRing<RingType> — the templated bridge between aring and the legacy Ring API.
static EngineMonomial * make(int v, int e)
Definition monomial.cpp:26
static void from_expvector(int n, exponents::ConstExponents a, Vector &result)
static void to_expvector(int n, ConstExponents a, exponents::Exponents result)
static Exponent weight(int nvars, ConstExponents a, const std::vector< Exponent > &wts)
static void gcd(int nvars, ConstExponents a, ConstExponents b, Exponents result)
static void one(int nvars, Exponents result)
static bool is_one(int nvars, ConstExponents a)
static void copy(int nvars, ConstExponents a, Exponents result)
static void quotient(int nvars, ConstExponents a, ConstExponents b, Exponents result)
static int lex_compare(int nvars, ConstExponents a, ConstExponents b)
static void lcm(int nvars, ConstExponents a, ConstExponents b, Exponents result)
void gbvector_remove(gbvector *f)
Definition gbring.cpp:288
static GBRing * create_PolynomialRing(const Ring *K, const Monoid *M)
Definition gbring.cpp:93
void gbvector_get_lead_monomial(const FreeModule *F, const gbvector *f, int *result)
Definition gbring.cpp:528
gbvector * gbvector_term(const FreeModule *F, ring_elem coeff, int comp)
Definition gbring.cpp:300
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
int numNonTermOrderVariables() const
Definition monoid.hpp:190
static void set_trivial_monoid_degree_ring(const PolynomialRing *DR)
Definition monoid.cpp:23
void to_expvector(const_monomial m, exponents_t result_exp) const
Definition monoid.cpp:747
const PolynomialRing * get_degree_ring() const
Definition monoid.hpp:174
monomial make_one() const
Definition monoid.cpp:455
const std::vector< int > & get_heft_vector() const
Definition monoid.hpp:179
int numInvertibleVariables() const
Definition monoid.hpp:189
static Monoid * get_trivial_monoid()
Definition monoid.cpp:54
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
friend class FreeModule
Definition poly.hpp:66
virtual bool from_ComplexInterval(gmp_CCi z, ring_elem &result) const
Definition poly.cpp:262
void internal_negate_to(ring_elem &f) const
Definition poly.cpp:665
ring_elem power_direct(const ring_elem f, int n) const
Definition poly.cpp:868
virtual bool is_equal(const ring_elem f, const ring_elem g) const
Definition poly.cpp:493
ring_elem diff_term(const_monomial m, const_monomial n, monomial resultmon, int use_coeff) const
Definition poly.cpp:2036
virtual vec vec_lead_term(int nparts, const FreeModule *F, vec v) const
Definition poly.cpp:2331
virtual void text_out(buffer &o) const
Definition poly.cpp:140
void internal_add_to(ring_elem &f, ring_elem &g) const
Definition poly.cpp:675
static const PolyRing * get_trivial_poly_ring()
Definition poly.cpp:35
virtual void increase_maxnorm(gmp_RRmutable norm, const ring_elem f) const
Definition poly.cpp:1385
virtual void syzygy(const ring_elem a, const ring_elem b, ring_elem &x, ring_elem &y) const
Definition poly.cpp:1217
static const PolyRing * create(const Ring *K, const Monoid *M)
Definition poly.cpp:101
Nterm * copy_term(const Nterm *t) const
Definition poly.cpp:161
virtual void degree_weights(const ring_elem f, const std::vector< int > &wts, int &lo, int &hi) const
Definition poly.cpp:580
virtual vec vec_top_coefficient(const vec v, int &var, int &exp) const
Definition poly.cpp:2374
vec translate_gbvector_to_vec_denom(const FreeModule *F, const gbvector *v, const ring_elem denom) const
Definition poly.cpp:2703
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 poly.cpp:829
virtual void elem_text_out(buffer &o, const ring_elem f, bool p_one=true, bool p_plus=false, bool p_parens=false) const
Definition poly.cpp:1308
void initialize_poly_ring(const Ring *K, const Monoid *M, const PolynomialRing *deg_ring)
Definition poly.cpp:72
virtual ring_elem from_long(long n) const
Definition poly.cpp:169
virtual void divide_coeff_to(ring_elem &f, ring_elem a) const
Definition poly.cpp:809
virtual void clear()
Definition poly.cpp:27
virtual int n_flat_terms(const ring_elem f) const
Definition poly.cpp:1958
ring_elem preferred_associate_divisor(ring_elem ff) const
Definition poly.cpp:459
ring_elem fromCoefficient(ring_elem &coeff) const
Definition poly.cpp:213
std::vector< int > setNegativeExponentMonomial(Nterm *f) const
Create an exponent vector whose i-th value is the minimum of the exponents of that variable,...
Definition poly.cpp:1401
virtual ring_elem mult(const ring_elem f, const ring_elem g) const
Definition poly.cpp:821
virtual void mult_coeff_to(ring_elem a, ring_elem &f) const
Definition poly.cpp:799
virtual bool from_BigComplex(gmp_CC z, ring_elem &result) const
Definition poly.cpp:226
virtual ring_elem content(ring_elem f) const
Definition poly.cpp:2200
virtual ring_elem homogenize(const ring_elem f, int v, int deg, const std::vector< int > &wts) const
Definition poly.cpp:603
virtual ring_elem remainder(const ring_elem f, const ring_elem g) const
Definition poly.cpp:1145
virtual ring_elem var(int v) const
Definition poly.cpp:299
ring_elem get_denominator_QQ(ring_elem f) const
Definition poly.cpp:2431
virtual ring_elem divide_by_expvector(const_exponents exp, const ring_elem a) const
Definition poly.cpp:2175
gbvector * translate_gbvector_from_ringelem_QQ(ring_elem coeff) const
Definition poly.cpp:2470
void imp_subtract_multiple_to(ring_elem &f, ring_elem a, const_monomial m, const ring_elem g) const
Definition poly.cpp:1000
ring_elem vec_get_denominator_QQ(vec f) const
Definition poly.cpp:2450
virtual bool from_complex_double(double re, double im, ring_elem &result) const
Definition poly.cpp:285
virtual ring_elem invert(const ring_elem f) const
Definition poly.cpp:961
virtual bool is_unit(const ring_elem f) const
Definition poly.cpp:478
virtual ring_elem diff(ring_elem a, ring_elem b, int use_coeff) const
Definition poly.cpp:2014
virtual ring_elem eval(const RingMap *map, const ring_elem f, int first_var) const
Definition poly.cpp:1346
virtual ring_elem divide_by_given_content(ring_elem f, ring_elem c) const
Definition poly.cpp:2219
virtual ring_elem zeroize_tiny(gmp_RR epsilon, const ring_elem f) const
Definition poly.cpp:1367
Nterm * division_algorithm_with_laurent_variables(Nterm *f, Nterm *g, Nterm *&quot) const
Definition poly.cpp:1422
virtual bool promote(const Ring *R, const ring_elem f, ring_elem &result) const
Definition poly.cpp:379
virtual bool is_homogeneous(const ring_elem f) const
Definition poly.cpp:533
virtual ring_elem from_int(mpz_srcptr n) const
Definition poly.cpp:181
virtual ring_elem mult_by_term(const ring_elem f, const ring_elem c, const_monomial m) const
Definition poly.cpp:781
virtual int index_of_var(const ring_elem a) const
Definition poly.cpp:319
virtual ring_elem make_flat_term(const ring_elem a, const_monomial m) const
Definition poly.cpp:1965
virtual ~PolyRing()
Definition poly.cpp:34
virtual ring_elem copy(const ring_elem f) const
Definition poly.cpp:653
Nterm * division_algorithm(Nterm *f, Nterm *g, Nterm *&quot) const
Definition poly.cpp:1458
vec translate_gbvector_to_vec(const FreeModule *F, const gbvector *v) const
Definition poly.cpp:2639
virtual void monomial_divisor(const ring_elem a, exponents_t exp) const
Definition poly.cpp:2137
virtual ring_elem remainderAndQuotient(const ring_elem f, const ring_elem g, ring_elem &quot) const
Definition poly.cpp:1163
virtual ring_elem get_part(const std::vector< int > &wts, const ring_elem f, bool lobound_given, bool hibound_given, long lobound, long hibound) const
Definition poly.cpp:1855
virtual ring_elem add(const ring_elem f, const ring_elem g) const
Definition poly.cpp:765
virtual bool from_double(double a, ring_elem &result) const
Definition poly.cpp:274
ring_elem gcd_extended(const ring_elem f, const ring_elem g, ring_elem &u, ring_elem &v) const
Definition poly.cpp:1083
virtual ring_elem * get_parts(const std::vector< int > &wts, const ring_elem f, long &result_len) const
Definition poly.cpp:1838
virtual ring_elem negate(const ring_elem f) const
Definition poly.cpp:750
ring_elem get_logical_coeff(const Ring *coeffR, const Nterm *&f) const
Definition poly.cpp:1701
const vecterm * vec_locate_lead_term(const FreeModule *F, vec v) const
Definition poly.cpp:2295
virtual void remove(ring_elem &f) const
Definition poly.cpp:664
gbvector * translate_gbvector_from_ringelem(ring_elem coeff) const
Definition poly.cpp:2487
virtual int compare_elems(const ring_elem f, const ring_elem g) const
Definition poly.cpp:510
virtual ring_elem make_logical_term(const Ring *coeffR, const ring_elem a, const_exponents exp) const
Definition poly.cpp:1882
gbvector * translate_gbvector_from_vec_QQ(const FreeModule *F, const vec v, ring_elem &result_denominator) const
Definition poly.cpp:2504
virtual ring_elem get_terms(int nvars0, const ring_elem f, int lo, int hi) const
Definition poly.cpp:1919
Nterm * powerseries_division_algorithm(Nterm *f, Nterm *g, Nterm *&quot) const
Definition poly.cpp:1553
virtual ring_elem random() const
Definition poly.cpp:1303
virtual bool from_BigReal(gmp_RR z, ring_elem &result) const
Definition poly.cpp:238
bool imp_attempt_to_cancel_lead_term(ring_elem &f, ring_elem g, ring_elem &coeff, monomial monom) const
Definition poly.cpp:1010
virtual ring_elem preferred_associate(ring_elem f) const
Definition poly.cpp:447
ring_elem gcd(const ring_elem f, const ring_elem g) const
Definition poly.cpp:1060
virtual ring_elem subtract(const ring_elem f, const ring_elem g) const
Definition poly.cpp:773
void minimal_monomial(ring_elem f, monomial &monom) const
Definition poly.cpp:1134
virtual void lead_logical_exponents(int nvars0, const ring_elem f, exponents_t result_exp) const
Definition poly.cpp:1746
virtual bool in_subring(int nslots, const ring_elem a) const
Definition poly.cpp:2108
vec vec_coefficient_of_var(vec v, int var, int exp) const
Definition poly.cpp:2345
virtual void degree_of_var(int n, const ring_elem a, int &lo, int &hi) const
Definition poly.cpp:2115
virtual void lower_content(ring_elem &cont, ring_elem new_coeff) const
Definition poly.cpp:2194
virtual bool multi_degree(const ring_elem f, monomial d) const
Definition poly.cpp:553
static void make_trivial_ZZ_poly_ring()
Definition poly.cpp:54
Nterm * new_term() const
Definition poly.cpp:146
virtual bool from_rational(mpq_srcptr q, ring_elem &result) const
Definition poly.cpp:194
virtual int n_logical_terms(int nvars0, const ring_elem f) const
Definition poly.cpp:1764
ring_elem fromSmallIntegerCoefficients(const std::vector< long > &coeffs, int var) const
Definition poly.cpp:2249
PolyRing()
Definition poly.hpp:82
virtual ring_elem divide(const ring_elem f, const ring_elem g) const
Warning! This function works even if g does not divide f.
Definition poly.cpp:993
virtual bool lift(const Ring *R, const ring_elem f, ring_elem &result) const
Definition poly.cpp:415
virtual bool from_Interval(gmp_RRi z, ring_elem &result) const
Definition poly.cpp:250
ring_elem lead_term(const ring_elem f) const
virtual ring_elem get_coeff(const Ring *coeffR, const ring_elem f, const_varpower vp) const
Definition poly.cpp:1989
vec translate_gbvector_to_vec_QQ(const FreeModule *F, const gbvector *v, const ring_elem denom) const
Definition poly.cpp:2576
virtual engine_RawArrayPairOrNull list_form(const Ring *coeffR, const ring_elem f) const
Definition poly.cpp:1789
virtual bool is_zero(const ring_elem f) const
Definition poly.cpp:487
void determine_common_denominator_QQ(ring_elem f, mpz_ptr denom_so_far) const
Definition poly.cpp:2418
virtual M2_arrayint support(const ring_elem a) const
Definition poly.cpp:339
virtual ring_elem lead_logical_coeff(const Ring *coeffR, const ring_elem f) const
Definition poly.cpp:1757
void sort(Nterm *&f) const
Definition poly.cpp:2077
virtual const_monomial lead_flat_monomial(const ring_elem f) const
Definition poly.cpp:1982
virtual ring_elem quotient(const ring_elem f, const ring_elem g) const
Definition poly.cpp:1154
virtual ring_elem lead_flat_coeff(const ring_elem f) const
Definition poly.cpp:1975
gbvector * translate_gbvector_from_vec(const FreeModule *F, const vec v, ring_elem &result_denominator) const
Definition poly.cpp:2542
static PolyRing * trivial_poly_ring
Definition poly.hpp:83
void internal_subtract_to(ring_elem &f, ring_elem &g) const
Definition poly.cpp:744
virtual ring_elem divide_by_var(int n, int d, const ring_elem a) const
Definition poly.cpp:2149
Concrete PolyRingFlat subclass implementing ordinary commutative polynomial rings K[x_1,...
Definition poly.hpp:64
int n_terms(const ring_elem f) const
Definition polyring.hpp:360
const Ring * getCoefficientRing() const
Definition polyring.hpp:200
virtual GBRing * get_gb_ring() const
Definition polyring.hpp:276
SkewMultiplication skew_
Definition polyring.hpp:104
void initialize_PolynomialRing(const Ring *K, const Monoid *M, const PolyRing *numeratorR, const PolynomialRing *ambientR, const Ring *denomR)
Definition polyring.cpp:29
void setIsGraded(bool new_val)
Definition polyring.hpp:142
const Ring * K_
Definition polyring.hpp:123
ring_elem ZZ_quotient_value_
Definition polyring.hpp:115
virtual const Monoid * getMonoid() const
Definition polyring.hpp:282
size_t poly_size_
Definition polyring.hpp:118
const Monoid * M_
Definition polyring.hpp:124
bool is_graded() const
Definition polyring.hpp:185
SumCollector * make_SumCollector() const
Definition polyring.cpp:209
virtual const Ring * getCoefficients() const
Definition polyring.hpp:277
virtual const PolyRing * getNumeratorRing() const
Definition polyring.hpp:259
virtual void clear()
Definition polyring.hpp:168
GBRing * gb_ring_
Definition polyring.hpp:140
int n_vars() const
Definition polyring.hpp:196
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
void subtract_to(ring_elem &f, const ring_elem &g) const
Definition ring.cpp:206
vec make_vec(int r, ring_elem a) const
Definition ring-vecs.cpp:60
ring_elem one() const
Definition ring.hpp:357
virtual bool has_associate_divisors() const
Definition ring.hpp:228
ring_elem minus_oneV
Definition ring.hpp:131
ring_elem zero() const
Definition ring.hpp:359
void initialize_ring(long charac, const PolynomialRing *DR=nullptr, const std::vector< int > &heft_vec={})
Definition ring.cpp:30
virtual const PolyRing * cast_to_PolyRing() const
Definition ring.hpp:245
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
long characteristic() const
Definition ring.hpp:159
ring_elem oneV
Definition ring.hpp:130
void add_to(ring_elem &f, const ring_elem &g) const
Definition ring.cpp:205
virtual bool lower_associate_divisor(ring_elem &f, ring_elem g) const
Definition ring.cpp:297
const Monoid * degree_monoid() const
Definition ring.cpp:13
ring_elem zeroV
Definition ring.hpp:129
Ring()
Definition ring.hpp:136
virtual SumCollector * make_SumCollector() const
Definition ring.cpp:486
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
xxx xxx xxx
Definition ring.hpp:102
const Ring * get_ring() const
Definition ringmap.hpp:111
ring_elem eval_term(const Ring *coeff_ring, const ring_elem coeff, const int *vp, int first_var, int nvars_in_source) const
Definition ringmap.cpp:140
Engine-side ring homomorphism: stores, for each source-ring variable, the target-ring element it maps...
Definition ringmap.hpp:60
static std::pair< bool, int > get_si(mpz_srcptr n)
Definition ZZ.cpp:46
int schreyer_compare(const_monomial m, int m_comp, const_monomial n, int n_comp) const
Definition schorder.cpp:337
Per-component tie-breaker data for a Schreyer monomial order on a FreeModule.
Definition schorder.hpp:68
virtual ring_elem getValue()=0
virtual void add(ring_elem f)=0
Abstract incremental accumulator that builds a ring_elem from many add(f) calls.
Definition ring.hpp:669
gbvector * value()
Definition gbring.cpp:1603
void add(gbvector *p)
Definition gbring.cpp:1532
void add(Nterm *p)
Definition geopoly.hpp:84
Nterm * value()
Definition geopoly.hpp:155
Debugger-callable d* helpers that pretty-print engine values to stderr.
FractionField — field of fractions of an integral domain, with on-the-fly normalisation.
RingZZ * globalZZ
Definition relem.cpp:13
#define monomial
Definition gb-toric.cpp:11
GBRing and gbvector — the GB-tuned polynomial-ring view used by classical Buchberger code.
polyheap — polynomial-specialised geometric heap for reduction accumulators.
vecHeap — geometric heap specialised for accumulating vec values.
int p
void subtract(int &result, int a, int b)
const int * const_monomial
Definition imonorder.hpp:45
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 sizeofarray(s, len)
Definition m2-mem.h:129
M2_arrayint M2_makearrayint(int n)
Definition m2-types.cpp:6
mpfr_srcptr gmp_RR
Definition m2-types.h:148
struct gmp_CC_struct * gmp_CC
Definition m2-types.h:156
mpfr_ptr gmp_RRmutable
Definition m2-types.h:150
struct engine_RawArrayPair_struct * engine_RawArrayPair
Definition m2-types.h:183
mpfi_srcptr gmp_RRi
Definition m2-types.h:153
engine_RawArrayPair engine_RawArrayPairOrNull
Definition m2-types.h:184
struct gmp_CCi_struct * gmp_CCi
Definition m2-types.h:162
Matrix — the engine's immutable homomorphism F -> G between free modules.
#define ALLOCATE_EXPONENTS(byte_len)
Definition monoid.hpp:62
#define EXPONENT_BYTE_SIZE(nvars)
Definition monoid.hpp:63
Monoid — variable count, naming, grading, and monomial order of a polynomial ring.
EngineMonomial — opaque single-monomial value type used at the engine boundary.
#define newarray_atomic_clear(T, len)
Definition newdelete.hpp:93
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 newitem(T)
Definition newdelete.hpp:86
#define GETMEM(T, size)
#define newarray(T, len)
Definition newdelete.hpp:82
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
volatile int x
int check_coeff_ring(const Ring *coeffR, const PolyRing *P)
Definition poly.cpp:359
const PolyRing * isUnivariateOverPrimeField(const Ring *R)
Definition poly.cpp:2240
#define POLY(q)
Definition poly.cpp:23
Concrete commutative PolyRing — standard polynomial ring inheriting from PolyRingFlat.
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
RingZZ * makeIntegerRing()
Definition ring.cpp:15
#define ZERO_RINGELEM
Definition ring.hpp:677
TermIterator< Nterm > begin(Nterm *ptr)
Definition ringelem.cpp:4
TermIterator< Nterm > end(Nterm *)
Definition ringelem.cpp:5
Nterm * tpoly
Definition ringelem.hpp:80
#define MPQ_VAL(f)
Definition ringelem.hpp:206
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
gbvector * next
Definition gbring.hpp:80
int comp
Definition gbring.hpp:82
Nterm * inresult
Definition poly.cpp:1835
Nterm head
Definition poly.cpp:1834
long wt
Definition poly.cpp:1833
part_elem * next
Definition poly.cpp:1832
ring_elem coeff
Definition ringelem.hpp:172
const int EQ
Definition style.hpp:40
const int LT
Definition style.hpp:39
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.
mpz_srcptr get_mpz() const
Definition ringelem.hpp:127