Macaulay2 Engine
Loading...
Searching...
No Matches
montable.cpp
Go to the documentation of this file.
1#define MOVE_UP_JUST_ONE
2#define INSERT_AT_END
3
4#include <algorithm>
5#include <assert.h>
6#include <functional>
7
8#include "ExponentVector.hpp"
9#include "montable.hpp"
10
11/********************/
12/* Support routines */
13/********************/
14
15static bool exponents_equal(int nvars, exponents_t a, exponents_t b)
16{
17 for (int i = 0; i < nvars; i++)
18 if (a[i] != b[i]) return false;
19 return true;
20}
21
22#ifndef INSERT_AT_END
23static bool exponents_greater(int nvars, exponents_t a, exponents_t b)
24{
25 for (int i = 0; i < nvars; i++)
26 {
27 if (a[i] < b[i]) return false;
28 if (a[i] > b[i]) return true;
29 }
30 return false;
31}
32#endif
33
34static void exponents_show(FILE *fil, exponents_t exp, int nvars)
35/* This is only for debugging */
36{
37 fprintf(fil, "[");
38 for (int i = 0; i < nvars; i++) fprintf(fil, "%d ", exp[i]);
39 fprintf(fil, "]");
40}
41
42/********************/
43/* MonomialTable ****/
44/********************/
45
47{
48 mon_term *t = reinterpret_cast<mon_term *>(mon_term_stash->new_elem());
49 t->_next = t->_prev = t;
50 t->_val = -1;
51 t->_lead = nullptr;
52 return t;
53}
54
60
62{
65 result->mon_term_stash = new stash("montable terms", sizeof(mon_term));
66 result->_nvars = nvars;
67 result->_count = 0;
68 /* The first entry is a dummy entry. Components
69 will always start at 1. */
70 result->_head.push_back(nullptr);
71
72 return result;
73}
74
76{
77 /* Loop through each component, and remove all mon_terms */
78 for (unsigned int i = 1; i < _head.size(); i++)
79 {
80 mon_term *t = _head[i];
81 while (t->_next != t)
82 {
83 mon_term *tmp = t->_next;
84 tmp->_prev->_next = tmp->_next;
85 tmp->_next->_prev = t;
86 mon_term_stash->delete_elem(tmp);
87 }
88 _head[i] = nullptr;
89 }
90 delete mon_term_stash;
91 _count = 0;
92}
93
94void MonomialTable::move_up(mon_term *const y, mon_term *const head)
95{
96 if (head->_next == y) return;
97 mon_term *const x = y->_prev;
98 mon_term *const w = x->_prev;
99 mon_term *const z = y->_next;
100 w->_next = y;
101 z->_prev = x;
102 x->_next = z;
103 x->_prev = y;
104 y->_next = x;
105 y->_prev = w;
106}
107
109{
110 mon_term *const x = y->_prev;
111 mon_term *const z = y->_next;
112 x->_next = z;
113 z->_prev = x;
114}
115
117{
118 mon_term *const x = z->_prev;
119 x->_next = y;
120 y->_next = z;
121 y->_prev = x;
122 z->_prev = y;
123}
124
125#ifdef MOVE_UP_JUST_ONE
126#define MOVE_UP(t, head) move_up(t, head)
127#else
128#define MOVE_UP(t, head) (remove(t), insert_before(t, head->_next))
129#endif
130
132{
133 assert(comp >= 1);
134 if (comp >= static_cast<int>(_head.size())) return -1;
135 if (comp == _last_match_comp && _last_match != nullptr &&
137 return _last_match->_val;
138 unsigned long expmask = ~exponents::mask(_nvars, exp);
139 mon_term *head = _head[comp];
140 for (mon_term *t = head->_next; t != head; t = t->_next)
141 if ((expmask & t->_mask) == 0)
142 if (exponents::divides(_nvars, t->_lead, exp))
143 {
144 _last_match = t;
145 _last_match_comp = comp;
146 // move_up(t,head);
147 return t->_val;
148 }
149 return -1;
150}
151
153 exponents_t exp,
154 int comp,
156{
157 assert(comp >= 1);
158 assert(max != 0);
159 if (comp >= static_cast<int>(_head.size())) return 0;
160 if (max == 1 && comp == _last_match_comp && _last_match != nullptr &&
162 {
163 if (result != nullptr) result->push_back(_last_match);
164 return 1;
165 }
166 mon_term *head = _head[comp];
167 int nmatches = 0;
168 unsigned long expmask = ~exponents::mask(_nvars, exp);
169 //*DEBUG*/ long nviewed = 0;
170 //*DEBUG*/ long nmasked = 0;
171 for (mon_term *t = head->_next, *tnext = t->_next; t != head;
172 t = tnext, tnext = t->_next)
173 if ((expmask & t->_mask) == 0)
174 {
175 //*DEBUG*/ nviewed++;
176 if (exponents::divides(_nvars, t->_lead, exp))
177 {
178 nmatches++; // this doesn't happen very often
179 _last_match = t;
180 _last_match_comp = comp;
181 // move_up(t,head);
182 if (result != nullptr) result->push_back(t);
183 if (max >= 0 && nmatches >= max) break;
184 }
185 }
186 //*DEBUG*/ else
187 //*DEBUG*/ nmasked++;
188 //*DEBUG*/ fprintf(stderr, "nviewed %d nmasked %ld max %d nfound %ld\n",
189 // nviewed, nmasked, max, nmatches);
190 return nmatches;
191}
192
194 int comp) const
195{
196 if (comp >= static_cast<int>(_head.size())) return nullptr;
197 mon_term *head = _head[comp];
198 mon_term *t;
199 int i;
200
201 unsigned long expmask = exponents::mask(_nvars, exp);
202
203 for (t = head->_next; t != head; t = t->_next)
204 if (expmask == t->_mask)
205 {
206 bool is_eq = 1;
207 for (i = 0; i < _nvars; i++)
208 if (exp[i] != t->_lead[i])
209 {
210 is_eq = 0;
211 break;
212 }
213 if (is_eq) return t;
214 }
215 return nullptr;
216}
217
218void MonomialTable::insert(exponents_t exp, int comp, int id)
219{
220 /* Insert 'exp' into the monomial table. These are kept sorted in ascending
221 order
222 in some order (lex order?). No element is ever removed.
223 */
224
225 if (comp >= INTSIZE(_head))
226 {
227 for (int i = INTSIZE(_head); i <= comp; i++)
228 _head.push_back(make_list_head());
229 }
230
231 mon_term *head = _head[comp];
232 mon_term *t;
233
234 /* Make a new mon_term including exp */
235 mon_term *newterm = reinterpret_cast<mon_term *>(mon_term_stash->new_elem());
236 newterm->_lead = exp;
237 newterm->_mask = exponents::mask(_nvars, exp);
238 newterm->_val = id;
239
240 _count++;
241
242/* Find where to put it */
243#ifdef INSERT_AT_END
244 // put it at the end
245 t = head->_prev;
246#else
247 // insert it in sequence (stupid ordering, though)
248 for (t = head; t->_next != head; t = t->_next)
249 {
250 if (exponents_greater(_nvars, newterm->_lead, t->_next->_lead))
251 {
252 /* Time to insert newterm, right between t, t->next */
253 break;
254 }
255 }
256#endif
257
258 /* The actual insertion */
259 newterm->_next = t->_next;
260 newterm->_prev = t;
261 t->_next->_prev = newterm;
262 t->_next = newterm;
263}
264
265/****************************
266 * Minimalization ***********
267 ****************************/
268
269struct sorter
270{
271 int nvars;
272 const VECTOR(exponents_t) & exps;
273 const VECTOR(int) & comps;
274 sorter(int nvars0,
275 const VECTOR(exponents_t) & exps0,
276 const VECTOR(int) & comps0)
277 : nvars(nvars0), exps(exps0), comps(comps0)
278 {
279 }
280 bool operator()(int x, int y)
281 {
282 exponents_t xx = exps[x];
283 exponents_t yy = exps[y];
284 for (int i = 0; i < nvars; i++)
285 if (xx[i] < yy[i])
286 return true;
287 else if (xx[i] > yy[i])
288 return false;
289 if (comps[x] < comps[y])
290 return true;
291 else if (comps[x] > comps[y])
292 return false;
293 return false;
294 }
295};
296
298 const VECTOR(exponents_t) & exps,
299 const VECTOR(int) & comps,
300 bool keep_duplicates,
301 VECTOR(int) & result_positions)
302{
303 /* Step 1: Sort an intarray into ascending order.
304 In this order, if e divides f, then e should appear
305 before f. Don't actually change 'exp'. Need a special compare routine. */
306
307 /* Step 2: Make a monomial table. */
308
309 /* Step 3: Loop through each element in the intarray. If the exponent is not
310 in the
311 monomial ideal, put that index into the result, and insert into the
312 monomial ideal.
313 If it is in the monomial ideal, go on. */
314
315 /* Step alternate3: If ALL minimal elements are to be taken. (e.g. if [1,1,0]
316 is
317 minimal, but occurs more than once, then keep all occurrences of [1,1,0].
318 */
319
320 /* Step 4: Remove the monomial table. Note that the exp vectors should not
321 be recreated. */
322
324
325 VECTOR(int) positions;
326 positions.reserve(exps.size());
327 for (unsigned int i = 0; i < exps.size(); i++) positions.push_back(i);
328
329 /* The following sorts in ascending lex order, considering the component and
330 the
331 inhomogeneous part of the exponent vector */
332 std::stable_sort(
333 positions.begin(), positions.end(), sorter(nvars, exps, comps));
334
335 T = MonomialTable::make(nvars);
336
337 VECTOR(int)::iterator first, end;
338 first = positions.begin();
339 end = positions.end();
340 while (first != end)
341 {
342 VECTOR(int)::iterator next = first + 1;
343 exponents_t this_exp = exps[*first];
344 int comp = comps[*first];
345 while (next != end)
346 {
347 if (!exponents_equal(nvars, this_exp, exps[*next])) break;
348 if (comp != comps[*next]) break;
349 next++;
350 }
351 if (T->find_divisor(this_exp, comp) == -1)
352 {
353 /* We have a minimal element */
354
355 T->insert(this_exp, comp, *first);
356 result_positions.push_back(*first);
357 if (keep_duplicates)
358 while (++first != next) result_positions.push_back(*first);
359 }
360
361 first = next;
362 /* At this point: [first,next) is the range of equal monomials */
363 }
364 freemem(T);
365}
366
368 const VECTOR(exponents_t) & exps,
369 const VECTOR(int) & comps,
370 const VECTOR(int) & vals,
371 VECTOR(int) & rejects)
372{
374
375 VECTOR(int) positions;
376 positions.reserve(exps.size());
377 for (unsigned int i = 0; i < exps.size(); i++) positions.push_back(i);
378
379 /* The following sorts in ascending lex order, considering the component and
380 the
381 inhomogeneous part of the exponent vector */
382 std::stable_sort(
383 positions.begin(), positions.end(), sorter(nvars, exps, comps));
384
385 T = MonomialTable::make(nvars);
386
387 VECTOR(int)::iterator first, end, last_minimal;
388 first = positions.begin();
389 end = positions.end();
390 last_minimal = first;
391 while (first != end)
392 {
393 VECTOR(int)::iterator next = first + 1;
394 exponents_t this_exp = exps[*first];
395 int comp = comps[*first];
396 while (next != end)
397 {
398 if (!exponents_equal(nvars, this_exp, exps[*next])) break;
399 if (comp != comps[*next]) break;
400 rejects.push_back(*next);
401 next++;
402 }
403 if (T->find_divisor(this_exp, comp) == -1)
404 {
405 /* We have a minimal element */
406
407 T->insert(this_exp, comp, vals[*first]);
408 *last_minimal++ = *first;
409 }
410 else
411 rejects.push_back(*first);
412
413 first = next;
414 /* At this point: [first,next) is the range of equal monomials */
415 }
416 return T;
417}
418
419void MonomialTable::show(FILE *fil)
420{
421 mon_term *t, *head;
422 /* Loop through each component, display monomials(val) 10 per line */
423 fprintf(fil,
424 "monomial table: %d vars, %d components, %d elements\n",
425 this->_nvars,
426 static_cast<int>(_head.size()),
427 this->_count);
428 for (unsigned i = 1; i < _head.size(); i++)
429 {
430 head = this->_head[i];
431 if (head->_next == head) continue;
432 fprintf(fil, " -- component %d --\n", i);
433 for (t = head->_next; t != head; t = t->_next)
434 {
435 exponents_show(fil, t->_lead, _nvars);
436 fprintf(fil, " (%d)\n", t->_val);
437 }
438 }
439 fprintf(fil, "\n");
440}
441
442// Local Variables:
443// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
444// indent-tabs-mode: nil
445// End:
ExponentVector< int, true > exponents
exponents::Exponents exponents_t
Dense exponent-vector template [e_0, ..., e_{nvars-1}] for monomial operations.
static bool divides(int nvars, ConstExponents a, ConstExponents b)
static HashExponent mask(int nvars, ConstExponents a)
stash * mon_term_stash
Definition montable.hpp:152
mon_term * make_list_head()
Definition montable.cpp:46
static void insert_before(mon_term *const y, mon_term *const z)
Definition montable.cpp:116
void insert(exponents_t exp, int comp, int id)
Definition montable.cpp:218
static MonomialTable * make_minimal(int nvars, const VECTOR(exponents_t) &exps, const VECTOR(int) &comps, const VECTOR(int) &vals, VECTOR(int) &rejects)
Definition montable.cpp:367
void show(FILE *fil)
Definition montable.cpp:419
static MonomialTable * make(int nvars)
Definition montable.cpp:61
int find_divisor(exponents_t exp, int comp)
Definition montable.cpp:131
static void move_up(mon_term *const y, mon_term *const head)
Definition montable.cpp:94
int find_divisors(int max, exponents_t exp, int comp, VECTOR(mon_term *) *result=nullptr)
Definition montable.cpp:152
mon_term * _last_match
Definition montable.hpp:156
static void minimalize(int nvars, const VECTOR(exponents_t) &exps, const VECTOR(int) &comps, bool keep_duplicates, VECTOR(int) &result_positions)
Definition montable.cpp:297
static void remove(mon_term *const y)
Definition montable.cpp:108
mon_term * find_exact(exponents_t exp, int comp) const
Definition montable.cpp:193
Definition mem.hpp:78
static bool exponents_equal(int nvars, exponents_t a, exponents_t b)
void freemem(void *s)
Definition m2-mem.cpp:103
VALGRIND_MAKE_MEM_DEFINED & result(result)
static bool exponents_equal(int nvars, exponents_t a, exponents_t b)
Definition montable.cpp:15
static void exponents_show(FILE *fil, exponents_t exp, int nvars)
Definition montable.cpp:34
MonomialTable — leading-monomial divisor index used by the GB reducer.
static bool exponents_greater(int nvars, exponents_t a, exponents_t b)
#define VECTOR(T)
Definition newdelete.hpp:78
volatile int x
#define max(a, b)
Definition polyroots.cpp:52
TermIterator< Nterm > end(Nterm *)
Definition ringelem.cpp:5
Doubly-linked-list node of a MonomialTable's per-component monomial list.
Definition montable.hpp:109
bool operator()(int x, int y)
Definition montable.cpp:280
const VECTOR(exponents_t) &exps
const VECTOR(int) &comps
int nvars
Definition montable.cpp:271
sorter(int nvars0, const VECTOR(exponents_t) &exps0, const VECTOR(int) &comps0)
Definition montable.cpp:274
#define INTSIZE(a)
Definition style.hpp:37
#define T
Definition table.c:13