Macaulay2 Engine
Loading...
Searching...
No Matches
tower.cpp
Go to the documentation of this file.
1// Copyright 2010 Michael E. Stillman
2
3#include "tower.hpp"
4
5#include "ExponentList.hpp"
6#include "dpoly.hpp"
7#include "ring.hpp"
8#include "ringmap.hpp"
9#include "polyring.hpp"
10#include "monoid.hpp"
11
12#define TOWER_POLYNOMIAL_VAL(f) reinterpret_cast<TowerPolynomial>((f).poly_val)
13
15bool Tower::initialize(long charac0,
16 M2_ArrayString names0,
17 const VECTOR(ring_elem) & extensions)
18{
19 initialize_ring(charac0);
21
22 names = names0;
23 nvars = names->len;
24 level = nvars - 1;
25
26 // Translate extensions to poly's
27 if (extensions.size() == 0)
28 {
29 D = DRing::create(charac0, nvars, nullptr);
30 }
31 else
32 {
33 TowerPolynomial* exts = new TowerPolynomial[extensions.size()];
34 for (int i = 0; i < extensions.size(); i++)
35 exts[i] = reinterpret_cast<TowerPolynomial>(extensions[i].poly_val);
36 D = DRing::create(charac0, nvars, exts);
37 delete[] exts;
38 }
39
40 zeroV = from_long(0);
41 oneV = from_long(1);
43
44 return true;
45}
46Tower *Tower::create(int charac, M2_ArrayString names)
47{
48 Tower *result = new Tower;
49 VECTOR(ring_elem) extensions;
50 if (!result->initialize(charac, names, extensions)) return nullptr;
51 return result;
52}
53
54Tower *Tower::create(const Tower *R, M2_ArrayString new_names)
55{
56 // TODO: write
57 (void) R;
58 (void) new_names;
59 return nullptr;
60}
61
62Tower *Tower::create(const Tower *R, VECTOR(ring_elem) & extensions)
63{
64 Tower *result = new Tower;
65 if (!result->initialize(R->characteristic(), R->names, extensions)) return nullptr;
66 return result;
67}
68
69unsigned int Tower::computeHashValue(const ring_elem a) const
70{
71 // TODO HASH
72 (void) a;
73 return 3212415;
74}
75
76void Tower::text_out(buffer &o) const
77{
78 o << "Tower[ZZ/" << characteristic() << "[";
79 for (int i = 0; i < nvars - 1; i++) o << names->array[i] << ",";
80 if (nvars > 0) o << names->array[nvars - 1];
81 o << "]]";
82 D->extensions_text_out(o, names);
83}
84
86{
87 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(a);
88 return D->index_of_var(f1);
89}
90
92{
93 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(a);
94 std::vector<int> max_degs;
95 D->degrees_of_vars(f1, max_degs);
96 int nelems = 0;
97 for (size_t i = 0; i < max_degs.size(); i++)
98 if (max_degs[i] > 0) nelems++;
100 int next = 0;
101 for (size_t i = 0; i < max_degs.size(); i++)
102 if (max_degs[i] > 0) result->array[next++] = static_cast<int>(i);
103 return result;
104}
105
107{
108 TowerPolynomial f;
109 D->set_from_long(f, n);
110 return TOWER_RINGELEM(f);
111}
112
113ring_elem Tower::from_int(mpz_srcptr n) const
114{
115 TowerPolynomial f;
116 D->set_from_int(f, n);
117 return TOWER_RINGELEM(f);
118}
119
120bool Tower::from_rational(mpq_srcptr q, ring_elem &result) const
121{
122 TowerPolynomial f;
123 if (not D->set_from_mpq(f, q)) return false;
125 return true;
126}
127
129{
130 TowerPolynomial f;
131 D->set_var(f, v);
132 return TOWER_RINGELEM(f);
133}
134
135bool Tower::is_unit(const ring_elem f) const
136{
137 // Write this. Git issue #611.
138 (void) f;
139 return false;
140}
141
142bool Tower::is_zero(const ring_elem f) const
143{
144 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
145
146 return D->is_zero(f1);
147}
148
149bool Tower::is_equal(const ring_elem f, const ring_elem g) const
150{
151 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
152 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
153
154 return D->is_equal(f1, g1);
155}
156
157int Tower::compare_elems(const ring_elem f, const ring_elem g) const
158{
159 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
160 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
161
162 return D->compare(f1, g1);
163}
164
166{
167 // Write this. Git issue #611.
168 return f;
169}
170
172{
173 // nothing needed to remove? Or should we remove it?
174}
175
177{
178 TowerPolynomial f1;
179 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
180 TowerPolynomial h;
181 D->set_zero(h);
182 D->set_zero(f1);
183 D->subtract(h, f1, g1);
184 return TOWER_RINGELEM(h);
185}
186
188{
189 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
190 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
191 TowerPolynomial h;
192 D->set_zero(h);
193 D->add(h, f1, g1);
194 return TOWER_RINGELEM(h);
195}
196
198{
199 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
200 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
201 TowerPolynomial h;
202 D->set_zero(h);
203 D->subtract(h, f1, g1);
204 return TOWER_RINGELEM(h);
205}
206
208{
209 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
210 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
211 TowerPolynomial h;
212 D->set_zero(h);
213 D->mult(h, f1, g1);
214 return TOWER_RINGELEM(h);
215}
216
218{
219 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
220 TowerPolynomial h;
221 D->set_zero(h);
222 if (!D->invert(h, f1)) ERROR("element not invertible");
223 return TOWER_RINGELEM(h);
224}
225
227{
228 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
229 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
230 TowerPolynomial h;
231 D->set_zero(h);
232 D->divide(h, f1, g1);
233 return TOWER_RINGELEM(h);
234}
235
237{
238 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
239 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
240 TowerPolynomial h;
241 D->set_zero(h);
242 D->remainder(h, f1, g1);
243 return TOWER_RINGELEM(h);
244}
245
247{
248 TowerPolynomial f;
249 D->set_zero(f);
250 D->set_random(f);
251 return TOWER_RINGELEM(f);
252}
253
255 const ring_elem f,
256 bool p_one,
257 bool p_plus,
258 bool p_parens) const
259{
260 D->elem_text_out(o, TOWER_POLYNOMIAL_VAL(f), p_one, p_plus, p_parens, names);
261}
262
277{
278 const RingMap *map;
279 const Ring *K;
281
282 TowerPolynomial f;
284 const Ring *target;
286 int nvars;
287
288 virtual bool viewTerm(long coeff, const_exponents exp)
289 {
290 // translate exp to varpower
291 // map->eval_term
292 // either:
293 // H->add, or target->add_to
294 vp.resize(0);
296 ring_elem c = K->from_long(coeff);
297 ring_elem a = map->eval_term(K, c, vp.data(), first_var, nvars);
298 H->add(a);
299 return true;
300 }
301
302 public:
304 const RingMap *map0,
305 const ring_elem f0,
306 int first_var0)
307 : DPolyTraverser(T->D),
308 map(map0),
310 first_var(first_var0),
311 nvars(T->n_vars())
312 {
313 target = map->get_ring();
314 H = target->make_SumCollector();
315 const PolynomialRing *P = target->cast_to_PolynomialRing();
316 K = (P == nullptr ? target : P->getCoefficients());
317 }
318
319 virtual ~TowerEvaluator() { delete H; }
321 {
322 traverse(f);
323 return H->getValue();
324 }
325};
326
328 const ring_elem f,
329 int first_var) const
330{
331 TowerEvaluator m(this, map, f, first_var);
332 return m.getValue();
333}
334
335bool Tower::promote(const Ring *Rf, const ring_elem f, ring_elem &result) const
336{
337 // Write this. Git issue #611
338 (void) Rf;
339 (void) f;
340 (void) result;
341 return false;
342}
343
344bool Tower::lift(const Ring *Rg, const ring_elem f, ring_elem &result) const
345{
346 // Write this. Git issue #611.
347 (void) Rg;
348 (void) f;
349 (void) result;
350 return false;
351}
352
354 const ring_elem b,
355 ring_elem &x,
356 ring_elem &y) const
357{
358 // Write this. Git issue #611.
359 (void) a;
360 (void) b;
361 (void) x;
362 (void) y;
363}
364
366{
367 TowerPolynomial h;
368 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
369 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
370 D->gcd(h, f1, g1);
371 return TOWER_RINGELEM(h);
372}
373
375 const ring_elem g,
376 ring_elem &u,
377 ring_elem &v) const
378{
379 TowerPolynomial h, u1, v1;
380 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
381 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
382 D->gcd_coefficients(h, u1, v1, f1, g1);
383 u = TOWER_RINGELEM(u1);
384 v = TOWER_RINGELEM(v1);
385 return TOWER_RINGELEM(h);
386}
387
388int Tower::degreeInVariable(int whichvar, const ring_elem f) const
389{
390 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
391 return D->degree(whichvar, f1);
392}
393
394ring_elem Tower::differentiate(int whichvar, const ring_elem f) const
395{
396 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
397 TowerPolynomial h = nullptr;
398 D->diff(whichvar, h, f1);
399 return TOWER_RINGELEM(h);
400}
401
402int Tower::extension_degree(int firstvar) const
403{
404 // returns -1 if infinite
405 return D->extension_degree(firstvar);
406}
407
409 mpz_srcptr n,
410 const ring_elem g) const // f^n mod g
411{
412 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
413 TowerPolynomial g1 = TOWER_POLYNOMIAL_VAL(g);
414 TowerPolynomial h = nullptr;
415 D->power_mod(h, f1, n, g1);
416 return TOWER_RINGELEM(h);
417}
418
420{
421 TowerPolynomial f1 = TOWER_POLYNOMIAL_VAL(f);
422 TowerPolynomial h = nullptr;
423 D->lowerP(h, f1);
424 return TOWER_RINGELEM(h);
425}
426
428// top level tower gcd routines //
430
431#include "relem.hpp"
432
434{
435 const Tower *R = F->get_ring()->cast_to_Tower();
436 const Tower *S = G->get_ring()->cast_to_Tower();
437 if (R == nullptr || R != S)
438 {
439 ERROR("encountered different rings");
440 }
441
442 ring_elem result = R->gcd(F->get_value(), G->get_value());
443 return RingElement::make_raw(R, result);
444}
445
447 const RingElement *G,
448 const RingElement **A,
449 const RingElement **B)
450{
451 const Tower *R = F->get_ring()->cast_to_Tower();
452 const Tower *S = G->get_ring()->cast_to_Tower();
453 if (R == nullptr || R != S)
454 {
455 ERROR("encountered different rings");
456 }
457
458 ring_elem u, v;
459 ring_elem result = R->gcd_extended(F->get_value(), G->get_value(), u, v);
460 *A = RingElement::make_raw(R, u);
461 *B = RingElement::make_raw(R, v);
462 return RingElement::make_raw(R, result);
463}
464
466// top level translation to polynomials in other rings //
468
469#include "polyring.hpp"
470
472{
473 // create a TowerPolynomial in the Tower T, return it.
474
475 const Monoid *M = R->getMonoid();
476 const Ring *K = R->getCoefficients();
477 int nvars = R->n_vars();
478 TowerPolynomial result = nullptr;
479 exponents_t exp = new int[nvars];
480 for (Nterm& t : fR)
481 {
482 M->to_expvector(t.monom, exp);
483 std::pair<bool, long> res = K->coerceToLongInteger(t.coeff);
484 assert(res.first);
485 int c1 = static_cast<int>(res.second);
486
487 D->add_term(result, c1, exp);
488 }
489 delete[] exp;
490 return TOWER_RINGELEM(result);
491}
492
493#if 0
494ring_elem DPoly::translateFromTower(int level, const PolynomialRing *P, TowerPolynomial f) const
495{
496 if (f == 0) return 0;
497 if (level == 0)
498 {
499 // create a univariate poly in variable P_0
500 }
501 else
502 {
503 ring_elem b = P->var(level);
504 for (int i=0; i<=f->deg; i++)
505 {
506 if (f->arr.polys[i] != 0)
507 {
508 ring_elem a = translateFromTower(level-1, P, f->arr.polys[i]);
509 ring_elem c = P->power(b,i);
510 ring_elem d = P->mult(c,a);
511 result = P->add(result, d);
512 }
513 }
514 return result;
515 }
516}
517
518ring_elem DRing::translateFromTower(const PolynomialRing *P, TowerPolynomial f) const
519{
520 // create a polynomial in P from the tower TowerPolynomial fT
521 TowerPolynomial f = TOWER_POLYNOMIAL_VAL(fT);
522 return D.translateFromTower(level, P, f);
523}
524
525ring_elem Tower::translateFromTower(const PolynomialRing *P, ring_elem fT) const
526{
527 // create a polynomial in P from the tower TowerPolynomial fT
528 TowerPolynomial f = TOWER_POLYNOMIAL_VAL(fT);
529 return D->translateFromTower(P, f);
530}
531#endif
532
533extern "C" // TODO: remove when this function is in e/interface
535 const RingElement *F)
536{
537 // either: F is an element in a Tower, or is an element in a PolynomialRing.
538 // In both cases: the number of variables and the characteristic should
539 // be the same.
541 const Tower *T = newRing->cast_to_Tower();
542 if (P != nullptr && T != nullptr)
543 {
544 if (P->n_vars() != T->n_vars())
545 {
546 ERROR("expected rings with the same number of variables");
547 return nullptr;
548 }
549 if (P->characteristic() != T->characteristic())
550 {
551 ERROR("expected rings with the same characteristic");
552 return nullptr;
553 }
554 ring_elem a = T->translate(P, F->get_value());
555 return RingElement::make_raw(T, a);
556 }
557#if 0
558 P = newRing->cast_to_PolynomialRing();
559 T = F->get_ring()->cast_to_Tower();
560 if (P != 0 && T != 0)
561 {
562 ring_elem a = T->translateFromTower(P, F->get_value());
563 return RingElement::make_raw(P, a);
564 }
565#endif
566 ERROR("expected an element of a TowerRing or a PolynomialRing");
567 return nullptr;
568}
569
570// Local Variables:
571// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
572// indent-tabs-mode: nil
573// End:
Variable-length sparse (variable, exponent) encoding of monomials.
exponents::ConstExponents const_exponents
exponents::Exponents exponents_t
const DPoly * D
Definition dpoly.hpp:464
void traverse(const TowerPolynomial f)
Definition dpoly.cpp:1564
DPolyTraverser(const DRing *D0)
Definition dpoly.hpp:472
long P
Definition dpoly.hpp:269
static DRing * create(long p, int nvars0, const TowerPolynomial *ext0)
Definition dpoly.cpp:1494
int level
Definition dpoly.hpp:267
DPoly D
Definition dpoly.hpp:268
static void from_expvector(int n, exponents::ConstExponents a, Vector &result)
void to_expvector(const_monomial m, exponents_t result_exp) const
Definition monoid.cpp:747
Engine-side commutative monomial monoid: variable names, ordering, multidegree machinery,...
Definition monoid.hpp:89
virtual ring_elem var(int v) const =0
virtual const Monoid * getMonoid() const
Definition polyring.hpp:282
virtual const Ring * getCoefficients() const
Definition polyring.hpp:277
int n_vars() const
Definition polyring.hpp:196
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual std::pair< bool, long > coerceToLongInteger(ring_elem a) const
Definition ring.cpp:236
virtual ring_elem add(const ring_elem f, const ring_elem g) const =0
ring_elem minus_oneV
Definition ring.hpp:131
void initialize_ring(long charac, const PolynomialRing *DR=nullptr, const std::vector< int > &heft_vec={})
Definition ring.cpp:30
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
bool declare_field()
Definition ring.cpp:69
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 ring.cpp:109
virtual ring_elem mult(const ring_elem f, const ring_elem g) const =0
ring_elem zeroV
Definition ring.hpp:129
Ring()
Definition ring.hpp:136
virtual const Tower * cast_to_Tower() const
Definition ring.hpp:241
ring_elem get_value() const
Definition relem.hpp:79
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
const Ring * get_ring() const
Definition relem.hpp:81
Front-end-visible "ring element" value: an engine ring_elem paired with the Ring* that gives it meani...
Definition relem.hpp:67
xxx xxx xxx
Definition ring.hpp:102
Engine-side ring homomorphism: stores, for each source-ring variable, the target-ring element it maps...
Definition ringmap.hpp:60
Abstract incremental accumulator that builds a ring_elem from many add(f) calls.
Definition ring.hpp:669
ring_elem gcd(const ring_elem f, const ring_elem g) const
Definition tower.cpp:365
ring_elem lowerP(const ring_elem f) const
Definition tower.cpp:419
virtual ring_elem invert(const ring_elem f) const
Definition tower.cpp:217
ring_elem differentiate(int var, const ring_elem f) const
Definition tower.cpp:394
ring_elem power_mod(const ring_elem f, mpz_srcptr n, const ring_elem g) const
Definition tower.cpp:408
Tower()
Definition tower.hpp:69
ring_elem translate(const PolynomialRing *R, ring_elem fR) const
Definition tower.cpp:471
virtual void text_out(buffer &o) const
Definition tower.cpp:76
virtual ring_elem copy(const ring_elem f) const
Definition tower.cpp:165
virtual unsigned int computeHashValue(const ring_elem a) const
Definition tower.cpp:69
virtual bool is_equal(const ring_elem f, const ring_elem g) const
Definition tower.cpp:149
virtual bool lift(const Ring *R, const ring_elem f, ring_elem &result) const
Definition tower.cpp:344
virtual int index_of_var(const ring_elem a) const
Definition tower.cpp:85
virtual ring_elem from_int(mpz_srcptr n) const
Definition tower.cpp:113
virtual ring_elem subtract(const ring_elem f, const ring_elem g) const
Definition tower.cpp:197
virtual bool is_zero(const ring_elem f) const
Definition tower.cpp:142
virtual M2_arrayint support(const ring_elem a) const
Definition tower.cpp:91
DRing * D
Definition tower.hpp:66
virtual ring_elem negate(const ring_elem f) const
Definition tower.cpp:176
int degreeInVariable(int var, const ring_elem f) const
Definition tower.cpp:388
int level
Definition tower.hpp:61
virtual void remove(ring_elem &f) const
Definition tower.cpp:171
virtual bool from_rational(mpq_srcptr q, ring_elem &result) const
Definition tower.cpp:120
virtual ring_elem mult(const ring_elem f, const ring_elem g) const
Definition tower.cpp:207
virtual ring_elem random() const
Definition tower.cpp:246
virtual ring_elem remainder(const ring_elem f, const ring_elem g) const
Definition tower.cpp:236
bool initialize(long charac0, M2_ArrayString names0, const VECTOR(ring_elem) &extensions)
Definition tower.cpp:15
int nvars
Definition tower.hpp:62
virtual ring_elem from_long(long n) const
Definition tower.cpp:106
virtual ~Tower()
Definition tower.cpp:14
M2_ArrayString names
Definition tower.hpp:64
static Tower * create(int charac, M2_ArrayString names)
Definition tower.cpp:46
virtual ring_elem var(int v) const
Definition tower.cpp:128
virtual int compare_elems(const ring_elem f, const ring_elem g) const
Definition tower.cpp:157
virtual bool promote(const Ring *R, const ring_elem f, ring_elem &result) const
Definition tower.cpp:335
virtual void syzygy(const ring_elem a, const ring_elem b, ring_elem &x, ring_elem &y) const
Definition tower.cpp:353
virtual ring_elem add(const ring_elem f, const ring_elem g) const
Definition tower.cpp:187
virtual ring_elem divide(const ring_elem f, const ring_elem g) const
Definition tower.cpp:226
virtual bool is_unit(const ring_elem f) const
Definition tower.cpp:135
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 tower.cpp:254
int extension_degree(int nvars) const
Definition tower.cpp:402
virtual ring_elem eval(const RingMap *map, const ring_elem f, int first_var) const
Definition tower.cpp:327
friend class TowerEvaluator
Definition tower.hpp:60
ring_elem gcd_extended(const ring_elem f, const ring_elem g, ring_elem &u, ring_elem &v) const
Definition tower.cpp:374
virtual bool viewTerm(long coeff, const_exponents exp)
Definition tower.cpp:288
gc_vector< int > vp
Definition tower.cpp:285
const Ring * K
Definition tower.cpp:279
TowerEvaluator(const Tower *T, const RingMap *map0, const ring_elem f0, int first_var0)
Definition tower.cpp:303
SumCollector * H
Definition tower.cpp:280
const RingMap * map
Definition tower.cpp:278
virtual ~TowerEvaluator()
Definition tower.cpp:319
const Ring * target
Definition tower.cpp:284
TowerPolynomial f
Definition tower.cpp:282
ring_elem getValue()
Definition tower.cpp:320
Ring subclass for tower polynomial rings (Z/p)[x_0][x_1]...[x_{n-1}] modulo a chain of algebraic exte...
Definition tower.hpp:59
Native univariate polynomial arithmetic over QQ extensions and finite fields.
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
M2_arrayint M2_makearrayint(int n)
Definition m2-types.cpp:6
Monoid — variable count, naming, grading, and monomial order of a polynomial ring.
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
volatile int x
PolynomialRing — abstract polynomial-ring base, the engine's most-reused class.
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
tbb::flow::graph G
Ring — the legacy abstract base class for every coefficient and polynomial ring.
#define TOWER_RINGELEM(a)
Definition ringelem.hpp:214
RingMap — engine representation of a ring homomorphism.
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
#define T
Definition table.c:13
const RingElement * towerExtendedGCD(const RingElement *F, const RingElement *G, const RingElement **A, const RingElement **B)
Definition tower.cpp:446
const RingElement * towerGCD(const RingElement *F, const RingElement *G)
Definition tower.cpp:433
const RingElement * rawTowerTranslatePoly(const Ring *newRing, const RingElement *F)
Definition tower.cpp:534
#define TOWER_POLYNOMIAL_VAL(f)
Definition tower.cpp:12
Legacy Tower — Ring-derived iterated extension of Z/p (pre-aring).