Macaulay2 Engine
Loading...
Searching...
No Matches
dpoly.cpp
Go to the documentation of this file.
1#include "dpoly.hpp"
2
3#include <cassert>
4#include <cctype>
5#include <cstdlib>
6#include <sstream>
7#include <vector>
8
9#include "interface/random.h"
10#include "ZZ.hpp"
11
12#define DEBUGGCDno
13
14long gcd_extended(long a, long b, long &u, long &v)
15{
16 long g;
17 long q;
18 long u1, v1, g1;
19 long utemp, vtemp, gtemp;
20
21 g1 = b;
22 u1 = 0;
23 v1 = 1;
24 g = a;
25 u = 1;
26 v = 0;
27 while (g1 != 0)
28 {
29 q = g / g1;
30 gtemp = g - q * g1;
31 utemp = u - q * u1;
32 vtemp = v - q * v1;
33 g = g1;
34 u = u1;
35 v = v1;
36 g1 = gtemp;
37 u1 = utemp;
38 v1 = vtemp;
39 }
40 return g;
41}
42
43void ZZp_FROM_INT(long charac, long &a, long b)
44{
45 a = b % charac;
46 if (a < 0) a += charac;
47}
48void ZZp_NEGATE(long charac, long &a) { a = charac - a; }
49void ZZp_APXY(long charac, long &a, long b, long c)
50{
51 a = (a + b * c) % charac;
52}
53void ZZp_ADD_TO(long charac, long &a, long b)
54{
55 a += b;
56 if (a >= charac) a -= charac;
57}
58void ZZp_SUBTRACT_TO(long charac, long &a, long b)
59{
60 a -= b;
61 if (a < 0) a += charac;
62}
63void ZZp_MULT(long charac, long &a, long b)
64{
65 a *= b;
66 a %= charac;
67}
68void ZZp_INVERT(long charac, long &result, long b)
69{
70 long u, v;
71 gcd_extended(charac, b, u, v);
72 if (v < 0) v += charac;
73 result = v;
74}
75void ZZp_RANDOM(long charac, long &result)
76{
77 result = rawRandomInt(static_cast<int32_t>(charac));
78}
79
80void DPoly::initialize(long p, int nvars0, const TowerPolynomial* ext0)
81{
82 charac = p;
83 nvars = nvars0;
84 nlevels = nvars0;
85 extensions = newarray(TowerPolynomial, nlevels);
86 if (ext0 == nullptr)
87 for (int i = 0; i < nlevels; i++) extensions[i] = nullptr;
88 else
89 for (int i = 0; i < nlevels; i++)
90 {
91 extensions[i] = copy(nlevels - 1, ext0[i]);
92 down_level(i, nlevels - 1, extensions[i]);
93 }
94}
95DPoly::DPoly(long p, int nvars0, const TowerPolynomial* ext0)
96{
97 initialize(p, nvars0, ext0);
98}
99
101{
102 // if negative, then that variable is transcendental over lower vars
103 if (level < 0 || level >= nlevels) return -1;
104 TowerPolynomial f = extensions[level];
105 if (f == nullptr) return -1;
106 return f->deg;
107}
108
109bool DPoly::down_level(int newlevel, int oldlevel, TowerPolynomial& f)
110{
111 if (f == nullptr) return true;
112 for (int i = oldlevel; i > newlevel; i--)
113 {
114 if (f->deg > 0)
115 {
116 dealloc_poly(f);
117 return false;
118 }
119 TowerPolynomial g = f->arr.polys[0];
120 f->arr.polys[0] = nullptr;
121 dealloc_poly(f);
122 f = g;
123 }
124 return true;
125}
126
127static int n_nonzero_terms(int level, const TowerPolynomial f)
128{
129 if (f == nullptr) return 0;
130 int nterms = 0;
131 if (level == 0)
132 {
133 for (int i = 0; i <= f->deg; i++)
134 if (f->arr.ints[i] != 0) nterms++;
135 }
136 else
137 {
138 for (int i = 0; i <= f->deg; i++)
139 if (f->arr.polys[i] != nullptr) nterms++;
140 }
141 return nterms;
142}
143
145 int level,
146 const TowerPolynomial f,
147 bool p_one,
148 bool p_plus,
149 bool p_parens,
150 M2_ArrayString names) const
151{
152 // o << to_string(level, f);
153 if (f == nullptr)
154 {
155 o << "0";
156 return;
157 }
158
159 int nterms = n_nonzero_terms(level, f);
160 bool needs_parens = p_parens && (nterms >= 2);
161
162 if (needs_parens)
163 {
164 if (p_plus) o << '+';
165 o << '(';
166 p_plus = false;
167 }
168
169 bool one = is_one(level, f);
170
171 if (one)
172 {
173 if (p_plus) o << "+";
174 if (p_one) o << "1";
175 return;
176 }
177
178 M2_string this_varname = names->array[level];
179
180 if (level == 0)
181 {
182 bool firstterm = true;
183 for (int i = f->deg; i >= 0; i--)
184 if (f->arr.ints[i] != 0)
185 {
186 if (!firstterm || p_plus) o << "+";
187 firstterm = false;
188 if (i == 0 || f->arr.ints[i] != 1) o << f->arr.ints[i];
189 if (i > 0) o << this_varname;
190 if (i > 1) o << i;
191 }
192 if (needs_parens) o << ")";
193 }
194 else
195 {
196 bool firstterm = true;
197 for (int i = f->deg; i >= 0; i--)
198 if (f->arr.polys[i] != nullptr)
199 {
200 bool this_p_parens = p_parens || (i > 0);
201
202 if (i == 0 || !is_one(level - 1, f->arr.polys[i]))
204 level - 1,
205 f->arr.polys[i],
206 p_one,
207 p_plus || !firstterm,
208 this_p_parens,
209 names);
210 else if (p_plus || !firstterm)
211 o << "+";
212 if (i > 0) o << this_varname;
213 if (i > 1) o << i;
214
215 firstterm = false;
216 }
217 if (needs_parens) o << ")";
218 }
219}
220
221void DPoly::extensions_text_out(buffer &o, M2_ArrayString names) const
222{
223 for (int i = 0; i < nlevels; i++)
224 {
225 if (extensions[i] != nullptr)
226 {
227 o << newline << " ";
228 elem_text_out(o, i, extensions[i], true, false, false, names);
229 }
230 }
231}
232
233void DPoly::increase_size_0(int newdeg, TowerPolynomial& f)
234{
235 assert(f != 0);
236 if (f->len <= newdeg)
237 {
238 long *newelems = newarray_atomic(long, newdeg + 1);
239 long *fp = f->arr.ints;
240 for (int i = 0; i <= f->deg; i++) newelems[i] = fp[i];
241 for (int i = f->deg + 1; i < newdeg + 1; i++) newelems[i] = 0;
242 freemem(fp);
243 f->arr.ints = newelems;
244 f->len = newdeg + 1;
245 f->deg = newdeg;
246 }
247}
248
249void DPoly::increase_size_n(int newdeg, TowerPolynomial& f)
250{
251 assert(f != 0);
252 if (f->len <= newdeg)
253 {
254 TowerPolynomial *newelems = newarray(TowerPolynomial, newdeg + 1);
255 TowerPolynomial *fp = f->arr.polys;
256 for (int i = 0; i <= f->deg; i++) newelems[i] = fp[i];
257 for (int i = f->deg + 1; i < newdeg + 1; i++) newelems[i] = nullptr;
258 freemem(fp);
259 f->arr.polys = newelems;
260 f->len = newdeg + 1;
261 f->deg = newdeg;
262 }
263}
264
265TowerPolynomial DPoly::alloc_poly_n(int deg, TowerPolynomial *elems)
266// if elems == 0, then set all coeffs to 0.
267{
268 TowerPolynomial result = new TowerPolynomialStruct;
269 result->arr.polys = newarray(TowerPolynomial, deg + 1);
270 result->deg = deg;
271 result->len = deg + 1;
272 if (elems == nullptr)
273 for (int i = 0; i <= deg; i++) result->arr.polys[i] = nullptr;
274 else
275 for (int i = 0; i <= deg; i++) result->arr.polys[i] = elems[i];
276 return result;
277}
278
279TowerPolynomial DPoly::alloc_poly_0(int deg, long *elems)
280{
281 TowerPolynomial result = new TowerPolynomialStruct;
282 result->arr.ints = newarray_atomic(long, deg + 1);
283 result->deg = deg;
284 result->len = deg + 1;
285 if (elems == nullptr)
286 for (int i = 0; i <= deg; i++) result->arr.ints[i] = 0;
287 else
288 for (int i = 0; i <= deg; i++) result->arr.ints[i] = elems[i];
289 return result;
290}
291
292void DPoly::dealloc_poly(TowerPolynomial &f)
293// only f is freed, not any pointers in the array of f
294{
295 if (f == nullptr) return;
296 freemem(f->arr.polys);
297 delete f;
298 f = nullptr;
299}
300
301TowerPolynomial DPoly::read_poly_n(char *&str, int level)
302{
303 int len = 0;
304 TowerPolynomial *elems = newarray(TowerPolynomial, 100);
305 TowerPolynomial this_elem = nullptr;
306 if (*str != '[')
307 {
308 fprintf(stderr, "expected '[', got %s\n", str);
309 exit(1);
310 }
311 str++;
312 // Now loop
313 while (*str != ']')
314 {
315 while (isspace(*str)) str++;
316 if (*str == ',')
317 {
318 str++;
319 }
320 else if (*str == '[')
321 {
322 this_elem = read_poly(str, level - 1); // eats ]
323 while (isspace(*str)) str++;
324 if (*str == ',') str++;
325 }
326 else
327 {
328 fprintf(stderr, "expected , or [, but got %s\n", str);
329 exit(1);
330 }
331 elems[len++] = this_elem;
332 this_elem = nullptr;
333 }
334 // the only way to get here is if *str == ']'. Eat that char.
335 str++;
336 TowerPolynomial result = DPoly::alloc_poly_n(len - 1, elems);
337 freemem(elems);
338 return result;
339}
340
341TowerPolynomial DPoly::read_poly_0(char *&str)
342{
343 int len = 0;
344 long *elems = newarray_atomic(long, 100);
345 long this_elem = 0;
346 if (*str != '[')
347 {
348 fprintf(stderr, "expected '[', got %s\n", str);
349 exit(1);
350 }
351 str++;
352 // Now loop
353 while (*str != ']')
354 {
355 while (isspace(*str)) str++;
356 if (*str == ',')
357 {
358 str++;
359 }
360 else if (isdigit(*str))
361 {
362 char *end;
363 this_elem = strtol(str, &end, 10);
364 str = end;
365 while (isspace(*str)) str++;
366 if (*str == ',') str++;
367 }
368 else
369 {
370 fprintf(stderr, "expected , or [, but got %s\n", str);
371 exit(1);
372 }
373 elems[len++] = this_elem;
374 this_elem = 0;
375 }
376 // the only way to get here is if *str == ']'. Eat that char.
377 str++;
378 TowerPolynomial result = DPoly::alloc_poly_0(len - 1, elems);
379 freemem(elems);
380 return result;
381}
382
383TowerPolynomial DPoly::read_poly(char *&str, int level)
384{
385 if (level > 0) return read_poly_n(str, level);
386 return read_poly_0(str);
387}
388
389std::ostream &DPoly::append_to_stream(std::ostream &o, int level, const TowerPolynomial f)
390{
391 if (f == nullptr)
392 o << "0";
393 else if (level == 0)
394 {
395 long *p = f->arr.ints;
396 o << "[";
397 for (int i = 0; i <= f->deg; i++)
398 {
399 if (i > 0) o << ",";
400 if (p[i] != 0) o << p[i];
401 }
402 o << "]";
403 }
404 else
405 {
406 TowerPolynomial *p = f->arr.polys;
407 o << "[";
408 for (int i = 0; i <= f->deg; i++)
409 {
410 if (i > 0) o << ",";
411 if (p[i] != nullptr) append_to_stream(o, level - 1, p[i]);
412 }
413 o << "]";
414 }
415 return o;
416}
417char *DPoly::to_string(int level, const TowerPolynomial f)
418{
419 std::ostringstream o;
420 append_to_stream(o, level, f);
421 o << '\0';
422 size_t n = o.str().length();
423 char *result = new char[n + 1];
424 memcpy(result, o.str().c_str(), n);
425 return result;
426}
427
428void DPoly::display_poly(FILE *fil, int level, const TowerPolynomial f)
429{
430 if (f == nullptr)
431 fprintf(fil, "0");
432 else if (level == 0)
433 {
434 long *p = f->arr.ints;
435 // fprintf(fil, "[(%ld)", f->deg);
436 fprintf(fil, "[");
437 for (int i = 0; i <= f->deg; i++)
438 {
439 if (i > 0) fprintf(fil, ",");
440 if (p[i] != 0) fprintf(fil, "%ld", p[i]);
441 }
442 fprintf(fil, "]");
443 }
444 else
445 {
446 TowerPolynomial *p = f->arr.polys;
447 // fprintf(fil, "[(%ld)", f->deg);
448 fprintf(fil, "[");
449 for (int i = 0; i <= f->deg; i++)
450 {
451 if (i > 0) fprintf(fil, ",");
452 if (p[i] != nullptr) display_poly(fil, level - 1, p[i]);
453 }
454 fprintf(fil, "]");
455 }
456}
457
458void dpoly(int level, const TowerPolynomial f) { DPoly::display_poly(stdout, level, f); }
459bool DPoly::is_equal(int level, const TowerPolynomial f, const TowerPolynomial g)
460{
461 if (f == nullptr)
462 {
463 if (g == nullptr) return true;
464 return false;
465 }
466 if (g == nullptr || f->deg != g->deg) return false;
467 if (level == 0)
468 {
469 long *fp = f->arr.ints;
470 long *gp = g->arr.ints;
471 for (int i = 0; i <= f->deg; i++)
472 if (fp[i] != gp[i]) return false;
473 return true;
474 }
475 // level > 0
476 TowerPolynomial *fp = f->arr.polys;
477 TowerPolynomial *gp = g->arr.polys;
478 for (int i = 0; i <= f->deg; i++)
479 if (!is_equal(level - 1, fp[i], gp[i])) return false;
480 return true;
481}
482
483TowerPolynomial DPoly::copy(int level, const TowerPolynomial f)
484{
485 if (f == nullptr) return nullptr;
486 TowerPolynomial result;
487 if (level == 0)
488 {
489 result = alloc_poly_0(f->deg);
490 for (int i = 0; i <= f->deg; i++) result->arr.ints[i] = f->arr.ints[i];
491 }
492 else
493 {
494 result = alloc_poly_n(f->deg);
495 for (int i = 0; i <= f->deg; i++)
496 result->arr.polys[i] = copy(level - 1, f->arr.polys[i]);
497 }
498 return result;
499}
500
501TowerPolynomial DPoly::from_long(int level, long c)
502{
503 if (c == 0) return nullptr;
504 TowerPolynomial result = alloc_poly_0(0);
505 result->arr.ints[0] = c;
506 for (int i = 1; i <= level; i++)
507 {
508 TowerPolynomial a = result;
509 result = alloc_poly_n(0);
510 result->arr.polys[0] = a;
511 }
512 return result;
513}
514
515TowerPolynomial DPoly::var(int level, int v)
516// make the variable v (but at level 'level')
517{
518 if (v > level) return nullptr;
519 int which = (v == 0 ? 1 : 0);
520 TowerPolynomial result =
521 alloc_poly_0(which); // TODO: check that this initializes elements to 0
522 result->arr.ints[which] = 1;
523 for (int i = 1; i <= level; i++)
524 {
525 which = (i == v ? 1 : 0);
526 TowerPolynomial a = result;
527 result = alloc_poly_n(which);
528 result->arr.polys[which] = a;
529 }
530 return result;
531}
532
533TowerPolynomial DPoly::random_0(int deg)
534{
535 if (deg < 0) deg = 3; // Take a random element of degree 0.
536 TowerPolynomial f = alloc_poly_0(deg);
537 for (int i = 0; i <= deg; i++) ZZp_RANDOM(charac, f->arr.ints[i]);
538 reset_degree_0(f); // possibly modifies f, if it is zero.
539 return f;
540}
541TowerPolynomial DPoly::random_n(int level, int deg)
542{
543 if (deg < 0) deg = 3; // Take a random element of degree 0.
544 TowerPolynomial f = alloc_poly_n(deg);
545 for (int i = 0; i <= deg; i++) f->arr.polys[i] = random(level - 1);
546 reset_degree_n(level, f); // possibly modifies f, if it is zero.
547 return f;
548}
549TowerPolynomial DPoly::random(int level, int deg)
550{
551 if (deg < 0) deg = 0; // Take a random element of degree 0.
552 if (level == 0) return random_0(deg);
553 return random_n(level, deg);
554}
555TowerPolynomial DPoly::random(int level)
556{
557 return random(level, degree_of_extension(level));
558}
559
560int DPoly::compare(int level, TowerPolynomial f, TowerPolynomial g)
561// returns -1 if f < g, 0 if f == g, and 1 if f > g
562// order used: first degree, then compare elements 0..charac-1
563// 0 is the lowest
564{
565 if (f == nullptr)
566 {
567 if (g == nullptr) return 0;
568 return 1;
569 }
570 if (g == nullptr) return -1;
571 if (f->deg > g->deg) return -1;
572 if (f->deg < g->deg) return 1;
573
574 if (level == 0)
575 {
576 for (int i = f->deg; i >= 0; i--)
577 {
578 long cmp = f->arr.ints[i] - g->arr.ints[i];
579 if (cmp > 0) return -1;
580 if (cmp < 0) return 1;
581 }
582 }
583 else
584 {
585 for (int i = f->deg; i >= 0; i--)
586 {
587 int cmp = compare(level - 1, f->arr.polys[i], g->arr.polys[i]);
588 if (cmp > 0) return -1;
589 if (cmp < 0) return 1;
590 }
591 }
592 return 0;
593}
594
595bool DPoly::is_one(int level, TowerPolynomial f)
596{
597 if (f == nullptr) return false;
598 if (f->deg != 0) return false;
599 if (level == 0)
600 return 1 == f->arr.ints[0];
601 else
602 return is_one(level - 1, f->arr.polys[0]);
603}
604void DPoly::negate_in_place(int level, TowerPolynomial &f)
605{
606 if (f == nullptr) return;
607 if (level == 0)
608 {
609 int deg = f->deg;
610 long *p = f->arr.ints;
611 for (int i = 0; i <= deg; i++)
612 if (p[i] != 0) ZZp_NEGATE(charac, p[i]);
613 }
614 else
615 {
616 int deg = f->deg;
617 TowerPolynomial *p = f->arr.polys;
618 for (int i = 0; i <= deg; i++)
619 if (p[i] != nullptr) negate_in_place(level - 1, p[i]);
620 }
621}
622
623void DPoly::reset_degree_0(TowerPolynomial &f)
624{
625 int fdeg = f->deg;
626 for (int j = fdeg; j >= 0; --j)
627 if (f->arr.ints[j] != 0)
628 {
629 f->deg = j;
630 return;
631 }
632 // at this point, everything is 0!
633 dealloc_poly(f); // sets f to 0
634}
635void DPoly::reset_degree_n(int level, TowerPolynomial &f)
636{
637 (void) level;
638 int fdeg = f->deg;
639 for (int j = fdeg; j >= 0; --j)
640 if (f->arr.polys[j] != nullptr)
641 {
642 f->deg = j;
643 return;
644 }
645 // at this point, everything is 0!
646 dealloc_poly(f); // sets f to 0
647}
648
649void DPoly::add_term(int level, TowerPolynomial &result, long coeff, exponents_t exp) const
650{
651 // modifies result.
652 // exp is an array [0..level-1] of exponent values for each variable
653 // 0..level-1
654 // the outer variable is at index 0.
655 // coeff is an already normalized coefficient, and is not 0.
656
657 int e = exp[0];
658
659 if (result == nullptr)
660 result = alloc_poly_n(e, nullptr);
661 else if (result->deg < e)
663
664 if (level == 0)
665 ZZp_ADD_TO(charac, result->arr.ints[e], coeff);
666 else
667 add_term(level - 1, result->arr.polys[e], coeff, exp + 1);
668}
669
670void DPoly::add_in_place_0(TowerPolynomial &f, const TowerPolynomial g)
671{
672 int i;
673 if (g == nullptr) return;
674 if (f == nullptr)
675 {
676 f = copy(0, g);
677 return;
678 }
679 int fdeg = f->deg;
680 int gdeg = g->deg;
681
682 increase_size_0(g->deg, f);
683 for (i = 0; i <= gdeg; i++)
684 ZZp_ADD_TO(charac, f->arr.ints[i], g->arr.ints[i]);
685 if (gdeg > fdeg)
686 f->deg = gdeg;
687 else if (gdeg == fdeg)
689}
690
691void DPoly::add_in_place_n(int level, TowerPolynomial &f, const TowerPolynomial g)
692{
693 int i;
694 if (g == nullptr) return;
695 if (f == nullptr)
696 {
697 f = copy(level, g);
698 return;
699 }
700 int fdeg = f->deg;
701 int gdeg = g->deg;
702
703 increase_size_n(g->deg, f);
704 for (i = 0; i <= gdeg; i++)
705 add_in_place(level - 1, f->arr.polys[i], g->arr.polys[i]);
706 if (gdeg > fdeg)
707 f->deg = gdeg;
708 else if (gdeg == fdeg)
709 {
710 // need to change the degree
711 for (int j = fdeg; j >= 0; --j)
712 if (f->arr.polys[j] != nullptr)
713 {
714 f->deg = j;
715 return;
716 }
717 // at this point, everything is 0!
718 dealloc_poly(f);
719 }
720}
721
722void DPoly::add_in_place(int level, TowerPolynomial &f, const TowerPolynomial g)
723{
724 if (level == 0)
725 add_in_place_0(f, g);
726 else
727 add_in_place_n(level, f, g);
728}
729
730void DPoly::subtract_in_place_0(TowerPolynomial &f, const TowerPolynomial g)
731{
732 int i;
733 if (g == nullptr) return;
734 if (f == nullptr)
735 {
736 f = copy(0, g);
737 negate_in_place(0, f);
738 return;
739 }
740 int fdeg = f->deg;
741 int gdeg = g->deg;
742
743 increase_size_0(g->deg, f);
744 for (i = 0; i <= gdeg; i++)
745 ZZp_SUBTRACT_TO(charac, f->arr.ints[i], g->arr.ints[i]);
746 if (gdeg > fdeg)
747 f->deg = gdeg;
748 else if (gdeg == fdeg)
749 {
750 // need to change the degree
751 for (int j = fdeg; j >= 0; --j)
752 if (f->arr.ints[j] != 0)
753 {
754 f->deg = j;
755 return;
756 }
757 // at this point, everything is 0!
758 dealloc_poly(f);
759 }
760}
761
762void DPoly::subtract_in_place_n(int level, TowerPolynomial &f, const TowerPolynomial g)
763{
764 int i;
765 if (g == nullptr) return;
766 if (f == nullptr)
767 {
768 f = copy(level, g);
769 negate_in_place(level, f);
770 return;
771 }
772 int fdeg = f->deg;
773 int gdeg = g->deg;
774
775 increase_size_n(g->deg, f);
776 for (i = 0; i <= gdeg; i++)
777 subtract_in_place(level - 1, f->arr.polys[i], g->arr.polys[i]);
778 if (gdeg > fdeg)
779 f->deg = gdeg;
780 else if (gdeg == fdeg)
781 {
782 // need to change the degree
783 for (int j = fdeg; j >= 0; --j)
784 if (f->arr.polys[j] != nullptr)
785 {
786 f->deg = j;
787 return;
788 }
789 // at this point, everything is 0!
790 dealloc_poly(f);
791 }
792}
793
794void DPoly::subtract_in_place(int level, TowerPolynomial &f, const TowerPolynomial g)
795{
796 if (level == 0)
798 else
799 subtract_in_place_n(level, f, g);
800}
801
802TowerPolynomial DPoly::mult_0(const TowerPolynomial f, const TowerPolynomial g, bool reduce_by_extension)
803{
804 if (f == nullptr || g == nullptr) return nullptr;
805 TowerPolynomial result = alloc_poly_0(f->deg + g->deg);
806
807 for (int i = 0; i <= f->deg; i++)
808 {
809 long a = f->arr.ints[i];
810 for (int j = 0; j <= g->deg; j++)
811 ZZp_APXY(charac, result->arr.ints[i + j], a, g->arr.ints[j]);
812 }
813
814 if (reduce_by_extension && extensions[0] != nullptr)
816 return result;
817}
818TowerPolynomial DPoly::mult_n(int level,
819 const TowerPolynomial f,
820 const TowerPolynomial g,
821 bool reduce_by_extension)
822{
823 if (f == nullptr || g == nullptr) return nullptr;
824 TowerPolynomial result = alloc_poly_n(f->deg + g->deg);
825
826 for (int i = 0; i <= f->deg; i++)
827 {
828 TowerPolynomial a = f->arr.polys[i];
829 if (a != nullptr)
830 for (int j = 0; j <= g->deg; j++)
831 {
832 TowerPolynomial b = g->arr.polys[j];
833 TowerPolynomial c = mult(level - 1, a, b, true);
834 if (c != nullptr)
835 {
836 add_in_place(level - 1, result->arr.polys[i + j], c);
837 dealloc_poly(c);
838 }
839 }
840 }
841
842 if (reduce_by_extension && extensions[level] != nullptr)
843 remainder(level, result, extensions[level]);
844 return result;
845}
846TowerPolynomial DPoly::mult(int level,
847 const TowerPolynomial f,
848 const TowerPolynomial g,
849 bool reduce_by_extension)
850{
851 if (level == 0) return mult_0(f, g, reduce_by_extension);
852 return mult_n(level, f, g, reduce_by_extension);
853}
854
855TowerPolynomial DPoly::invert(int level, const TowerPolynomial a)
856{
857 // plan: compute the extended gcd of a and extensions[level]
858 // as univariate polynomials (at level 'level').
859 // either return 0, if the gcd returned was not 1, or return
860 // result_u.
861 TowerPolynomial u, v;
862 TowerPolynomial g = gcd_coefficients(level, a, extensions[level], u, v);
863 if (!is_one(level, g))
864 {
865 dealloc_poly(u);
866 }
867 dealloc_poly(g);
868 dealloc_poly(v);
869 return u;
870}
871
872void DPoly::mult_by_coeff_0(TowerPolynomial &f, long b)
873{
874 if (f == nullptr) return;
875 long *p = f->arr.ints;
876 long deg = f->deg;
877 if (b == 0)
878 dealloc_poly(f);
879 else if (b != 1)
880 for (int i = 0; i <= deg; i++)
881 {
882 if (*p != 0) ZZp_MULT(charac, *p, b);
883 p++;
884 }
885}
886void DPoly::mult_by_coeff_n(int level, TowerPolynomial &f, TowerPolynomial b)
887{
888 if (f == nullptr) return;
889 TowerPolynomial *p = f->arr.polys;
890 long deg = f->deg;
891 if (b == nullptr)
892 {
893 dealloc_poly(f);
894 }
895 else if (!is_one(level - 1, b))
896 for (int i = 0; i <= deg; i++)
897 {
898 if (*p != nullptr) *p = mult(level - 1, *p, b, true);
899 p++;
900 }
901}
902void DPoly::make_monic_0(TowerPolynomial &f, long &result_multiplier)
903{
904 if (f == nullptr) return;
905 long *p = f->arr.ints;
906 long a = p[f->deg];
907 long b;
908 ZZp_INVERT(charac, b, a);
909 mult_by_coeff_0(f, b);
910 result_multiplier = b;
911}
912void DPoly::make_monic_n(int level, TowerPolynomial &f, TowerPolynomial &result_multiplier)
913{
914 if (f == nullptr) return;
915 TowerPolynomial *p = f->arr.polys;
916 TowerPolynomial a = p[f->deg];
917 TowerPolynomial b = invert(level - 1, a);
918 mult_by_coeff_n(level, f, b);
919 result_multiplier = b;
920}
921
922void DPoly::make_monic(int level, TowerPolynomial &f)
923{
924 if (f == nullptr) return;
925 if (level == 0)
926 {
927 long not_used;
928 make_monic_0(f, not_used);
929 }
930 else
931 {
932 TowerPolynomial not_used;
933 make_monic_n(level, f, not_used);
934 dealloc_poly(not_used);
935 }
936}
937
938bool DPoly::make_monic3(int level, TowerPolynomial &u1, TowerPolynomial &u2, TowerPolynomial &u3)
939// let c be the inverse of the lead coefficient of u3.
940// return false if this lead coeff is not invertible
941// else return true
942// replace u1, u2, u3 by c*u1, c*u2, c*u3
943{
944 if (u3 == nullptr) return true;
945
946 if (level == 0)
947 {
948 long c = 0;
949 make_monic_0(u3, c);
950 if (c == 0) return false;
951 mult_by_coeff_0(u1, c);
952 mult_by_coeff_0(u2, c);
953 }
954 else
955 {
956 TowerPolynomial c = nullptr;
957 make_monic_n(level, u3, c);
958 if (c == nullptr) return false;
959 mult_by_coeff_n(level, u1, c);
960 mult_by_coeff_n(level, u2, c);
961 dealloc_poly(c);
962 }
963 return true;
964}
965
966TowerPolynomial DPoly::division_in_place_monic(int level, TowerPolynomial &f, const TowerPolynomial g)
967{
968 // ASSUMPTION: g is MONIC, non-zero
969 if (f == nullptr) return nullptr;
970 if (f->deg < g->deg)
971 {
972 return nullptr;
973 }
974 int shift = f->deg - g->deg;
975 TowerPolynomial quot = alloc_poly_n(shift);
976
977 if (level == 0)
978 {
979 long *p = f->arr.ints;
980 long *q = g->arr.ints;
981 for (int d = f->deg; shift >= 0; d--, shift--)
982 {
983 long a = p[d];
984 if (a != 0)
985 {
986 quot->arr.ints[shift] = a;
987 ZZp_NEGATE(charac, a);
988 for (int j = 0; j <= g->deg; j++)
989 ZZp_APXY(charac, p[shift + j], a, q[j]);
990 }
991 }
993 }
994 else
995 {
996 TowerPolynomial *p = f->arr.polys;
997 TowerPolynomial *q = g->arr.polys;
998 for (int d = f->deg; shift >= 0; d--, shift--)
999 {
1000 TowerPolynomial a = p[d];
1001 if (a != nullptr)
1002 {
1003 quot->arr.polys[shift] = copy(level - 1, a);
1004 for (int j = 0; j <= g->deg; j++)
1005 {
1006 TowerPolynomial b = mult(level - 1, a, q[j], true);
1007 subtract_in_place(level - 1, p[j + shift], b);
1008 }
1009 }
1010 }
1011 reset_degree_n(level, f);
1012 }
1013 return quot;
1014}
1016 TowerPolynomial &f,
1017 const TowerPolynomial g,
1018 TowerPolynomial &result_quot)
1019// returns false if the lead coeff is not invertible
1020{
1021 assert(g != 0);
1022 if (f == nullptr || f->deg < g->deg)
1023 {
1024 result_quot = nullptr;
1025 return true;
1026 }
1027 int shift = f->deg - g->deg;
1028 result_quot = alloc_poly_n(shift);
1029
1030 if (level == 0)
1031 {
1032 // TODO: this code seems completely wrong!??!! too?
1033 long *p = f->arr.ints;
1034 long *q = g->arr.ints;
1035 long leadcoeff = q[g->deg];
1036 long invlead = 1;
1037 if (leadcoeff != 1)
1038 {
1039 ZZp_INVERT(charac, invlead, leadcoeff);
1040 }
1041 for (int d = f->deg; shift >= 0; d--, shift--)
1042 {
1043 long a = p[d];
1044 if (a != 0)
1045 {
1046 ZZp_MULT(charac, a, invlead);
1047 result_quot->arr.ints[shift] = a;
1048 ZZp_NEGATE(charac, a);
1049 for (int j = 0; j <= g->deg; j++)
1050 ZZp_APXY(charac, p[shift + j], a, q[j]);
1051 }
1052 }
1053 reset_degree_0(f);
1054 return true;
1055 }
1056 else
1057 {
1058 // TODO: this code seems completely wrong!??!!
1059 TowerPolynomial *p = f->arr.polys;
1060 TowerPolynomial *q = g->arr.polys;
1061 TowerPolynomial leadcoeff = q[g->deg];
1062 TowerPolynomial invlead;
1063 if (is_one(level - 1, leadcoeff))
1064 invlead = leadcoeff;
1065 else
1066 {
1067 invlead = invert(level - 1, leadcoeff);
1068 if (invlead == nullptr) return false;
1069 }
1070 for (int d = f->deg; shift >= 0; d--, shift--)
1071 {
1072 TowerPolynomial a = p[d];
1073 if (a != nullptr)
1074 {
1075 TowerPolynomial b = mult(level - 1, invlead, a, true);
1076 result_quot->arr.polys[shift] = copy(level - 1, b);
1077 for (int j = 0; j <= g->deg; j++)
1078 {
1079 b = mult(level - 1, a, q[j], true);
1080 subtract_in_place(level - 1, p[j + shift], b);
1081 }
1082 }
1083 }
1084 reset_degree_n(level, f);
1085 return true;
1086 }
1087}
1088
1089void DPoly::remainder(int level, TowerPolynomial &f, const TowerPolynomial g)
1090{
1091 if (g == nullptr) return;
1092 TowerPolynomial quot = nullptr;
1093 division_in_place(level, f, g, quot);
1094 dealloc_poly(quot);
1095}
1096
1097void DPoly::pseudo_remainder(int level, TowerPolynomial &f, const TowerPolynomial g)
1098{
1099 (void) level;
1100 (void) f;
1101 if (g == nullptr) return;
1102 // TODO: write
1103}
1104TowerPolynomial DPoly::pseudo_division(int level, TowerPolynomial &f, const TowerPolynomial g)
1105{
1106 (void) level;
1107 (void) f;
1108 if (g == nullptr) return nullptr;
1109 // TODO: write
1110 return nullptr;
1111}
1112TowerPolynomial DPoly::resultant(int level, TowerPolynomial f, TowerPolynomial g)
1113{
1114 // TODO: write
1115 (void) level;
1116 (void) f;
1117 (void) g;
1118 return nullptr;
1119}
1120static void swap_poly(TowerPolynomial &f, TowerPolynomial &g)
1121{
1122 TowerPolynomial a = f;
1123 f = g;
1124 g = a;
1125}
1126TowerPolynomial DPoly::gcd(int level, const TowerPolynomial f, const TowerPolynomial g)
1127{
1128 TowerPolynomial F = copy(level, f);
1129 TowerPolynomial G = copy(level, g);
1130 if (G == nullptr)
1131 {
1132 G = F;
1133 F = nullptr;
1134 }
1135 for (;;)
1136 {
1137#ifdef DEBUGGCD
1138 printf("G = %s\n", to_string(level, G));
1139#endif
1140 make_monic(level, G);
1141 if (G == nullptr) return nullptr; // failed
1142
1143#ifdef DEBUGGCD
1144 printf("monic G = %s\n", to_string(level, G));
1145 printf("F = %s\n", to_string(level, F));
1146#endif
1147
1148 remainder(level, F, G); // modifies F
1149 if (F == nullptr) return G;
1150
1151#ifdef DEBUGGCD
1152 printf("F mod G = %s\n", to_string(level, F));
1153#endif
1154
1155 swap_poly(F, G);
1156 }
1157}
1158
1159TowerPolynomial DPoly::gcd_coefficients(int level,
1160 const TowerPolynomial f,
1161 const TowerPolynomial g,
1162 TowerPolynomial &result_u,
1163 TowerPolynomial &result_v)
1164{
1165 // Assumption:
1166 // f and g are non-zero
1167 TowerPolynomial v1, v2, v3;
1168 TowerPolynomial u1, u2, u3;
1169 TowerPolynomial q = nullptr;
1170
1171 v1 = nullptr;
1172 v2 = from_long(level, 1);
1173 v3 = copy(level, g);
1174
1175 u1 = from_long(level, 1);
1176 u2 = nullptr;
1177 u3 = copy(level, f);
1178
1179 if (v3 == nullptr || (u3 != nullptr && v3->deg > u3->deg))
1180 {
1181 swap_poly(u1, v1);
1182 swap_poly(u2, v2);
1183 swap_poly(u3, v3);
1184 }
1185
1186// At the end of the loop:
1187// u1 * f + u2 * g == u3
1188// v1 * f + v2 * g == v3
1189// (and (v1,v2,v3) is close to the gcd
1190
1191#ifdef DEBUGGCD
1192 if (level == 1)
1193 {
1194 printf("u1 = %s\n", to_string(level, u1));
1195 printf("u2 = %s\n", to_string(level, u2));
1196 printf("u3 = %s\n", to_string(level, u3));
1197
1198 printf("v1 = %s\n", to_string(level, v1));
1199 printf("v2 = %s\n", to_string(level, v2));
1200 printf("v3 = %s\n", to_string(level, v3));
1201 }
1202#endif
1203
1204 while (v3 != nullptr)
1205 {
1206 if (!make_monic3(level, v1, v2, v3))
1207 {
1208 // deallocate some polynomials, then return 0. No monic gcd
1209 dealloc_poly(q);
1210 dealloc_poly(u1);
1211 dealloc_poly(u2);
1212 dealloc_poly(u3);
1213 dealloc_poly(v1);
1214 dealloc_poly(v2);
1215 dealloc_poly(v3);
1216 result_u = nullptr;
1217 result_v = nullptr;
1218 return nullptr;
1219 }
1221 level,
1222 u3,
1223 v3); // u3 := u3 - q*v3, as v3 is monic, this is always possible
1224
1225#ifdef DEBUGGCD
1226 if (level == 1)
1227 {
1228 printf("q = %s\n", to_string(level, q));
1229 printf("u3 = %s\n", to_string(level, u3));
1230 }
1231#endif
1232
1233 negate_in_place(level, q);
1234 TowerPolynomial a = mult(level, q, v1, false);
1235 TowerPolynomial b = mult(level, q, v2, false);
1236 add_in_place(level, u1, a);
1237 add_in_place(level, u2, b);
1238
1239#ifdef DEBUGGCD
1240 if (level == 1)
1241 {
1242 printf("u1 = %s\n", to_string(level, u1));
1243 printf("u2 = %s\n", to_string(level, u2));
1244 printf("u3 = %s\n", to_string(level, u3));
1245 }
1246#endif
1247 dealloc_poly(a); // MES: totally wipeout polys a, b here!
1248 dealloc_poly(b);
1249 swap_poly(u1, v1);
1250 swap_poly(u2, v2);
1251 swap_poly(u3, v3);
1252 }
1253
1254#ifdef DEBUGGCD
1255 if (level == 1)
1256 {
1257 printf("u1 = %s\n", to_string(level, u1));
1258 printf("u2 = %s\n", to_string(level, u2));
1259 printf("u3 = %s\n", to_string(level, u3));
1260 }
1261#endif
1262
1263 // At this point u3 is monic, and is the monic gcd
1264
1265 // v3 is already 0 here.
1266 dealloc_poly(v1);
1267 dealloc_poly(v2);
1268
1269 result_u = u1;
1270 result_v = u2;
1271 return u3;
1272}
1273
1274int DPoly::degree(int level, int whichvar, const TowerPolynomial f) const
1275{
1276 if (f == nullptr) return -1;
1277 if (whichvar == 0) return f->deg;
1278 // At this point, we need to find the max degree of the given var
1279 int deg = -1;
1280 for (int i = 0; i <= f->deg; i++)
1281 {
1282 TowerPolynomial g = f->arr.polys[i];
1283 if (g != nullptr)
1284 {
1285 int d = degree(level - 1, whichvar - 1, g);
1286 if (d > deg) deg = d;
1287 }
1288 }
1289 return deg;
1290}
1291
1292TowerPolynomial DPoly::mult_by_int_0(long a, const TowerPolynomial f)
1293{
1294 TowerPolynomial result = alloc_poly_0(f->deg);
1295 for (int i = 0; i <= f->deg; i++)
1296 {
1297 long c = f->arr.ints[i];
1298 if (c != 0)
1299 {
1300 ZZp_MULT(charac, c, a);
1301 result->arr.ints[i] = c;
1302 }
1303 }
1305 return result;
1306}
1307TowerPolynomial DPoly::mult_by_int_n(int level, long a, const TowerPolynomial f)
1308{
1309 TowerPolynomial result = alloc_poly_n(f->deg);
1310 for (int i = 0; i <= f->deg; i++)
1311 {
1312 TowerPolynomial c = f->arr.polys[i];
1313 if (c != nullptr) result->arr.polys[i] = mult_by_int(level - 1, a, c);
1314 }
1315 reset_degree_n(level, result);
1316 return result;
1317}
1318
1319TowerPolynomial DPoly::mult_by_int(int level, long a, const TowerPolynomial f)
1320{
1321 if (f == nullptr) return nullptr;
1322 if (level == 0) return mult_by_int_0(a, f);
1323 return mult_by_int_n(level, a, f);
1324}
1325
1326TowerPolynomial DPoly::diff_0(const TowerPolynomial f)
1327{
1328 if (f == nullptr || f->deg == 0) return nullptr;
1329 TowerPolynomial result = alloc_poly_0(f->deg - 1);
1330 for (int i = 1; i <= f->deg; i++)
1331 {
1332 long c = f->arr.ints[i];
1333 if (c != 0)
1334 {
1335 ZZp_MULT(charac, c, i);
1336 result->arr.ints[i - 1] = c;
1337 }
1338 }
1340 return result;
1341}
1342
1343TowerPolynomial DPoly::diff_n(int level, int whichvar, const TowerPolynomial f)
1344{
1345 TowerPolynomial result;
1346 if (whichvar == 0)
1347 {
1348 result = alloc_poly_0(f->deg - 1);
1349 for (int i = 1; i <= f->deg; i++)
1350 {
1351 TowerPolynomial c = f->arr.polys[i];
1352 if (c != nullptr) result->arr.polys[i - 1] = mult_by_int(level - 1, i, c);
1353 }
1354 }
1355 else
1356 {
1357 result = alloc_poly_0(f->deg);
1358 for (int i = 0; i <= f->deg; i++)
1359 {
1360 TowerPolynomial c = f->arr.polys[i];
1361 if (c != nullptr) result->arr.polys[i] = diff(level - 1, whichvar - 1, c);
1362 }
1363 }
1364 reset_degree_n(level, result);
1365 return result;
1366}
1367
1368TowerPolynomial DPoly::diff(int level, int whichvar, const TowerPolynomial f)
1369{
1370 if (f == nullptr) return nullptr;
1371 if (level == 0) return diff_0(f);
1372 return diff_n(level, whichvar, f);
1373}
1374
1375TowerPolynomial DPoly::power_mod(int level, const TowerPolynomial f, mpz_srcptr m, const TowerPolynomial g)
1376// f^m mod g
1377{
1378 // We assume that m > 0. THIS IS NOT CHECKED!!
1379 mpz_t n;
1380 mpz_init_set(n, m);
1381 TowerPolynomial prod = from_long(level, 1);
1382 TowerPolynomial base = copy(level, f);
1383 TowerPolynomial tmp;
1384
1385 for (;;)
1386 {
1387 // fprintf(stdout, "prod = ");
1388 // dpoly(level,prod);
1389 // fprintf(stdout, "\nbase = ");
1390 // dpoly(level,base);
1391 // fprintf(stdout, "\n");
1392 if (RingZZ::mod_ui(n, 2) == 1)
1393 {
1394 tmp = mult(level, prod, base, false);
1395 remainder(level, tmp, g);
1396 // TODO: free prod
1397 prod = tmp;
1398 }
1399 mpz_tdiv_q_2exp(n, n, 1);
1400 if (mpz_sgn(n) == 0)
1401 {
1402 mpz_clear(n);
1403 // fprintf(stdout, "final prod = ");
1404 // dpoly(level,prod);
1405 // fprintf(stdout, "\nbase = ");
1406 // dpoly(level,base);
1407 // fprintf(stdout, "\n");
1408 // TODO: free base
1409 return prod;
1410 }
1411 else
1412 {
1413 tmp = mult(level, base, base, false);
1414 remainder(level, tmp, g);
1415 // TODO: free base
1416 base = tmp;
1417 }
1418 }
1419}
1420
1421TowerPolynomial DPoly::lowerP(int level, const TowerPolynomial f)
1422{
1423 int i, j;
1424 TowerPolynomial result;
1425 if (f == nullptr) return nullptr;
1426 int charac_as_int = static_cast<int>(charac);
1427 int newdeg = f->deg / charac_as_int; // should be exact...
1428 if (level == 0)
1429 {
1430 result = alloc_poly_0(newdeg);
1431 // In this situation, we just need to grab every p*i coeff...
1432 for (i = 0, j = 0; i <= newdeg; i++, j += charac_as_int)
1433 result->arr.ints[i] = f->arr.ints[j];
1434 }
1435 else
1436 {
1437 result = alloc_poly_n(newdeg);
1438 mpz_t order;
1439 mpz_init(order);
1440 unsigned long extdeg = 1;
1441 for (i = 0; i < level; i++) extdeg *= degree_of_extension(i);
1442 mpz_ui_pow_ui(order, charac_as_int, extdeg - 1);
1443 for (i = 0, j = 0; i <= newdeg; i++, j += charac_as_int)
1444 {
1445 // need p-th roots of the coefficients. So we take p^(n-1)
1446 // power (if coefficients are in field of size p^n)
1447 TowerPolynomial a = f->arr.polys[j];
1448 TowerPolynomial b = power_mod(level - 1, a, order, extensions[level - 1]);
1449 result->arr.polys[i] = b;
1450 }
1451 mpz_clear(order);
1452 }
1453 return result;
1454}
1455
1456int DPoly::index_of_var(int level, const TowerPolynomial f) const
1457{
1458 if (f == nullptr or level < 0 or f->deg >= 2) return -1;
1459 if (level == 0)
1460 {
1461 if (f->deg == 0) return -1;
1462 // At this point, degree is 1.
1463 if (f->arr.ints[0] == 0 and f->arr.ints[1] == 1)
1464 return 0;
1465 else
1466 return -1;
1467 }
1468 else
1469 {
1470 if (f->arr.polys[0] == nullptr and is_one(level - 1, f->arr.polys[1]))
1471 return level;
1472 if (f->deg == 1) return -1;
1473 return index_of_var(level - 1, f->arr.polys[0]);
1474 }
1475}
1476
1478 const TowerPolynomial f,
1479 std::vector<int> &result_maxdegs) const
1480{
1481 // Set the values of result_maxdegs at indices: 0..level
1482 result_maxdegs[level] = std::max(result_maxdegs[level], f->deg);
1483 if (level == 0) return;
1484 for (int i = 0; i <= f->deg; i++)
1485 if (f->arr.polys[i] != nullptr)
1486 degrees_of_vars(level - 1, f->arr.polys[i], result_maxdegs);
1487}
1488
1489DRing::DRing(long charac, int nvars, const TowerPolynomial *exts)
1490 : level(nvars - 1), D(charac, nvars, exts), P(charac)
1491{
1492}
1493
1494DRing *DRing::create(long p, int nvars0, const TowerPolynomial *ext0)
1495{
1496 return new DRing(p, nvars0, ext0);
1497}
1498
1499void DRing::set_from_int(TowerPolynomial &result, mpz_srcptr r)
1500{
1501 mpz_t a;
1502 mpz_init(a);
1503 mpz_mod_ui(a, r, P);
1504 long c = mpz_get_si(a);
1505 mpz_clear(a);
1506 if (c < 0) c += P;
1507 result = D.from_long(level, c);
1508}
1509
1510bool DRing::set_from_mpq(TowerPolynomial &result, mpq_srcptr r)
1511{
1512 // returns false if r doesn't lift
1513 mpz_t a;
1514 mpz_init(a);
1515 mpz_mod_ui(a, mpq_numref(r), P);
1516 long ctop = mpz_get_si(a);
1517 mpz_mod_ui(a, mpq_denref(r), P);
1518 long cbottom = mpz_get_si(a);
1519 mpz_clear(a);
1520 if (ctop < 0) ctop += P;
1521 if (cbottom < 0) cbottom += P;
1522 if (cbottom == 0)
1523 {
1524 result = nullptr;
1525 return false;
1526 }
1527 ZZp_INVERT(P, cbottom, cbottom);
1528 ZZp_MULT(P, ctop, cbottom);
1529
1530 result = D.from_long(level, ctop);
1531 return true;
1532}
1533
1534int DRing::extension_degree(int firstvar) // returns -1 if infinite
1535{
1536 int result = 1;
1537 for (int i = 0; i <= level - firstvar; i++)
1538 {
1539 int d = D.degree_of_extension(i);
1540 if (d < 0) return -1;
1541 result *= d;
1542 }
1543 return result;
1544}
1545
1547 const TowerPolynomial f,
1548 bool p_one,
1549 bool p_plus,
1550 bool p_parens,
1551 M2_ArrayString names) const
1552{
1553 D.elem_text_out(o, level, f, p_one, p_plus, p_parens, names);
1554}
1555
1556void DRing::add_term(elem &result, long coeff, exponents_t exp) const
1557{
1558 long c;
1559 ZZp_FROM_INT(P, c, coeff); // puts it into normal form, just in case.
1560 if (c == 0) return;
1561 D.add_term(level, result, c, exp);
1562}
1563
1564void DPolyTraverser::traverse(const TowerPolynomial f)
1565{
1566 exponents_t exp = new int[D->nvars];
1567 for (size_t i = 0; i < D->nvars; i++) exp[i] = 0;
1568 traverse1(D->nlevels - 1,
1569 f,
1570 exp); // the return value is only for the recursive algorithm
1571 delete[] exp;
1572}
1573
1574bool DPolyTraverser::traverse1(int level, const TowerPolynomial f, exponents_t exp)
1575{
1576 if (level == 0)
1577 {
1578 long *cfs = f->arr.ints;
1579 for (int i = f->deg; i >= 0; --i)
1580 if (cfs[i] != 0)
1581 {
1582 exp[level] = i;
1583 if (!viewTerm(cfs[i], exp)) return false;
1584 }
1585 exp[level] = 0;
1586 }
1587 else
1588 {
1589 TowerPolynomial *cfs = f->arr.polys;
1590 for (int i = f->deg; i >= 0; --i)
1591 if (cfs[i] != nullptr)
1592 {
1593 exp[level] = i;
1594 if (!traverse1(level - 1, cfs[i], exp)) return false;
1595 }
1596 exp[level] = 0;
1597 }
1598 return true;
1599}
1600
1601// Local Variables:
1602// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1603// indent-tabs-mode: nil
1604// End:
exponents::Exponents exponents_t
Legacy RingZZ — a Ring-derived integer ring backed by GMP mpz_t.
void subtract_in_place(int level, TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:794
TowerPolynomial * extensions
Definition dpoly.hpp:114
static void increase_size_n(int newdeg, TowerPolynomial &f)
Definition dpoly.cpp:249
void make_monic(int level, TowerPolynomial &f)
Definition dpoly.cpp:922
void mult_by_coeff_0(TowerPolynomial &f, long b)
Definition dpoly.cpp:872
static TowerPolynomial read_poly(char *&str, int level)
Definition dpoly.cpp:383
static TowerPolynomial alloc_poly_n(int deg, TowerPolynomial *elems=nullptr)
Definition dpoly.cpp:265
TowerPolynomial mult_n(int level, const TowerPolynomial f, const TowerPolynomial g, bool reduce_by_extension)
Definition dpoly.cpp:818
TowerPolynomial random(int level, int deg)
Definition dpoly.cpp:549
TowerPolynomial pseudo_division(int level, TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:1104
static TowerPolynomial copy(int level, const TowerPolynomial f)
Definition dpoly.cpp:483
DPoly(long p, int nvars0, const TowerPolynomial *extensions=nullptr)
Definition dpoly.cpp:95
TowerPolynomial diff_0(const TowerPolynomial f)
Definition dpoly.cpp:1326
void reset_degree_n(int level, TowerPolynomial &f)
Definition dpoly.cpp:635
TowerPolynomial var(int level, int v)
Definition dpoly.cpp:515
TowerPolynomial invert(int level, const TowerPolynomial a)
Definition dpoly.cpp:855
int degree_of_extension(int level)
Definition dpoly.cpp:100
void elem_text_out(buffer &o, int level, const TowerPolynomial f, bool p_one, bool p_plus, bool p_parens, M2_ArrayString names) const
Definition dpoly.cpp:144
TowerPolynomial gcd_coefficients(int level, const TowerPolynomial f, const TowerPolynomial g, TowerPolynomial &result_u, TowerPolynomial &result_v)
Definition dpoly.cpp:1159
void mult_by_coeff_n(int level, TowerPolynomial &f, TowerPolynomial b)
Definition dpoly.cpp:886
void remainder(int level, TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:1089
TowerPolynomial random_0(int deg)
Definition dpoly.cpp:533
TowerPolynomial power_mod(int level, const TowerPolynomial f, mpz_srcptr n, const TowerPolynomial g)
Definition dpoly.cpp:1375
void add_in_place(int level, TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:722
static std::ostream & append_to_stream(std::ostream &o, int level, const TowerPolynomial f)
Definition dpoly.cpp:389
void add_in_place_n(int level, TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:691
static bool is_equal(int level, const TowerPolynomial f, const TowerPolynomial g)
Definition dpoly.cpp:459
void make_monic_n(int level, TowerPolynomial &f, TowerPolynomial &result_multiplier)
Definition dpoly.cpp:912
long charac
Definition dpoly.hpp:115
TowerPolynomial diff_n(int level, int whichvar, const TowerPolynomial f)
Definition dpoly.cpp:1343
void degrees_of_vars(int level, const TowerPolynomial f, std::vector< int > &result_max_degs) const
Definition dpoly.cpp:1477
TowerPolynomial mult_by_int_0(long c, const TowerPolynomial f)
Definition dpoly.cpp:1292
void pseudo_remainder(int level, TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:1097
static void increase_size_0(int newdeg, TowerPolynomial &f)
Definition dpoly.cpp:233
TowerPolynomial random_n(int level, int deg)
Definition dpoly.cpp:541
TowerPolynomial mult_0(const TowerPolynomial f, const TowerPolynomial g, bool reduce_by_extension)
Definition dpoly.cpp:802
TowerPolynomial mult(int level, const TowerPolynomial f, const TowerPolynomial g, bool reduce_by_extension)
Definition dpoly.cpp:846
TowerPolynomial diff(int level, int var, const TowerPolynomial f)
Definition dpoly.cpp:1368
void subtract_in_place_0(TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:730
TowerPolynomial gcd(int level, const TowerPolynomial f, const TowerPolynomial g)
Definition dpoly.cpp:1126
void add_in_place_0(TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:670
static TowerPolynomial read_poly_n(char *&str, int level)
Definition dpoly.cpp:301
int compare(int level, const TowerPolynomial f, const TowerPolynomial g)
Definition dpoly.cpp:560
bool make_monic3(int level, TowerPolynomial &u1, TowerPolynomial &u2, TowerPolynomial &u3)
Definition dpoly.cpp:938
TowerPolynomial lowerP(int level, const TowerPolynomial f)
Definition dpoly.cpp:1421
void initialize(long p, int nvars0, const TowerPolynomial *ext0)
Definition dpoly.cpp:80
static void dealloc_poly(TowerPolynomial &f)
Definition dpoly.cpp:292
void make_monic_0(TowerPolynomial &f, long &result_multiplier)
Definition dpoly.cpp:902
void add_term(int level, TowerPolynomial &result, long coeff, exponents_t exp) const
Definition dpoly.cpp:649
static TowerPolynomial alloc_poly_0(int deg, long *elems=nullptr)
Definition dpoly.cpp:279
void negate_in_place(int level, TowerPolynomial &f)
Definition dpoly.cpp:604
TowerPolynomial mult_by_int(int level, long c, const TowerPolynomial f)
Definition dpoly.cpp:1319
void reset_degree_0(TowerPolynomial &f)
Definition dpoly.cpp:623
static TowerPolynomial read_poly_0(char *&str)
Definition dpoly.cpp:341
int nvars
Definition dpoly.hpp:112
TowerPolynomial resultant(int level, TowerPolynomial f, TowerPolynomial g)
Definition dpoly.cpp:1112
int index_of_var(int level, const TowerPolynomial f) const
Definition dpoly.cpp:1456
static bool is_one(int level, const TowerPolynomial f)
Definition dpoly.cpp:595
void subtract_in_place_n(int level, TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:762
int nlevels
Definition dpoly.hpp:113
void extensions_text_out(buffer &o, M2_ArrayString names) const
Definition dpoly.cpp:221
TowerPolynomial mult_by_int_n(int level, long c, const TowerPolynomial f)
Definition dpoly.cpp:1307
static void display_poly(FILE *fil, int level, const TowerPolynomial f)
Definition dpoly.cpp:428
bool down_level(int newlevel, int oldlevel, TowerPolynomial &f)
Definition dpoly.cpp:109
bool division_in_place(int level, TowerPolynomial &f, const TowerPolynomial g, TowerPolynomial &result_quot)
Definition dpoly.cpp:1015
int degree(int level, int var, const TowerPolynomial f) const
Definition dpoly.cpp:1274
static char * to_string(int level, const TowerPolynomial f)
Definition dpoly.cpp:417
TowerPolynomial division_in_place_monic(int level, TowerPolynomial &f, const TowerPolynomial g)
Definition dpoly.cpp:966
static TowerPolynomial from_long(int level, long c)
Definition dpoly.cpp:501
const DPoly * D
Definition dpoly.hpp:464
bool traverse1(int level, const TowerPolynomial g, exponents_t exp)
Definition dpoly.cpp:1574
void traverse(const TowerPolynomial f)
Definition dpoly.cpp:1564
virtual bool viewTerm(long coeff, const_exponents exp)=0
void add_term(elem &result, long coeff, exponents_t exp) const
Definition dpoly.cpp:1556
void set_from_int(TowerPolynomial &result, mpz_srcptr r)
Definition dpoly.cpp:1499
long P
Definition dpoly.hpp:269
int extension_degree(int firstvar)
Definition dpoly.cpp:1534
void elem_text_out(buffer &o, const TowerPolynomial f, bool p_one, bool p_plus, bool p_parens, M2_ArrayString names) const
Definition dpoly.cpp:1546
bool set_from_mpq(TowerPolynomial &result, mpq_srcptr r)
Definition dpoly.cpp:1510
static DRing * create(long p, int nvars0, const TowerPolynomial *ext0)
Definition dpoly.cpp:1494
int level
Definition dpoly.hpp:267
DRing(long charac, int nvars, const TowerPolynomial *exts)
Definition dpoly.cpp:1489
TowerPolynomial elem
Definition dpoly.hpp:275
DPoly D
Definition dpoly.hpp:268
static unsigned int mod_ui(mpz_srcptr n, unsigned int p)
Definition ZZ.cpp:55
void ZZp_MULT(long charac, long &a, long b)
Definition dpoly.cpp:63
void ZZp_ADD_TO(long charac, long &a, long b)
Definition dpoly.cpp:53
void ZZp_APXY(long charac, long &a, long b, long c)
Definition dpoly.cpp:49
void dpoly(int level, const TowerPolynomial f)
Definition dpoly.cpp:458
void ZZp_RANDOM(long charac, long &result)
Definition dpoly.cpp:75
void ZZp_INVERT(long charac, long &result, long b)
Definition dpoly.cpp:68
static void swap_poly(TowerPolynomial &f, TowerPolynomial &g)
Definition dpoly.cpp:1120
long gcd_extended(long a, long b, long &u, long &v)
Definition dpoly.cpp:14
void ZZp_SUBTRACT_TO(long charac, long &a, long b)
Definition dpoly.cpp:58
void ZZp_NEGATE(long charac, long &a)
Definition dpoly.cpp:48
void ZZp_FROM_INT(long charac, long &a, long b)
Definition dpoly.cpp:43
static int n_nonzero_terms(int level, const TowerPolynomial f)
Definition dpoly.cpp:127
Native univariate polynomial arithmetic over QQ extensions and finite fields.
static CanonicalForm base
Definition factory.cpp:289
int p
void freemem(void *s)
Definition m2-mem.cpp:103
VALGRIND_MAKE_MEM_DEFINED & result(result)
char newline[]
Definition m2-types.cpp:49
#define newarray(T, len)
Definition newdelete.hpp:82
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
int32_t rawRandomInt(int32_t max)
Definition random.cpp:44
Engine-boundary C API for the engine's PRNG and rational / real / complex random draws.
tbb::flow::graph G
TermIterator< Nterm > end(Nterm *)
Definition ringelem.cpp:5
Heap-allocated node of a tower polynomial: a dense degree-indexed coefficient array that recurses thr...
Definition dpoly.hpp:81