Macaulay2 Engine
Loading...
Searching...
No Matches
aring-tower.hpp
Go to the documentation of this file.
1// Copyright 2010-2012 Michael E. Stillman.
2#ifndef _aring_tower_hpp_
3#define _aring_tower_hpp_
4
42
43#include <vector>
44#include <string>
45
46#include "ExponentVector.hpp"
47#include "aring-zzp-ffpack.hpp"
48#include "style.hpp"
49#include "aring.hpp"
50#include "ringelem.hpp"
51
52class RingMap;
53
54namespace M2 {
59
77{
78 int deg;
79 int len;
80 union
81 {
83 // long* ints; // array of integers. at level == 0
84 ARingPolynomial *polys; // array of more ptrs to poly structs, at level > 0
85 };
86};
87
88class DRing;
89
90// TODO: make this a template type, with the base e.g. ZZ/p, ZZ, QQ, etc.
110{
112
113 public:
116
125 class Element : public ElementImpl<ElementType>
126 {
127 public:
128 Element() = delete;
129 Element(Element &&other) : ElementImpl(other), R(other.R)
130 {
131 other.mValue = NULL;
132 } // move constructor only,
133 explicit Element(const ARingTower &_R)
134 : ElementImpl(static_cast<ElementType>(nullptr)), R(_R)
135 {
136 }
138 : R(_R)
139 {
140 R.init_set(mValue,value);
141 }
143 {
144 if (mValue) R.clear(mValue);
145 }
146
147 private:
148 const ARingTower &R;
149 };
150
163 {
164 const ARingTower &R;
165 const int mSize;
166 const std::unique_ptr<ElementType[]> mData;
167
168 public:
169 ElementArray(const ARingTower &_R, size_t size)
170 : R(_R), mSize(size), mData(new ElementType[size])
171 {
172 for (size_t i = 0; i < mSize; i++) mData[i] = nullptr;
173 }
175 {
176 for (size_t i = 0; i < mSize; i++) R.clear(mData[i]);
177 }
178 ElementType &operator[](size_t idx) { return mData[idx]; }
179 const ElementType &operator[](size_t idx) const { return mData[idx]; }
180 ElementType *data() { return mData.get(); }
181 const ElementType *data() const { return mData.get(); }
182 };
183
185
187 // Creation and destruction //
189
191 const std::vector<std::string> &names,
192 const std::vector<ElementType> &extensions);
193
194 virtual ~ARingTower();
195
196 // TODO: the interface for these three need to change
197 static ARingTower *create(const BaseRingType &baseRing,
198 const std::vector<std::string> &names);
199 static ARingTower *create(const ARingTower &R,
200 const std::vector<std::string> &new_names);
201 static ARingTower *create(const ARingTower &R,
202 const std::vector<ElementType> &extensions);
203
204 size_t n_vars() const { return mNumVars; }
205 const ARingZZpFFPACK &baseRing() const { return mBaseRing; }
206 const std::vector<std::string> &varNames() const { return mVarNames; }
207 unsigned long characteristic() const { return mBaseRing.characteristic(); }
209 // The following are he routines required to be of type "RingInterface"
211
212 unsigned int computeHashValue(const elem &a) const { return a->deg; }
213 void text_out(buffer &o) const;
214
216 // Routines to help in switch from coeffrings to aring //
217 // these will be renamed or go away (hopefully) /////////
219 void init_set(elem &result, elem a) const // TODO: write this
220 {
221 (void) result;
222 (void) a;
223 }
224
225 void set(elem &result, elem a) const // TODO: write this
226 {
227 (void) result;
228 (void) a;
229 }
230
232 // ElementType informational ////
234
235 bool is_unit(ElementType f) const // TODO: write this
236 {
237 (void) f;
238 return false;
239 }
240
241 bool is_zero(ElementType f) const { return f == nullptr; }
243 {
244 return is_equal(mStartLevel, f, g);
245 }
246
248 {
249 // TODO: write this
250 (void) f;
251 (void) g;
252 return 0;
253 }
254
256 // to/from ringelem ////////
258 // These simply repackage the element as either a ringelem or an
259 // 'ElementType'.
260 // No reinitialization is done.
261 // Do not take the same element and store it as two different ring_elem's!!
263 {
264 ElementType b = const_cast<ElementType>(a);
265 result.poly_val = reinterpret_cast<Nterm *>(b);
266 }
267
269 {
270 Nterm *b = const_cast<Nterm *>(a.poly_val);
271 result = reinterpret_cast<ElementType>(b);
272 }
273
274 // There's a strong argument that ElementType shouldn't be a pointer type
275 // it makes this function not particularly safe
277 {
278 return reinterpret_cast<ElementType>(a.poly_val);
279 }
280
281 // 'init', 'init_set' functions
282
283 void init(elem &result) const { result = nullptr; }
284 void clear(elem &f) const { clear(mStartLevel, f); }
285 void set_zero(elem &result) const { result = nullptr; }
286 void copy(elem &result, elem a) const { result = copy(mStartLevel, a); }
287 void set_from_long(elem &result, long a) const
288 { // TODO: write this
289 (void) result;
290 (void) a;
291 }
292
293 // v from 0..n_vars()-1, sets result to 0 if v is out of range
294 void set_var(elem &result, int v) const { result = var(mStartLevel, v); }
295 void set_from_mpz(elem &result, mpz_srcptr a) const
296 {
297 (void) result;
298 (void) a;
299 assert(false);
300 } // TODO: write this
301
302 bool set_from_mpq(elem &result, mpq_srcptr a) const
303 {
304 (void) result;
305 (void) a;
306 assert(false);
307 return false;
308 } // TODO: write this
309
311 {
312 (void) result;
313 (void) a;
314 return false;
315 }
316
317 // arithmetic
318 void negate(elem &result, elem a) const
319 {
320 result = copy(mStartLevel, a);
322 }
323
324 // we silently assume that a != 0. If it is, result is set to a^0, i.e. 1
325 void invert(elem &result, elem a) const // TODO: write this
326 {
327 (void) result;
328 (void) a;
329 }
330
331 void add(elem &result, elem a, elem b) const
332 {
333 if (a == nullptr)
334 result = b;
335 else if (b == nullptr)
336 result = a;
337 else
338 {
341 result = a1;
342 }
343 } // TODO: should b be consumed?
344
345 void subtract(elem &result, elem a, elem b) const
346 {
347 result = copy(mStartLevel, a);
349 } // TODO: write this
350
351 void subtract_multiple(elem &result, elem a, elem b) const // TODO: write this
352 {
353 (void) result;
354 (void) a;
355 (void) b;
356 }
357
358 void mult(elem &result, elem a, elem b) const // TODO: write this
359 {
360 (void) result;
361 (void) a;
362 (void) b;
363 }
364
365 void divide(elem &result, elem a, elem b) const // TODO: write this
366 {
367 (void) result;
368 (void) a;
369 (void) b;
370 }
371
372 void power(elem &result, elem a, int n) const // TODO: write this
373 {
374 (void) result;
375 (void) a;
376 (void) n;
377 }
378
379 void power_mpz(elem &result, elem a, mpz_srcptr n) const // TODO: write this
380 {
381 (void) result;
382 (void) a;
383 (void) n;
384 }
385
386 void swap(ElementType &a, ElementType &b) const // TODO: write this
387 {
388 (void) a;
389 (void) b;
390 }
391
393 ElementType a,
394 bool p_one = true,
395 bool p_plus = false,
396 bool p_parens = false) const
397 {
398 elem_text_out(o, mStartLevel, a, p_one, p_plus, p_parens);
399 }
400
401 // returns x,y s.y. x*a + y*b == 0.
402 // if possible, x is set to 1.
403 // no need to consider the case a==0 or b==0.
405 ElementType b,
406 ElementType &x,
407 ElementType &y) const
408 {
409 (void) a;
410 (void) b;
411 (void) x;
412 (void) y;
413 } // TODO: write this
414
415 void random(ElementType &result) const // TODO: write this
416 {
417 (void) result;
418 }
419
420 void eval(const RingMap *map,
421 const elem f,
422 int first_var,
423 ring_elem &result) const
424 {
425 (void) map;
426 (void) f;
427 (void) first_var;
428 (void) result;
429 } // TODO: write this
430
431 // f *= b, where b is an element in mBaseRing
432 void mult_by_coeff(ARingPolynomial &f, const BaseCoefficientType &b) const;
433
434 private:
435 void extensions_text_out(buffer &o) const; // TODO: write this
436
437 void elem_text_out(buffer &o,
438 int level,
439 const ElementType f,
440 bool p_one,
441 bool p_plus,
442 bool p_parens) const;
443
444 private:
445 bool is_one(int level, const ARingPolynomial f) const; // TODO: write this
446 bool is_equal(int level, const ARingPolynomial f, const ARingPolynomial g) const;
447
448 ARingPolynomial alloc_poly_n(int deg) const;
449 ARingPolynomial alloc_poly_0(int deg) const;
450 void dealloc_poly(ARingPolynomial &f) const;
451
452 ARingPolynomial copy(int level, const ARingPolynomial f) const;
453
454 // possibly increase the capacity of 'f', to accommodate polynomials of degree
455 // 'newdeg'
456 void increase_capacity(int newdeg, ARingPolynomial &f) const;
457
458 // sets the (top level) degree of f to be correct. If f is the 0 poly, then f
459 // is deallocated
460 void reset_degree(ARingPolynomial &f) const;
461
462 // Create a polynomial at level 'level', representing the variable 'v'
463 // v should be in the range 0..mNumVars-1. If not, then the 0 elem is
464 // returned.
465 // ASSUMPTION: level >= v. If not, 0 is returned.
466 ARingPolynomial var(int level, int v) const;
467
468 // f += g. f and g should both be of level 'level'
469 void add_in_place(int level, ARingPolynomial &f, const ARingPolynomial g) const;
470
471 void subtract_in_place(int level, ARingPolynomial &f, const ARingPolynomial g) const;
472
473 void negate_in_place(int level, ARingPolynomial &f) const;
474
475 void mult_by_coeff(int level, ARingPolynomial &f, const BaseCoefficientType &b) const;
476
477 // free all space associated to f, set f to 0.
478 void clear(int level, ARingPolynomial &f) const;
479
480 private:
484
485 const std::vector<std::string> mVarNames;
486 std::vector<ElementType> mExtensions;
487};
488
489}; // M2 namespace
490
491#endif
492
493#if 0
494 public:
495 bool is_unit(ElementType f) const;
496 bool is_zero(ElementType f) const { return f == 0; }
497 bool is_equal(ElementType f, ElementType g) const { return mRing.is_equal(mStartLevel, f, g); }
498 int compare_elems(ElementType f, ElementType g) const { return mRing.compare(mStartLevel, f, g); }
499
500 //TODO: NO! this should be a copy!!
501 void init_set(ElementType &result, ElementType a) const { result = a; }
502
503 //TODO: NO! this should be a copy!!
504 void set(ElementType &result, ElementType a) const { mRing.remove(mStartLevel, result); result = a; }
505
506 //TODO: should this remove previous value??
507 void set_zero(ElementType &result) const { result = 0; }
508
509
510 void set_from_long(ElementType &result, long r) {
511 r = r % mCharacteristic;
512 if (r < 0) r += P;
513 result = mRing.from_long(mStartLevel, r);
514 }
515
516 void set_from_int(ElementType &result, mpz_ptr r);
517
518 bool set_from_mpq(ElementType &result, mpq_srcptr r);
519
520 void set_random(ElementType &result) { result = mRing.random(mStartLevel); }
521
522 bool invert(ElementType &result, ElementType a) const
523 // returns true if invertible. Returns false if not, and then result is set to 0.
524 {
525 result = mRing.invert(mStartLevel, a);
526 return result != 0;
527 }
528
529 void add(ElementType &result, ElementType a, ElementType b) const
530 {
531 if (a == 0) result = b;
532 else if (b == 0) result = a;
533 else
534 {
535 ElementType a1 = mRing.copy(mStartLevel, a);
536 mRing.add_in_place(mStartLevel, a1, b);
537 result = a1;
538 }
539 }
540
541 void subtract(ElementType &result, ElementType a, ElementType b) const
542 {
543 ElementType a1 = mRing.copy(mStartLevel, a);
544 mRing.subtract_in_place(mStartLevel, a1, b);
545 result = a1;
546 }
547
548 void subtract_multiple(ElementType &result, ElementType a, ElementType b) const
549 {
550 if (a == 0 || b == 0) return;
551 ElementType ab = mRing.mult(mStartLevel,a,b,true);
552 mRing.subtract_in_place(mStartLevel, result, ab);
553 }
554
555 void mult(ElementType &result, ElementType a, ElementType b) const
556 {
557 if (a == 0 || b == 0)
558 result = 0;
559 else
560 result = mRing.mult(mStartLevel, a, b, true);
561 }
562
563 void divide(ElementType &result, ElementType a, ElementType b) const
564 {
565 if (a == 0 || b == 0)
566 result = 0;
567 else
568 {
569 ElementType a1 = mRing.copy(mStartLevel, a);
570 if (!mRing.division_in_place(mStartLevel, a1, b, result))
571 result = 0;
572 mRing.dealloc_poly(a1);
573 }
574 }
575
576 void remainder(ElementType &result, ElementType a, ElementType b) const
577 {
578 if (a == 0 || b == 0)
579 result = 0;
580 else
581 {
582 result = mRing.copy(mStartLevel, a);
583 mRing.remainder(mStartLevel, result, b);
584 }
585 }
586
587 void to_ring_elem(ring_elem &result, const ElementType a) const
588 {
589 ElementType h = mRing.copy(mStartLevel, a);
591 }
592
593 void from_ring_elem(ElementType &result, const ring_elem &a) const
594 {
595 ElementType a1 = reinterpret_cast<TowerPolynomial>(a.poly_val);
596 result = mRing.copy(mStartLevel, a1);
597 }
598
599 void swap(ElementType &a, ElementType &b) const
600 {
601 ElementType tmp = a;
602 a = b;
603 b = tmp;
604 }
605
606 void elem_text_out(buffer &o,
607 const ElementType f,
608 bool p_one,
609 bool p_plus,
610 bool p_parens) const;
611
612 void gcd(ElementType &result, const ElementType f, const ElementType g) { result = mRing.gcd(mStartLevel,f,g); }
613
614 void gcd_coefficients(ElementType &result_gcd,
615 ElementType &result_u, ElementType &result_v,
616 const ElementType f, const ElementType g)
617 {
618 result_gcd = mRing.gcd_coefficients(mStartLevel, f, g, result_u, result_v);
619 }
620
621
622 int degree(int var, const ElementType f) const { return mRing.degree(mStartLevel,var,f); }
623 void diff(int var, ElementType &result, const ElementType f) const { result = mRing.diff(mStartLevel, var, f); }
624 int extension_degree(int firstvar); // returns -1 if infinite
625 void power_mod(ElementType &result, const ElementType f, mpz_srcptr n, const ElementType g) const { result = mRing.power_mod(mStartLevel, f, n, g); } // f^n mod g
626 void lowerP(ElementType &result, const ElementType f) { result = mRing.lowerP(mStartLevel, f); }
627
628 private:
629 void extensions_text_out(buffer &o) const;
630
632 // Predicates ///////////////////////
634 bool is_equal(int level, const ARingPolynomial f, const ARingPolynomial g);
635 bool is_zero(ARingPolynomial f) { return f == 0; }
636
638 // Construction of new elements /////
640
641 ARingPolynomial copy(int level, const_poly f);
642 ARingPolynomial var(int level, int v); // make the variable v (but at level 'level')
643 ARingPolynomial from_long(int level, long c); // c should be reduced mod p
644
646 // Private routines for arithmetic //
648 void reset_degree_0(ARingPolynomial &f); // possibly sets f to 0
649 void reset_degree_n(int level, ARingPolynomial &f); // ditto
650
651 void mult_by_coeff_0(ARingPolynomial &f, long b);
652 void mult_by_coeff_n(int level, ARingPolynomial &f, ARingPolynomial b);
653 // f *= b. b should have level 'level-1'.
654
655 void make_monic_0(ARingPolynomial & f, long &result_multiplier);
656 void make_monic_n(int level, ARingPolynomial & f, ARingPolynomial &result_multiplier);
657
658 bool make_monic3(int level, ARingPolynomial & u1, ARingPolynomial &u2, ARingPolynomial &u3);
659
660
661 void add_in_place_0(ARingPolynomial &f, const ARingPolynomial g);
662 void add_in_place_n(int level, ARingPolynomial &f, const ARingPolynomial g);
663 void add_in_place(int level, ARingPolynomial &f, const ARingPolynomial g);
664
665 void subtract_in_place_0(ARingPolynomial &f, const ARingPolynomial g);
666 void subtract_in_place_n(int level, ARingPolynomial &f, const ARingPolynomial g);
667 void subtract_in_place(int level, ARingPolynomial &f, const ARingPolynomial g);
668
669 ARingPolynomial mult_0(const ARingPolynomial f, const ARingPolynomial g, bool reduce_by_extension);
670 ARingPolynomial mult_n(int level, const ARingPolynomial f, const ARingPolynomial g, bool reduce_by_extension);
671 ARingPolynomial mult(int level, const ARingPolynomial f, const ARingPolynomial g, bool reduce_by_extension);
672
673 ARingPolynomial random_0(int deg);
674 ARingPolynomial random_n(int level, int deg);
675 ARingPolynomial random(int level, int deg);
676 ARingPolynomial random(int level); // obtains a random element, using only variables which are algebraic over the base
677
678 ARingPolynomial diff_0(const ARingPolynomial f);
679 ARingPolynomial diff_n(int level, int whichvar, const ARingPolynomial f);
680
681 ARingPolynomial mult_by_int_0(long c, const ARingPolynomial f);
682 ARingPolynomial mult_by_int_n(int level, long c, const ARingPolynomial f);
683 ARingPolynomial mult_by_int(int level, long c, const ARingPolynomial f);
684
686 // Translation to/from other rings //
688 void add_term(int level, ARingPolynomial &result, long coeff, exponents_t exp) const; // modifies result.
689#endif
690
691// Local Variables:
692// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
693// indent-tabs-mode: nil
694// End:
exponents::Exponents exponents_t
Dense exponent-vector template [e_0, ..., e_{nvars-1}] for monomial operations.
M2::ARingZZpFFPACK — Z/p via FFLAS-FFPACK's Givaro::Modular<double> field.
Shared base of the aring framework (namespace M2) that unifies the engine's coefficient rings.
Single-level view of a tower-polynomial ring: a DPoly plus a fixed working level and a Tower-flavoure...
Definition dpoly.hpp:266
Element(Element &&other)
Element(const ARingTower &_R, const ElementType &value)
Element(const ARingTower &_R)
const ARingTower & R
ElementType & operator[](size_t idx)
const std::unique_ptr< ElementType[]> mData
ElementArray(const ARingTower &_R, size_t size)
const ElementType & operator[](size_t idx) const
const ElementType * data() const
ElementType elem
void text_out(buffer &o) const
ARingPolynomial ElementType
bool is_unit(ElementType f) const
void power_mpz(elem &result, elem a, mpz_srcptr n) const
void invert(elem &result, elem a) const
void divide(elem &result, elem a, elem b) const
ARingTower(const BaseRingType &baseRing, const std::vector< std::string > &names, const std::vector< ElementType > &extensions)
bool set_from_mpq(elem &result, mpq_srcptr a) const
void copy(elem &result, elem a) const
void swap(ElementType &a, ElementType &b) const
void set_from_long(elem &result, long a) const
void dealloc_poly(ARingPolynomial &f) const
static const RingID ringID
void reset_degree(ARingPolynomial &f) const
const ARingZZpFFPACK & baseRing() const
size_t n_vars() const
void to_ring_elem(ring_elem &result, const ElementType &a) const
void increase_capacity(int newdeg, ARingPolynomial &f) const
void syzygy(ElementType a, ElementType b, ElementType &x, ElementType &y) const
const std::vector< std::string > mVarNames
void set(elem &result, elem a) const
void eval(const RingMap *map, const elem f, int first_var, ring_elem &result) const
ARingZZpFFPACK BaseRingType
bool is_zero(ElementType f) const
ARingPolynomial alloc_poly_n(int deg) const
bool set_from_BigReal(elem &result, gmp_RR a) const
std::vector< ElementType > mExtensions
void subtract(elem &result, elem a, elem b) const
int compare_elems(ElementType f, ElementType g) const
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(elem &result, elem a) const
void negate_in_place(int level, ARingPolynomial &f) const
virtual ~ARingTower()
void mult(elem &result, elem a, elem b) const
void set_from_mpz(elem &result, mpz_srcptr a) const
void power(elem &result, elem a, int n) const
void clear(elem &f) const
bool is_one(int level, const ARingPolynomial f) const
void subtract_multiple(elem &result, elem a, elem b) const
ElementType from_ring_elem_const(const ring_elem &a) const
void from_ring_elem(ElementType &result, const ring_elem &a) const
void random(ElementType &result) const
void add_in_place(int level, ARingPolynomial &f, const ARingPolynomial g) const
const ARingZZpFFPACK & mBaseRing
friend class ARingTowerEvaluator
void add(elem &result, elem a, elem b) const
static ARingTower * create(const BaseRingType &baseRing, const std::vector< std::string > &names)
unsigned int computeHashValue(const elem &a) const
void elem_text_out(buffer &o, ElementType a, bool p_one=true, bool p_plus=false, bool p_parens=false) const
void set_var(elem &result, int v) const
unsigned long characteristic() const
void init_set(elem &result, elem a) const
ARingPolynomial var(int level, int v) const
void subtract_in_place(int level, ARingPolynomial &f, const ARingPolynomial g) const
void set_zero(elem &result) const
void extensions_text_out(buffer &o) const
void init(elem &result) const
FieldType::Element ElementType
wrapper for the FFPACK::ModularBalanced<double> field implementation
const ElementType & value() const
Definition aring.hpp:132
ElementImpl()=default
ElementType mValue
Definition aring.hpp:119
Engine-side ring homomorphism: stores, for each source-ring variable, the target-ring element it maps...
Definition ringmap.hpp:60
void subtract(int &result, int a, int b)
void subtract_multiple(int &result, int a, int b)
struct ARingPolynomialStruct * ARingPolynomial
RingID
Definition aring.hpp:75
@ ring_tower_ZZp
Definition aring.hpp:93
VALGRIND_MAKE_MEM_DEFINED & result(result)
mpfr_srcptr gmp_RR
Definition m2-types.h:148
#define swap(a, b, t)
Definition monsort.hpp:127
Definition aring-CC.cpp:3
void set(DMat< RT > &A, MatrixWindow wA, const DMat< RT > &B, MatrixWindow wB)
void mult(const DMatZZpFFPACK &A, const DMatZZpFFPACK &B, DMatZZpFFPACK &C)
Definition dmat.cpp:72
const mpreal remainder(const mpreal &x, const mpreal &y, mp_rnd_t rnd_mode=mpreal::get_default_rnd())
Definition mpreal.h:2504
const mpreal random(unsigned int seed=0)
Definition mpreal.h:2858
volatile int x
#define TOWER_RINGELEM(a)
Definition ringelem.hpp:214
ring_elem — the universal value type carried by every Ring* in the engine.
ARingPolynomial * polys
ARingZZpFFPACK::ElementType * coeffs
Heap-allocated node of an ARingTower polynomial: a dense degree-indexed coefficient array that recurs...
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
Engine-wide stylistic constants: LT / EQ / GT codes, INTSIZE, GEOHEAP_SIZE.
Nterm * poly_val
Definition ringelem.hpp:86