Macaulay2 Engine
Loading...
Searching...
No Matches
aring-tower.cpp
Go to the documentation of this file.
1// Copyright 2012 Michael E. Stillman
2
3#include "aring-tower.hpp"
4
5namespace M2 {
6
8{
9 // TODO: write me.
10 // needs to free the extension polynomials
11}
12
13// The main construction routine for tower rings
14// (1) names[i] is the name of the i-th variable, used solely for display.
15// (2) extensions is a std vector of length <= #variables (size of names
16// array).
17// The i-th element is a polynomial of level i (- <= i < mNumVars
18// (which allows NULL as a value too)
20 const std::vector<std::string> &names,
21 const std::vector<ElementType> &extensions)
23{
24 assert(names.size() >= 1);
25 mNumVars = static_cast<int>(names.size());
27
28 // Now copy all of the extension polynomials
29 assert(extensions.size() <= names.size());
30 for (size_t i = 0; i < names.size(); i++)
31 {
32 if (extensions.size() < i)
33 {
34 // mExtensions.push_back(mRing.copy(i, extensions[i]));
35 }
36 else
37 mExtensions.push_back(static_cast<ElementType>(nullptr));
38 }
39}
40
42 const std::vector<std::string> &names)
43{
44 std::vector<ElementType> extensions;
45 return new ARingTower(baseRing, names, extensions);
46}
47
49 const std::vector<std::string> &new_names)
50{
51 // TODO: write
52 (void) R;
53 (void) new_names;
54 return nullptr;
55}
56
58 const std::vector<ElementType> &extensions)
59{
60 // TODO: check that 'extensions' has the correct form for R.
61 // if not: throw an exception
62 // else:
63 return new ARingTower(R.baseRing(), R.varNames(), extensions);
64}
65
67// Allocation /////
69// TODO: what is the contract here???!!
71// if elems == 0, then set all coeffs to 0.
72{
74 result->polys = new ARingPolynomial[deg + 1];
75 result->deg = deg;
76 result->len = deg + 1;
77 for (int i = 0; i <= deg; i++) result->polys[i] = nullptr;
78 return result;
79}
80
82{
84 result->coeffs = new ARingZZpFFPACK::ElementType[deg + 1];
85 result->deg = deg;
86 result->len = deg + 1;
87 for (int i = 0; i <= deg; i++) result->coeffs[i] = 0;
88 return result;
89}
90
92// only f is freed, not any pointers in the array of f
93{
94 if (f == nullptr) return;
95 delete[] f->polys;
96 delete f;
97 f = nullptr;
98}
99
100void ARingTower::clear(int level, ARingPolynomial &f) const
101// free all space associated to f, set f to 0.
102{
103 if (f == nullptr) return;
104 if (level == 0)
105 {
106 for (int i = 0; i <= f->deg; i++) mBaseRing.clear(f->coeffs[i]);
107 delete[] f->coeffs;
108 }
109 else
110 {
111 for (int i = 0; i <= f->deg; i++) clear(level - 1, f->polys[i]);
112 delete[] f->polys;
113 }
114 delete f;
115 f = nullptr;
116}
117
119{
120 if (f == nullptr) return;
121 int fdeg = f->deg;
122 for (int j = fdeg; j >= 0; --j)
123 if (f->polys[j] != nullptr)
124 {
125 f->deg = j;
126 return;
127 }
128 // at this point, everything is 0!
129 dealloc_poly(f); // sets f to 0
130}
131
133{
134 if (f == nullptr) return nullptr;
136 if (level == 0)
137 for (int i = 0; i <= f->deg; i++) result->coeffs[i] = f->coeffs[i];
138 else
139 for (int i = 0; i <= f->deg; i++)
140 result->polys[i] = copy(level - 1, f->polys[i]);
141 return result;
142}
143
144// TODO: should increase_capacity set the degree?? I don't think so...
146{
147 assert(f != 0);
148 if (f->len <= newdeg)
149 {
150 ARingPolynomial *newelems = newarray(ARingPolynomial, newdeg + 1);
151 ARingPolynomial *fp = f->polys;
152 for (int i = 0; i <= f->deg; i++) newelems[i] = fp[i];
153 for (int i = f->deg + 1; i < newdeg + 1; i++) newelems[i] = nullptr;
154 delete[] fp;
155 f->polys = newelems;
156 f->len = newdeg + 1;
157 f->deg = newdeg;
158 }
159}
160
162// Display ////////
164
166{
167 o << "Tower[ZZ/" << characteristic() << "[";
168 for (size_t i = 0; i < n_vars() - 1; i++) o << varNames()[i] << ",";
169 if (n_vars() > 0) o << varNames()[n_vars() - 1];
170 o << "]]";
172}
173
175{
176 for (int i = 0; i < mExtensions.size(); i++)
177 {
178 if (mExtensions[i] != nullptr)
179 {
180 o << newline << " ";
181 elem_text_out(o, i, mExtensions[i], true, false, false);
182 }
183 }
184}
185
186namespace {
187 int n_nonzero_terms(int level, ARingPolynomial f)
188 {
189 if (f == nullptr) return 0;
190 int nterms = 0;
191 if (level == 0)
192 {
193 for (int i = 0; i <= f->deg; i++)
194 if (f->coeffs[i] != 0) nterms++;
195 }
196 else
197 {
198 for (int i = 0; i <= f->deg; i++)
199 if (f->polys[i] != nullptr) nterms++;
200 }
201 return nterms;
202 }
203};
204
205bool ARingTower::is_one(int level, const ARingPolynomial f) const
206{
207 if (f == nullptr) return false;
208 if (f->deg != 0) return false;
209 if (level == 0)
210 return 1 == f->coeffs[0];
211 else
212 return is_one(level - 1, f->polys[0]);
213}
214
216 int level,
217 const ARingPolynomial f,
218 bool p_one,
219 bool p_plus,
220 bool p_parens) const
221{
222 // o << to_string(level, f);
223 if (f == nullptr)
224 {
225 o << "0";
226 return;
227 }
228
229 int nterms = n_nonzero_terms(level, f);
230 bool needs_parens = p_parens && (nterms >= 2);
231
232 if (needs_parens)
233 {
234 if (p_plus) o << '+';
235 o << '(';
236 p_plus = false;
237 }
238
239 bool one = is_one(level, f);
240
241 if (one)
242 {
243 if (p_plus) o << "+";
244 if (p_one) o << "1";
245 return;
246 }
247
248 const std::string &this_varname = varNames()[level];
249
250 if (level == 0)
251 {
252 bool firstterm = true;
253 for (int i = f->deg; i >= 0; i--)
254 if (f->coeffs[i] != 0)
255 {
256 if (!firstterm || p_plus) o << "+";
257 firstterm = false;
258 if (i == 0 || f->coeffs[i] != 1)
259 mBaseRing.elem_text_out(o, f->coeffs[i], p_one, p_plus, p_parens);
260 if (i > 0) o << this_varname;
261 if (i > 1) o << i;
262 }
263 if (needs_parens) o << ")";
264 }
265 else
266 {
267 bool firstterm = true;
268 for (int i = f->deg; i >= 0; i--)
269 if (f->polys[i] != nullptr)
270 {
271 bool this_p_parens = p_parens || (i > 0);
272
273 if (i == 0 || !is_one(level - 1, f->polys[i]))
275 level - 1,
276 f->polys[i],
277 p_one,
278 p_plus || !firstterm,
279 this_p_parens);
280 else if (p_plus || !firstterm)
281 o << "+";
282 if (i > 0) o << this_varname;
283 if (i > 1) o << i;
284
285 firstterm = false;
286 }
287 if (needs_parens) o << ")";
288 }
289}
290
291ARingPolynomial ARingTower::var(int level, int v) const
292// make the variable v (but at level 'level')
293{
294 if (v > level) return nullptr;
295 int which = (v == 0 ? 1 : 0);
297 alloc_poly_0(which); // TODO: check that this initializes elements to 0
298 result->coeffs[which] = 1;
299 for (int i = 1; i <= level; i++)
300 {
301 which = (i == v ? 1 : 0);
303 result = alloc_poly_n(which);
304 result->polys[which] = a;
305 }
306 return result;
307}
308
309bool ARingTower::is_equal(int level, const ARingPolynomial f, const ARingPolynomial g) const
310{
311 if (f == nullptr)
312 {
313 if (g == nullptr) return true;
314 return false;
315 }
316 if (g == nullptr || f->deg != g->deg) return false;
317 if (level == 0)
318 {
321 for (int i = 0; i <= f->deg; i++)
322 if (fp[i] != gp[i]) return false;
323 return true;
324 }
325 // level > 0
326 ARingPolynomial *fp = f->polys;
327 ARingPolynomial *gp = g->polys;
328 for (int i = 0; i <= f->deg; i++)
329 if (!is_equal(level - 1, fp[i], gp[i])) return false;
330 return true;
331}
332
334{
335 if (g == nullptr) return;
336 if (f == nullptr)
337 {
338 f = copy(level, g);
339 return;
340 }
341 int fdeg = f->deg;
342 int gdeg = g->deg;
343
344 increase_capacity(g->deg, f);
345 if (level == 0)
346 for (int i = 0; i <= gdeg; i++)
347 mBaseRing.add(f->coeffs[i], f->coeffs[i], g->coeffs[i]);
348 else
349 for (int i = 0; i <= gdeg; i++)
350 add_in_place(level - 1, f->polys[i], g->polys[i]);
351
352 if (gdeg > fdeg)
353 f->deg = gdeg;
354 else if (gdeg == fdeg)
355 reset_degree(f);
356}
357
359{
360 if (f == nullptr) return;
361 int deg = f->deg;
362 if (level == 0)
363 {
364 for (int i = 0; i <= deg; i++)
365 if (f->coeffs[i] != 0) mBaseRing.negate(f->coeffs[i], f->coeffs[i]);
366 }
367 else
368 {
369 for (int i = 0; i <= deg; i++)
370 if (f->polys[i] != nullptr) negate_in_place(level - 1, f->polys[i]);
371 }
372}
373
375{
376 if (g == nullptr) return;
377 if (f == nullptr)
378 {
379 f = copy(level, g);
380 negate_in_place(level, f);
381 return;
382 }
383 int fdeg = f->deg;
384 int gdeg = g->deg;
385
386 increase_capacity(g->deg, f);
387 if (level == 0)
388 for (int i = 0; i <= gdeg; i++)
389 mBaseRing.subtract(f->coeffs[i], f->coeffs[i], g->coeffs[i]);
390 else
391 for (int i = 0; i <= gdeg; i++)
392 subtract_in_place(level - 1, f->polys[i], g->polys[i]);
393
394 if (gdeg > fdeg)
395 f->deg = gdeg;
396 else if (gdeg == fdeg)
397 reset_degree(f);
398}
399
402 const BaseCoefficientType &b) const
403{
404 assert(!mBaseRing.is_zero(b));
405 if (f == nullptr) return;
406
407 long deg = f->deg;
408 if (level == 0)
409 {
410 for (int i = 0; i <= deg; i++)
411 if (f->coeffs[i] != 0) mBaseRing.mult(f->coeffs[i], f->coeffs[i], b);
412 }
413 else
414 {
415 for (int i = 0; i <= deg; i++)
416 if (f->polys[i] != nullptr) mult_by_coeff(level - 1, f->polys[i], b);
417 }
418}
419
421{
422 if (f == nullptr) return;
423 if (mBaseRing.is_zero(b))
424 {
425 clear(f);
426 return;
427 }
428 // TODO: add this line one is_one is implemented in ZZpFFPACK: if
429 // (mBaseRing.is_one(b)) return;
431}
432
433}; // namespace M2
434
435// Local Variables:
436// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
437// indent-tabs-mode: nil
438// End:
M2::ARingTower — iterated finite-field extension tower for very large GF(p^k).
void text_out(buffer &o) const
ARingPolynomial ElementType
ARingTower(const BaseRingType &baseRing, const std::vector< std::string > &names, const std::vector< ElementType > &extensions)
void copy(elem &result, elem a) const
void dealloc_poly(ARingPolynomial &f) const
void reset_degree(ARingPolynomial &f) const
const ARingZZpFFPACK & baseRing() const
size_t n_vars() const
void increase_capacity(int newdeg, ARingPolynomial &f) const
const std::vector< std::string > mVarNames
ARingZZpFFPACK BaseRingType
ARingPolynomial alloc_poly_n(int deg) const
std::vector< ElementType > mExtensions
bool is_equal(ElementType f, ElementType g) const
const std::vector< std::string > & varNames() const
ARingPolynomial alloc_poly_0(int deg) const
void mult_by_coeff(ARingPolynomial &f, const BaseCoefficientType &b) const
BaseRingType::ElementType BaseCoefficientType
void negate_in_place(int level, ARingPolynomial &f) const
virtual ~ARingTower()
void clear(elem &f) const
bool is_one(int level, const ARingPolynomial f) const
void add_in_place(int level, ARingPolynomial &f, const ARingPolynomial g) const
const ARingZZpFFPACK & mBaseRing
static ARingTower * create(const BaseRingType &baseRing, const std::vector< std::string > &names)
void elem_text_out(buffer &o, ElementType a, bool p_one=true, bool p_plus=false, bool p_parens=false) const
unsigned long characteristic() const
ARingPolynomial var(int level, int v) const
void subtract_in_place(int level, ARingPolynomial &f, const ARingPolynomial g) const
void extensions_text_out(buffer &o) const
FieldType::Element ElementType
wrapper for the FFPACK::ModularBalanced<double> field implementation
static int n_nonzero_terms(int level, const TowerPolynomial f)
Definition dpoly.cpp:127
struct ARingPolynomialStruct * ARingPolynomial
VALGRIND_MAKE_MEM_DEFINED & result(result)
char newline[]
Definition m2-types.cpp:49
Definition aring-CC.cpp:3
#define newarray(T, len)
Definition newdelete.hpp:82
ARingPolynomial * polys
ARingZZpFFPACK::ElementType * coeffs
Heap-allocated node of an ARingTower polynomial: a dense degree-indexed coefficient array that recurs...