Macaulay2 Engine
Loading...
Searching...
No Matches
qring.cpp
Go to the documentation of this file.
1// Copyright 2005, Michael E. Stillman
2
3#include "qring.hpp"
4#include "monideal.hpp"
5#include "montable.hpp"
6#include "montableZZ.hpp"
7#include "gbring.hpp"
8#include "poly.hpp"
9
10#include "aring-glue.hpp" // for globalQQ??
11
13{
14 quotient_ideal.push_back(f);
15 quotient_gbvectors.push_back(g);
16}
17
18QRingInfo::QRingInfo(const PolyRing *ambientR) : R(ambientR)
19{
20 exp_size = EXPONENT_BYTE_SIZE(R->n_vars());
21 monom_size = MONOMIAL_BYTE_SIZE(R->getMonoid()->monomial_size());
22}
23
25{
26 // remove the gbvector's as they are stashed in gbrings.
27 // WARNING: these need to be deleted only if the gbring is non-NULL.
28
29 if (GR == nullptr) return;
30 for (int i = 0; i < quotient_gbvectors.size(); i++)
31 GR->gbvector_remove(quotient_gbvectors[i]);
32}
33
36{
37 delete Rideal;
38 delete ringtable;
40}
41
44 const VECTOR(Nterm *) & quotients)
45 : QRingInfo(ambientR)
46// This constructs the quotient ideal, and sets the MonomialIdeal.
47// A subset of 'quotients' must be a minimal GB, and any non-minimal elements
48// should be writable in terms of previous ones.
49// IE, in constructing (R/I)/J, the GB elements of J (mod I), together with the
50// GB elements of I, form a GB, but the GB elements of I might not be minimal.
51// In this case, 'quotients' should be the list of GB elements of J followed by
52// those
53// of I.
54//
55// The ideal may be in a tower of polynomial rings, in which case it needs to be
56// a GB over the flattened ring.
57{
58 Rideal = new MonomialIdeal(R);
59 ringtable = MonomialTable::make(R->n_vars());
61 exponents_t exp = newarray_atomic(int, R->n_vars());
62 for (int i = 0; i < quotients.size(); i++)
63 {
64 // Make a varpower element. See if it is in Rideal.
65 // If not, place it into quotient_elements_.
66
67 Nterm *f = quotients[i];
68 R->getMonoid()->to_expvector(f->monom, exp);
69
70 Bag *not_used;
71
72 if (!Rideal->search_expvector(exp, not_used))
73 {
74 // The element is part of a minimal GB
75 int index = n_quotients();
76 gbvector *g = R->translate_gbvector_from_ringelem(f);
78 R->getMonoid()->to_varpower(f->monom, vp);
79 Bag *b = new Bag(index, vp);
80 Rideal->insert(b);
81 ringtable->insert(exp, 1, index); // consumes exp
82 exp = newarray_atomic(int, R->n_vars());
83 }
84 }
85 freemem(exp);
86}
87
89 const VECTOR(Nterm *) & quotients)
90 : QRingInfo_field(ambientR, quotients)
91{
92}
93
96 const Nterm *g) const
97{
99 const Monoid *M = R->getMonoid();
100 M->divide(f->monom, g->monom, MONOM1);
101 ring_elem c = R->getCoefficients()->negate(f->coeff);
102 if (R->is_skew_commutative())
103 {
106 // We need to determine the sign
107 M->to_expvector(g->monom, EXP2);
108 M->to_expvector(MONOM1, EXP1);
109 if (R->getSkewInfo().mult_sign(EXP1, EXP2) < 0)
110 R->getCoefficients()->negate_to(c);
111 }
112 ring_elem g1 = const_cast<Nterm *>(g);
113 g1 = R->mult_by_term(g1, c, MONOM1);
114 ring_elem f1 = f;
115 R->internal_add_to(f1, g1);
116 f = f1;
117}
118
120// This handles the case of monic GB over a small field
121// It must handle skew multiplication too
122{
124
125 const Monoid *M = R->getMonoid();
126 Nterm head;
127 Nterm *result = &head;
128 Nterm *t = f;
129 while (t != nullptr)
130 {
131 M->to_expvector(t->monom, EXP1);
132 Bag *b;
133 if (Rideal->search_expvector(EXP1, b))
134 {
136 // Now we must replace t with
137 // t + c*m*s, where in(t) = in(c*m*s), and c is 1 or -1.
139 }
140 else
141 {
142 result->next = t;
143 t = t->next;
144 result = result->next;
145 }
146 }
147 result->next = nullptr;
148 f = head.next;
149}
150
152 gbvector *&f) const
153{
155
156 GBRing *GR = R->get_gb_ring();
157 gbvector head;
158 gbvector *result = &head;
159 gbvector *t = f;
160 while (t != nullptr)
161 {
162 GR->gbvector_get_lead_exponents(F, t, EXP1);
163 int x = ringtable->find_divisor(EXP1, 1);
164 if (x >= 0)
165 {
166 const gbvector *r = quotient_gbvector(x);
167 gbvector *zero = nullptr;
168 GR->gbvector_reduce_lead_term(F, F, zero, t, zero, r, zero);
169 }
170 else
171 {
172 result->next = t;
173 t = t->next;
174 result = result->next;
175 }
176 }
177 result->next = nullptr;
178 f = head.next;
179}
180
182 const VECTOR(Nterm *) & quotients)
183 : QRingInfo_field(ambientR, quotients)
184{
185}
186
189{
191 const Monoid *M = R->getMonoid();
192 M->divide(f->monom, g->monom, MONOM1);
193 ring_elem c = globalQQ->RingQQ::negate(f->coeff);
194 c = globalQQ->RingQQ::divide(c, g->coeff);
195 if (R->is_skew_commutative())
196 {
199 // We need to determine the sign
200 M->to_expvector(g->monom, EXP2);
201 M->to_expvector(MONOM1, EXP1);
202 if (R->getSkewInfo().mult_sign(EXP1, EXP2) < 0)
203 globalQQ->RingQQ::negate_to(c);
204 }
205 ring_elem g1 = const_cast<Nterm *>(g);
206 g1 = R->mult_by_term(g1, c, MONOM1);
207 ring_elem f1 = f;
208 R->internal_add_to(f1, g1);
209 f = f1;
210}
211
213// This handles the case of monic GB over a small field
214// It must handle skew multiplication too
215{
217
218 const Monoid *M = R->getMonoid();
219 Nterm head;
220 Nterm *result = &head;
221 Nterm *t = f;
222 while (t != nullptr)
223 {
224 M->to_expvector(t->monom, EXP1);
225 Bag *b;
226 if (Rideal->search_expvector(EXP1, b))
227 {
229 // Now we must replace t with
230 // t + c*m*s, where in(t) = in(c*m*s), and c is 1 or -1.
232 }
233 else
234 {
235 result->next = t;
236 t = t->next;
237 result = result->next;
238 }
239 }
240 result->next = nullptr;
241 f = head.next;
242}
243
245 gbvector *&f) const
246{
248
249 GBRing *GR = R->get_gb_ring();
250 gbvector head;
251 gbvector *result = &head;
252 result->next = nullptr;
253 gbvector *t = f;
254 while (t != nullptr)
255 {
256 GR->gbvector_get_lead_exponents(F, t, EXP1);
257 int x = ringtable->find_divisor(EXP1, 1);
258 if (x >= 0)
259 {
260 const gbvector *r = quotient_gbvector(x);
261 gbvector *zero = nullptr;
262 GR->gbvector_reduce_lead_term(F, F, head.next, t, zero, r, zero);
263 }
264 else
265 {
266 result->next = t;
267 t = t->next;
268 result = result->next;
269 result->next = nullptr;
270 }
271 }
272 f = head.next;
273}
274
276 gbvector *&f,
277 bool use_denom,
278 ring_elem &denom) const
279{
281
282 GBRing *GR = R->get_gb_ring();
283 gbvector head;
284 gbvector *result = &head;
285 result->next = nullptr;
286 gbvector *t = f;
287 while (t != nullptr)
288 {
289 GR->gbvector_get_lead_exponents(F, t, EXP1);
290 int x = ringtable->find_divisor(EXP1, 1);
291 if (x >= 0)
292 {
293 const gbvector *r = quotient_gbvector(x);
294 gbvector *zero = nullptr;
296 F, F, head.next, t, zero, r, zero, use_denom, denom);
297 }
298 else
299 {
300 result->next = t;
301 t = t->next;
302 result = result->next;
303 result->next = nullptr;
304 }
305 }
306 f = head.next;
307}
308
310{
311 delete ringtableZZ;
313}
314
317 const VECTOR(Nterm *) & quotients)
318 : QRingInfo(ambientR)
319{
321 exponents_t exp = newarray_atomic(int, R->n_vars());
322 for (int i = 0; i < quotients.size(); i++)
323 {
324 // Make a varpower element. See if it is in Rideal.
325 // If not, place it into quotient_elements.
326
327 Nterm *f = quotients[i];
328 R->getMonoid()->to_expvector(f->monom, exp);
329
330 if (!ringtableZZ->is_strong_member(f->coeff.get_mpz(), exp, 1))
331 {
332 // The element is part of a minimal GB
333 // Also, this grabs exp.
334 int index = n_quotients();
335 ringtableZZ->insert(f->coeff.get_mpz(), exp, 1, index);
336 gbvector *g = R->translate_gbvector_from_ringelem(f);
338 exp = newarray_atomic(int, R->n_vars());
339
340 if (f->next == nullptr && R->getMonoid()->is_one(f->monom))
341 {
342 is_ZZ_quotient_ = true;
344 }
345 }
346 }
347 freemem(exp);
348}
349
351// Never multiplies f by anything. IE before(f), after(f) are equiv. mod g.
352// this should ONLY be used if K is globalZZ.
353{
354 const Monoid *M = R->getMonoid();
355 const ring_elem a = f->coeff;
356 const ring_elem b = g->coeff;
357 ring_elem u, v, rem;
358 rem = globalZZ->remainderAndQuotient(a, b, v);
359 if (globalZZ->is_zero(v)) return false;
360 v = globalZZ->negate(v);
361 bool result = globalZZ->is_zero(rem);
363 M->divide(f->monom, g->monom, MONOM1);
364 if (R->is_skew_commutative())
365 {
368 // We need to determine the sign
369 M->to_expvector(g->monom, EXP2);
370 M->to_expvector(MONOM1, EXP1);
371 if (R->getSkewInfo().mult_sign(EXP1, EXP2) < 0)
372 R->getCoefficients()->negate_to(v);
373 }
374
375 // now mult g to cancel
376 ring_elem g1 = const_cast<Nterm *>(g);
377 g1 = R->mult_by_term(g1, v, MONOM1);
378 ring_elem f1 = f;
379 R->internal_add_to(f1, g1);
380 f = f1;
381 return result;
382}
383
385// This handles the case of monic GB over a small field
386// It must handle skew multiplication too
387{
389
390 const Monoid *M = R->getMonoid();
391 Nterm head;
392 Nterm *result = &head;
393 Nterm *t = f;
394 while (t != nullptr)
395 {
396 M->to_expvector(t->monom, EXP1);
397 int w = ringtableZZ->find_smallest_coeff_divisor(EXP1, 1);
398 if (w >= 0)
399 {
400 // reduce lead term as much as possible
401 // If the lead monomial reduces away, continue,
402 // else tack the monomial onto the result
403 Nterm *g = quotient_element(w);
404 if (reduce_lead_term_ZZ(t, g)) continue;
405 }
406 result->next = t;
407 t = t->next;
408 result = result->next;
409 }
410 result->next = nullptr;
411 f = head.next;
412}
413
415// This handles the case of monic GB over a small field
416// It must handle skew multiplication too
417{
419
420 GBRing *GR = R->get_gb_ring();
421 gbvector head;
422 gbvector *result = &head;
423 gbvector *t = f;
424 while (t != nullptr)
425 {
426 GR->gbvector_get_lead_exponents(F, t, EXP1);
427 int w = ringtableZZ->find_smallest_coeff_divisor(EXP1, 1);
428 if (w >= 0)
429 {
430 // reduce lead term as much as possible
431 // If the lead monomial reduces away, continue,
432 // else tack the monomial onto the result
433 const gbvector *g = quotient_gbvector(w);
434 gbvector *zero = nullptr;
435 if (GR->gbvector_reduce_lead_term_ZZ(F, F, t, zero, g, zero))
436 continue;
437 }
438 result->next = t;
439 t = t->next;
440 result = result->next;
441 }
442 result->next = nullptr;
443 f = head.next;
444}
445
446// Local Variables:
447// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
448// indent-tabs-mode: nil
449// End:
exponents::Exponents exponents_t
const RingQQ * globalQQ
Definition aring.cpp:24
ConcreteRing<RingType> — the templated bridge between aring and the legacy Ring API.
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
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
void gbvector_get_lead_exponents(const FreeModule *F, const gbvector *f, int *result)
Definition gbring.cpp:541
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
Polynomial-ring view tuned for the inner loop of classical Buchberger Groebner-basis computations.
Definition gbring.hpp:120
void to_expvector(const_monomial m, exponents_t result_exp) const
Definition monoid.cpp:747
void divide(const_monomial m, const_monomial n, monomial result) const
Definition monoid.hpp:331
Engine-side commutative monomial monoid: variable names, ordering, multidegree machinery,...
Definition monoid.hpp:89
Engine-side monomial ideal: a decision tree of Nmi_nodes storing the (typically minimal) generators b...
Definition monideal.hpp:136
static MonomialTable * make(int nvars)
Definition montable.cpp:61
static MonomialTableZZ * make(int nvars)
Concrete PolyRingFlat subclass implementing ordinary commutative polynomial rings K[x_1,...
Definition poly.hpp:64
void normal_form(ring_elem &f) const
Definition qring.cpp:384
void gbvector_normal_form(const FreeModule *F, gbvector *&f) const
Definition qring.cpp:414
bool reduce_lead_term_ZZ(Nterm *&f, const Nterm *g) const
Definition qring.cpp:350
ring_elem ZZ_quotient_value_
Definition qring.hpp:249
bool is_ZZ_quotient_
Definition qring.hpp:246
QRingInfo_ZZ(const PolyRing *ambientR, const VECTOR(Nterm *) &quotients)
Definition qring.cpp:316
MonomialTableZZ * ringtableZZ
Definition qring.hpp:245
void destroy(GBRing *GR)
Definition qring.cpp:309
QRingInfo_field_QQ(const PolyRing *ambientR, const VECTOR(Nterm *) &quotients)
Definition qring.cpp:181
void gbvector_normal_form(const FreeModule *F, gbvector *&f) const
Definition qring.cpp:244
void normal_form(ring_elem &f) const
Definition qring.cpp:212
void reduce_lead_term_QQ(Nterm *&f, const Nterm *g) const
Definition qring.cpp:188
void gbvector_normal_form(const FreeModule *F, gbvector *&f) const
Definition qring.cpp:151
QRingInfo_field_basic(const PolyRing *ambientR, const VECTOR(Nterm *) &quotients)
Definition qring.cpp:88
void normal_form(ring_elem &f) const
Definition qring.cpp:119
void reduce_lead_term_basic_field(Nterm *&f, const Nterm *g) const
Definition qring.cpp:95
void destroy(GBRing *GR)
Definition qring.cpp:35
MonomialTable * ringtable
Definition qring.hpp:154
MonomialIdeal * Rideal
Definition qring.hpp:153
QRingInfo_field(const PolyRing *ambientR, const VECTOR(Nterm *) &quotients)
Definition qring.cpp:43
Nterm * quotient_element(int i) const
Definition qring.hpp:98
int n_quotients() const
Definition qring.hpp:97
QRingInfo()
Definition qring.hpp:93
virtual ~QRingInfo()
Definition qring.cpp:34
const PolyRing * R
Definition qring.hpp:83
virtual void destroy(GBRing *GR)
Definition qring.cpp:24
size_t exp_size
Definition qring.hpp:86
const gbvector * quotient_gbvector(int i) const
Definition qring.hpp:99
size_t monom_size
Definition qring.hpp:87
QRingInfo(const PolyRing *R)
Definition qring.cpp:18
void appendQuotientElement(Nterm *f, gbvector *g)
Definition qring.cpp:12
int basis_elem() const
Definition int-bag.hpp:66
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.
int zero
int_bag Bag
Definition int-bag.hpp:70
void freemem(void *s)
Definition m2-mem.cpp:103
void size_t s
Definition m2-mem.cpp:271
VALGRIND_MAKE_MEM_DEFINED & result(result)
MonomialIdeal — exponent-vector-only representation of an ideal generated by monomials.
#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
MonomialTable — leading-monomial divisor index used by the GB reducer.
MonomialTableZZ — coefficient-aware leading-monomial index for ZZ-coefficient Groebner bases.
typename std::vector< T, gc_allocator< T > > gc_vector
a version of the STL vector, which allocates its backing memory with gc.
Definition newdelete.hpp:76
#define VECTOR(T)
Definition newdelete.hpp:78
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
volatile int x
Concrete commutative PolyRing — standard polynomial ring inheriting from PolyRingFlat.
QRingInfo family — bookkeeping plus normal-form machinery attached to a PolyRingQuotient for R / I re...
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
mpz_srcptr get_mpz() const
Definition ringelem.hpp:127