Macaulay2 Engine
Loading...
Searching...
No Matches
aring-glue.hpp
Go to the documentation of this file.
1// Copyright 2011 Michael E. Stillman
2
3#ifndef _ring_glue_hh_
4#define _ring_glue_hh_
5
48
49#include "aring.hpp"
50#include "aring-translate.hpp"
51#include "ring.hpp"
52
53#include "mutablemat.hpp"
54
55static const bool displayArithmeticCalls = false;
56
57#define COERCE_RING(RingType, R) dynamic_cast<const RingType *>(R)
58
59namespace M2 {
63template <class RingType>
64class ConcreteRing : public Ring
65{
66 std::unique_ptr<RingType> R;
67
68 protected:
69 explicit ConcreteRing(std::unique_ptr<RingType> R0) : R(std::move(R0)) {}
70 virtual ~ConcreteRing() = default;
71
72 public:
73 // explicitly delete the copy constructor
74 ConcreteRing(const ConcreteRing &ring) = delete;
75 typedef typename RingType::ElementType ElementType;
76 typedef typename RingType::Element Element;
77
78 static ConcreteRing<RingType> *create(std::unique_ptr<RingType> R);
79
80 template <class... Args>
81 static ConcreteRing<RingType> *create(Args &&...args);
82
83 virtual M2::RingID ringID() const { return RingType::ringID; }
84 const RingType &ring() const { return *R; }
86 virtual MutableMatrix *makeMutableMatrix(size_t nrows,
87 size_t ncols,
88 bool dense) const
89 {
90 // JY: The use of get here on R is safe because MutableMat will always keep
91 // a reference to this so long as it has a reference to R, and this is in
92 // the gc heap, so that reference keeps R alive. Really, the MutableMat
93 // constructor should probably be calling ring(), but ring() is not virtual
94 // and not every Ring is an instance of ConcreteRing.
95 if (dense)
96 return new MutableMat<DMat<RingType> >(this, R.get(), nrows, ncols);
97 else
98 return new MutableMat<SMat<RingType> >(this, R.get(), nrows, ncols);
99 }
100
102 {
103 return ringID() == ring_ZZp or ringID() == ring_ZZpFfpack or
105 }
106
107 bool isGaloisField() const
108 {
109 return ringID() == ring_GFM2 or
111 }
112
114 // Special functions for Galois Fields //
116 // These are declared below for Galois fields, and the definitions appear
117 // where?
118
119 const RingElement *getMinimalPolynomial() const { return nullptr; }
120 const RingElement *getGenerator() const { return nullptr; }
122 {
123 (void) a;
124 return nullptr;
125 }
126
127 virtual long discreteLog(const ring_elem &a) const
128 {
129 (void) a;
130 throw exc::engine_error("cannot compute discrete logarithm in this ring");
131 }
132
134 // Functions on elements ///
136 virtual unsigned int computeHashValue(ring_elem a) const
137 {
138 const ElementType &b = ring().from_ring_elem_const(a);
139 return ring().computeHashValue(b);
140 }
141
142 virtual std::pair<bool, long> coerceToLongInteger(ring_elem a) const
143 {
144 (void) a;
145 return std::pair<bool, long>(false, 0);
146 }
147
148 // The following are all the routines required by 'ring'
149 virtual void text_out(buffer &o) const { return R->text_out(o); }
150 virtual ring_elem from_long(long n) const
151 {
152 if (displayArithmeticCalls) fprintf(stderr, "calling from_long\n");
154 Element a(*R);
155 R->set_from_long(a, n);
156 R->to_ring_elem(result, a);
157 return result;
158 }
159
160 virtual ring_elem from_int(mpz_srcptr n) const
161 {
162 if (displayArithmeticCalls) fprintf(stderr, "calling from_int(mpz)\n");
164 Element a(*R);
165 R->set_from_mpz(a, n);
166 R->to_ring_elem(result, a);
167 return result;
168 }
169 virtual bool from_rational(mpq_srcptr q, ring_elem &result) const
170 {
171 Element a(*R);
172 bool ret = R->set_from_mpq(a, q);
173 if (ret) R->to_ring_elem(result, a);
174 return ret;
175 }
176 virtual bool from_BigReal(gmp_RR q, ring_elem &result) const
177 {
178 Element a(*R);
179 bool ret = get_from_BigReal(*R, a, q);
180 if (ret) R->to_ring_elem(result, a);
181 return ret;
182 }
183
184 virtual bool from_Interval(gmp_RRi q, ring_elem &result) const
185 {
186 Element a(*R);
187 bool ret = get_from_Interval(*R, a, q);
188 if (ret) R->to_ring_elem(result, a);
189 return ret;
190 }
191
193 {
194 Element a(*R);
195 bool ret = get_from_ComplexInterval(*R, a , z);
196 if (ret) R->to_ring_elem(result, a);
197 return ret;
198 }
199
200 virtual bool from_BigComplex(gmp_CC q, ring_elem &result) const
201 {
202 Element a(*R);
203 // bool ret = R->set_from_BigComplex(a,q);
204 bool ret = get_from_BigComplex(*R, a, q);
205 if (ret) R->to_ring_elem(result, a);
206 return ret;
207 }
208 virtual bool from_double(double q, ring_elem &result) const
209 {
210 Element a(*R);
211 bool ret = get_from_double(*R, a, q);
212 if (ret) R->to_ring_elem(result, a);
213 return ret;
214 }
215 virtual bool from_complex_double(double re,
216 double im,
217 ring_elem &result) const
218 {
219 Element a(*R);
220 bool ret = get_from_complex_double(*R, a, re, im);
221 if (ret) R->to_ring_elem(result, a);
222 return ret;
223 }
224
225 virtual ring_elem var(int v) const
226 {
227 if (displayArithmeticCalls) fprintf(stderr, "calling var\n");
229 Element a(*R);
230 R->set_var(a, v);
231 R->to_ring_elem(result, a);
232 return result;
233 }
234
251
252 virtual bool promote(const Ring *S,
253 const ring_elem f,
254 ring_elem &result) const;
255
256 //* If there is a "natural" map S --> R=this, where f is an element of
257 // R, then result is set to an element f in S which maps to f, and true is
258 // returned.
259 // Otherwise, false is returned.
260 //
261 // For examples of maps, see 'promote'.
262 //
263 // Lifting elements of ZZ/p to QQ does not count, as there is no actual
264 // homomorphism
265 // from QQ --> ZZ/p
266
267 virtual bool lift(const Ring *S, const ring_elem f, ring_elem &result) const;
268
269 virtual bool is_unit(const ring_elem f) const
270 {
271 if (displayArithmeticCalls) fprintf(stderr, "calling is_unit\n");
272 const ElementType &a = R->from_ring_elem_const(f);
273 bool ret = R->is_unit(a);
274 return ret;
275 }
276
277 virtual bool is_zero(const ring_elem f) const
278 {
279 if (displayArithmeticCalls) fprintf(stderr, "calling is_zero\n");
280 const ElementType &a = R->from_ring_elem_const(f);
281 bool ret = R->is_zero(a);
282 return ret;
283 }
284
285 virtual bool is_equal(const ring_elem f, const ring_elem g) const
286 {
287 if (displayArithmeticCalls) fprintf(stderr, "calling is_equal\n");
288 const ElementType &a = R->from_ring_elem_const(f);
289 const ElementType &b = R->from_ring_elem_const(g);
290 bool ret = R->is_equal(a, b);
291 return ret;
292 }
293
294 virtual int compare_elems(const ring_elem f, const ring_elem g) const
295 {
296 if (displayArithmeticCalls) fprintf(stderr, "calling compare_elems\n");
297 const ElementType &a = R->from_ring_elem_const(f);
298 const ElementType &b = R->from_ring_elem_const(g);
299 int ret = R->compare_elems(a, b);
300 return ret;
301 }
302
303 virtual ring_elem copy(const ring_elem f) const
304 {
305 if (displayArithmeticCalls) fprintf(stderr, "calling copy\n");
306 const ElementType &a = R->from_ring_elem_const(f);
307 Element b(*R);
309 R->set(b, a);
310 R->to_ring_elem(result, b);
311 return result;
312 }
313
314 virtual void remove(ring_elem &f) const
315 {
316 (void) f;
317 if (displayArithmeticCalls) fprintf(stderr, "calling remove\n");
318 /* currently, do nothing... */
319 }
320
321 virtual ring_elem negate(const ring_elem f) const
322 {
323 if (displayArithmeticCalls) fprintf(stderr, "calling negate\n");
324 const ElementType &a = R->from_ring_elem_const(f);
325 Element b(*R);
327 R->negate(b, a);
328 R->to_ring_elem(result, b);
329 return result;
330 }
331
332 virtual ring_elem add(const ring_elem f, const ring_elem g) const
333 {
334 if (displayArithmeticCalls) fprintf(stderr, "calling add\n");
335 const ElementType &a = R->from_ring_elem_const(f);
336 const ElementType &b = R->from_ring_elem_const(g);
337 Element c(*R);
339 R->add(c, a, b);
340 R->to_ring_elem(result, c);
341 return result;
342 }
343
344 virtual ring_elem subtract(const ring_elem f, const ring_elem g) const
345 {
346 if (displayArithmeticCalls) fprintf(stderr, "calling subtract\n");
347 const ElementType &a = R->from_ring_elem_const(f);
348 const ElementType &b = R->from_ring_elem_const(g);
349 Element c(*R);
351 R->subtract(c, a, b);
352 R->to_ring_elem(result, c);
353 return result;
354 }
355
356 virtual ring_elem mult(const ring_elem f, const ring_elem g) const
357 {
358 if (displayArithmeticCalls) fprintf(stderr, "calling mult\n");
359 const ElementType &a = R->from_ring_elem_const(f);
360 const ElementType &b = R->from_ring_elem_const(g);
361 Element c(*R);
363 R->mult(c, a, b);
364 R->to_ring_elem(result, c);
365 return result;
366 }
367
368 virtual ring_elem power(const ring_elem f, mpz_srcptr n) const
369 {
370 if (displayArithmeticCalls) fprintf(stderr, "calling power mpz\n");
371 const ElementType &a = R->from_ring_elem_const(f);
372 Element b(*R);
374 R->power_mpz(b, a, n);
375 R->to_ring_elem(result, b);
376 return result;
377 }
378
379 virtual ring_elem power(const ring_elem f, int n) const
380 {
381 if (displayArithmeticCalls) fprintf(stderr, "calling power int\n");
382 const ElementType &a = R->from_ring_elem_const(f);
383 Element b(*R);
385 R->power(b, a, n);
386 R->to_ring_elem(result, b);
387 return result;
388 }
389
390 virtual ring_elem invert(const ring_elem f) const
391 {
392 if (displayArithmeticCalls) fprintf(stderr, "calling invert\n");
393 const ElementType &a = R->from_ring_elem_const(f);
394 Element b(*R);
396 R->invert(b, a);
397 R->to_ring_elem(result, b);
398 return result;
399 }
400
401 virtual ring_elem divide(const ring_elem f, const ring_elem g) const
402 {
403 if (displayArithmeticCalls) fprintf(stderr, "calling divide\n");
404 const ElementType &a = R->from_ring_elem_const(f);
405 const ElementType &b = R->from_ring_elem_const(g);
406 Element c(*R);
408 R->divide(c, a, b);
409 R->to_ring_elem(result, c);
410 return result;
411 }
412
413 virtual void syzygy(const ring_elem f,
414 const ring_elem g,
415 ring_elem &x,
416 ring_elem &y) const
417 {
418 if (displayArithmeticCalls) fprintf(stderr, "calling syzygy\n");
419 const ElementType &a = R->from_ring_elem_const(f);
420 const ElementType &b = R->from_ring_elem_const(g);
421 Element xe(*R), ye(*R);
422 R->syzygy(a, b, xe, ye);
423 R->to_ring_elem(x, xe);
424 R->to_ring_elem(y, ye);
425 }
426
427 virtual ring_elem random() const
428 {
429 if (displayArithmeticCalls) fprintf(stderr, "calling random\n");
431 Element a(*R);
432 R->random(a);
433 R->to_ring_elem(result, a);
434 return result;
435 }
436
437 virtual void elem_text_out(buffer &o,
438 const ring_elem f,
439 bool p_one = true,
440 bool p_plus = false,
441 bool p_parens = false) const
442 {
443 if (displayArithmeticCalls) fprintf(stderr, "calling elem_text_out\n");
444 const ElementType &a = R->from_ring_elem_const(f);
445 R->elem_text_out(o, a, p_one, p_plus, p_parens);
446 }
447
448 // map : this = R --> S, f in R
449 // sending primelem --> map->elem(firstvar)
450 // return map(f) as a ring_elem in S
451 virtual ring_elem eval(const RingMap *map,
452 const ring_elem f,
453 int first_var) const
454 {
455 // TODO we shouldn't have to use a non-const element type,
456 // but lots of ARing instances use a non-const reference for the input
457 // this should be fixable, but will require checking
458 Element a(*R);
460 R->from_ring_elem(a, f);
461 R->eval(map, a, first_var, result);
462 return result;
463 }
464
465 // TODO: look again at the next two when ring_elem is phased out
466 virtual ring_elem zeroize_tiny(gmp_RR epsilon, const ring_elem f) const;
467 virtual void increase_maxnorm(gmp_RRmutable norm, const ring_elem f) const;
468
469 virtual unsigned long get_precision()
470 const; // if the ring is not over RRR/CCC returns 0
471
472}; // class ConcreteRing<RingType>
473
488class RingQQ : public ConcreteRing<ARingQQ>
489{
490 public:
491 explicit RingQQ(std::unique_ptr<ARingQQ> R0)
492 : ConcreteRing<ARingQQ>(std::move(R0))
493 {
494 }
495 bool is_QQ() const { return true; }
497 static RingQQ *create()
498 {
499 auto R0 = std::make_unique<ARingQQ>();
500 auto characteristic = R0->characteristic();
501 RingQQ *result = new RingQQ(std::move(R0));
502 result->initialize_ring(characteristic);
503 result->declare_field();
504
505 result->zeroV = result->from_long(0);
506 result->oneV = result->from_long(1);
507 result->minus_oneV = result->from_long(-1);
508
509 return result;
510 }
511
513 {
514 mpz_srcptr numer = top.get_mpz();
515 mpz_srcptr denom = bottom.get_mpz();
516 mpq_ptr b = getmemstructtype(mpq_ptr);
517 mpq_init(b);
518 mpz_set(mpq_numref(b), numer);
519 mpz_set(mpq_denref(b), denom);
520 mpq_canonicalize(b);
521 mpz_reallocate_limbs(mpq_numref(b));
522 mpz_reallocate_limbs(mpq_denref(b));
523 return ring_elem(b);
524 }
525
527 {
528 return globalZZ->from_int(mpq_numref(MPQ_VAL(q)));
529 }
530
532 {
533 return globalZZ->from_int(mpq_denref(MPQ_VAL(q)));
534 }
535
537 {
538 mpq_srcptr a = MPQ_VAL(f);
539 if (mpq_sgn(a) >= 0) return from_long(1);
540 return from_long(-1);
541 }
542
544 {
545 mpq_srcptr a = MPQ_VAL(f);
546 mpq_srcptr b = MPQ_VAL(g);
547 int sa = mpq_sgn(a);
548 int sb = mpq_sgn(b);
549 int s = (sa == 0 ? sb : sa);
550 mpq_ptr result = getmemstructtype(mpq_ptr);
551 mpq_init(result);
552
553 mpz_gcd(mpq_numref(result), mpq_numref(a), mpq_numref(b));
554 mpz_lcm(mpq_denref(result), mpq_denref(a), mpq_denref(b));
555 if (s != mpq_sgn(result)) mpq_neg(result, result);
556 mpz_reallocate_limbs(mpq_numref(result));
557 mpz_reallocate_limbs(mpq_denref(result));
558 f = ring_elem(result);
559 return true; // the answer could become lower, if a newer g has a larger
560 // denom
561 }
562
563 void lower_content(ring_elem &c, const ring_elem g) const
564 {
565 if (is_zero(c))
566 {
567 c = g;
568 return;
569 }
570 mpq_srcptr a = MPQ_VAL(c);
571 mpq_srcptr b = MPQ_VAL(g);
572 int sa = mpq_sgn(a);
573 mpq_ptr result = getmemstructtype(mpq_ptr);
574 mpq_init(result);
575
576 mpz_gcd(mpq_numref(result), mpq_numref(a), mpq_numref(b));
577 mpz_lcm(mpq_denref(result), mpq_denref(a), mpq_denref(b));
578 if (sa != mpq_sgn(result)) mpq_neg(result, result);
579 mpz_reallocate_limbs(mpq_numref(result));
580 mpz_reallocate_limbs(mpq_denref(result));
581 c = ring_elem(result);
582 }
583};
584
585template <class RingType>
587 std::unique_ptr<RingType> R)
588{
589 auto characteristic = R->characteristic();
591 result->initialize_ring(characteristic);
592 result->declare_field();
593
594 result->zeroV = result->from_long(0);
595 result->oneV = result->from_long(1);
596 result->minus_oneV = result->from_long(-1);
597
598
599 return result;
600}
601
602template <class RingType>
603template <class... Args>
605{
607 std::make_unique<RingType>(std::forward<Args>(args)...));
608}
609
611// promote and lift //
613// This is the second level of dispatch, sending the request
614// to the routines in the namespace ARingTranslate
615
616namespace RingPromoter {
617 template <typename SourceRing, typename TargetRing>
618 bool promoter(const Ring *R,
619 const Ring *S,
620 const ring_elem fR,
621 ring_elem &resultS)
622 {
623 assert(dynamic_cast<const ConcreteRing<SourceRing> *>(R) != 0);
624 assert(dynamic_cast<const ConcreteRing<TargetRing> *>(S) != 0);
625 const SourceRing &R1 =
626 dynamic_cast<const ConcreteRing<SourceRing> *>(R)->ring();
627 const TargetRing &S1 =
628 dynamic_cast<const ConcreteRing<TargetRing> *>(S)->ring();
629
630 typename SourceRing::Element fR1(R1);
631 typename TargetRing::Element gS1(S1);
632
633 R1.from_ring_elem(fR1, fR);
634 bool retval = mypromote(R1, S1, fR1, gS1);
635 if (retval) S1.to_ring_elem(resultS, gS1);
636 return retval;
637 }
638
639 template <typename SourceRing, typename TargetRing>
640 bool lifter(const Ring *R,
641 const Ring *S,
642 ring_elem &result_gR,
643 const ring_elem gS)
644 {
645 assert(dynamic_cast<const ConcreteRing<SourceRing> *>(R) != 0);
646 assert(dynamic_cast<const ConcreteRing<TargetRing> *>(S) != 0);
647 const SourceRing &R1 =
648 dynamic_cast<const ConcreteRing<SourceRing> *>(R)->ring();
649 const TargetRing &S1 =
650 dynamic_cast<const ConcreteRing<TargetRing> *>(S)->ring();
651
652 typename SourceRing::Element fR1(R1);
653 typename TargetRing::Element gS1(S1);
654
655 S1.from_ring_elem(gS1, gS);
656 bool retval = mylift(R1, S1, fR1, gS1); // sets fR1.
657 if (retval) R1.to_ring_elem(result_gR, fR1);
658 return retval;
659 }
660};
661
662template <typename RingType>
664 const ring_elem fR,
665 ring_elem &resultS) const
666{
667 const Ring *S = this;
668 // fprintf(stderr, "calling promote\n");
669 namespace RP = RingPromoter;
670 if (R == globalZZ)
671 {
672 resultS = S->from_int(fR.get_mpz());
673 return true;
674 }
675 if (R == S)
676 {
677 resultS = copy(fR);
678 return true;
679 }
680 switch (R->ringID())
681 {
682 case M2::ring_ZZp:
683 switch (S->ringID())
684 {
685 case M2::ring_ZZp:
686 return false;
688 return RP::promoter<ARingZZp, ARingZZpFFPACK>(R, S, fR, resultS);
689 default:
690 return false;
691 }
692 break;
694 switch (S->ringID())
695 {
696 case M2::ring_ZZp:
697 return RP::promoter<ARingZZpFFPACK, ARingZZp>(R, S, fR, resultS);
699 return RP::promoter<ARingZZpFFPACK, ARingZZpFFPACK>(
700 R, S, fR, resultS);
701 default:
702 return false;
703 }
704 case M2::ring_QQ:
705 switch (S->ringID())
706 {
707 case M2::ring_RR:
708 return RP::promoter<ARingQQ, ARingRR>(R, S, fR, resultS);
709 case M2::ring_RRR:
710 return RP::promoter<ARingQQ, ARingRRR>(R, S, fR, resultS);
711 case M2::ring_RRi:
712 return RP::promoter<ARingQQ, ARingRRi>(R, S, fR, resultS);
713 case M2::ring_CC:
714 return RP::promoter<ARingQQ, ARingCC>(R, S, fR, resultS);
715 case M2::ring_CCC:
716 return RP::promoter<ARingQQ, ARingCCC>(R, S, fR, resultS);
717 case M2::ring_CCi:
718 return RP::promoter<ARingQQ, ARingCCi>(R, S, fR, resultS);
719 default:
720 return false;
721 }
722 case M2::ring_RR:
723 switch (S->ringID())
724 {
725 case M2::ring_RR:
726 return RP::promoter<ARingRR, ARingRR>(R, S, fR, resultS);
727 case M2::ring_RRR:
728 return RP::promoter<ARingRR, ARingRRR>(R, S, fR, resultS);
729 case M2::ring_RRi:
730 return RP::promoter<ARingRR, ARingRRi>(R, S, fR, resultS);
731 case M2::ring_CC:
732 return RP::promoter<ARingRR, ARingCC>(R, S, fR, resultS);
733 case M2::ring_CCC:
734 return RP::promoter<ARingRR, ARingCCC>(R, S, fR, resultS);
735 case M2::ring_CCi:
736 return RP::promoter<ARingRR, ARingCCi>(R, S, fR, resultS);
737 default:
738 return false;
739 }
740 case M2::ring_RRR:
741 switch (S->ringID())
742 {
743 case M2::ring_RR:
744 return RP::promoter<ARingRRR, ARingRR>(R, S, fR, resultS);
745 case M2::ring_RRR:
746 return RP::promoter<ARingRRR, ARingRRR>(R, S, fR, resultS);
747 case M2::ring_RRi:
748 return RP::promoter<ARingRRR, ARingRRi>(R, S, fR, resultS);
749 case M2::ring_CC:
750 return RP::promoter<ARingRRR, ARingCC>(R, S, fR, resultS);
751 case M2::ring_CCC:
752 return RP::promoter<ARingRRR, ARingCCC>(R, S, fR, resultS);
753 case M2::ring_CCi:
754 return RP::promoter<ARingRRR, ARingCCi>(R, S, fR, resultS);
755 default:
756 return false;
757 }
758 case M2::ring_RRi:
759 switch (S->ringID())
760 {
761 case M2::ring_RR:
762 return RP::promoter<ARingRRi, ARingRR>(R, S, fR, resultS);
763 case M2::ring_RRR:
764 return RP::promoter<ARingRRi, ARingRRR>(R, S, fR, resultS);
765 case M2::ring_RRi:
766 return RP::promoter<ARingRRi, ARingRRi>(R, S, fR, resultS);
767 case M2::ring_CCi:
768 return RP::promoter<ARingRRi,ARingCCi>(R, S, fR, resultS);
769 default:
770 return false;
771 }
772 case M2::ring_CC:
773 switch (S->ringID())
774 {
775 case M2::ring_CC:
776 return RP::promoter<ARingCC, ARingCC>(R, S, fR, resultS);
777 case M2::ring_CCC:
778 return RP::promoter<ARingCC, ARingCCC>(R, S, fR, resultS);
779 case M2::ring_CCi:
780 return RP::promoter<ARingCC, ARingCCi>(R, S, fR, resultS);
781 default:
782 return false;
783 }
784 case M2::ring_CCC:
785 switch (S->ringID())
786 {
787 case M2::ring_CCC:
788 return RP::promoter<ARingCCC, ARingCCC>(R, S, fR, resultS);
789 case M2::ring_CC:
790 return RP::promoter<ARingCCC, ARingCC>(R, S, fR, resultS);
791 case M2::ring_CCi:
792 return RP::promoter<ARingCCC, ARingCCi>(R, S, fR, resultS);
793 default:
794 return false;
795 }
796 case M2::ring_CCi:
797 switch (S->ringID())
798 {
799 case M2::ring_CCi:
800 return RP::promoter<ARingCCi, ARingCCi>(R, S, fR, resultS);
801 default:
802 return false;
803 }
804 default:
805 break;
806 };
807 return false;
808}
809
810// given a natural map: R --> S = this,
811// 'lift' sets result_gR with an element which maps to gS, if possible.
812// true is returned iff this is possible.
813template <typename RingType>
815 const ring_elem gS,
816 ring_elem &result_gR) const
817{
818 const Ring *S = this;
819
820 namespace RP = RingPromoter;
821 if (R == S)
822 {
823 result_gR = gS;
824 return true;
825 }
826 if (R == globalZZ)
827 {
828 printf("error!! lift called with no ZZ lifting method\n");
829 // MES:TODO!! WRITE ME
830 return true;
831 }
832 switch (R->ringID())
833 {
834 case M2::ring_ZZp:
835 switch (S->ringID())
836 {
837 case M2::ring_ZZp:
838 return false;
840 return RP::lifter<ARingZZp, ARingZZpFFPACK>(R, S, result_gR, gS);
841 default:
842 return false;
843 }
844 break;
846 switch (S->ringID())
847 {
848 case M2::ring_ZZp:
849 return RP::lifter<ARingZZpFFPACK, ARingZZp>(R, S, result_gR, gS);
851 return RP::lifter<ARingZZpFFPACK, ARingZZpFFPACK>(
852 R, S, result_gR, gS);
853 default:
854 return false;
855 }
856 case M2::ring_RR:
857 switch (S->ringID())
858 {
859 case M2::ring_RR:
860 return RP::lifter<ARingRR, ARingRR>(R, S, result_gR, gS);
861 case M2::ring_RRR:
862 return RP::lifter<ARingRR, ARingRRR>(R, S, result_gR, gS);
863 case M2::ring_RRi:
864 return RP::lifter<ARingRR, ARingRRi>(R, S, result_gR, gS);
865 case M2::ring_CC:
866 return RP::lifter<ARingRR, ARingCC>(R, S, result_gR, gS);
867 case M2::ring_CCC:
868 return RP::lifter<ARingRR, ARingCCC>(R, S, result_gR, gS);
869 default:
870 return false;
871 }
872 case M2::ring_RRR:
873 switch (S->ringID())
874 {
875 case M2::ring_RR:
876 return RP::lifter<ARingRRR, ARingRR>(R, S, result_gR, gS);
877 case M2::ring_RRR:
878 return RP::lifter<ARingRRR, ARingRRR>(R, S, result_gR, gS);
879 case M2::ring_RRi:
880 return RP::lifter<ARingRRR, ARingRRi>(R, S, result_gR, gS);
881 case M2::ring_CC:
882 return RP::lifter<ARingRRR, ARingCC>(R, S, result_gR, gS);
883 case M2::ring_CCC:
884 return RP::lifter<ARingRRR, ARingCCC>(R, S, result_gR, gS);
885 default:
886 return false;
887 }
888 case M2::ring_CC:
889 switch (S->ringID())
890 {
891 case M2::ring_CC:
892 return RP::lifter<ARingCC, ARingCC>(R, S, result_gR, gS);
893 case M2::ring_CCC:
894 return RP::lifter<ARingCCC, ARingCC>(R, S, result_gR, gS);
895 default:
896 return false;
897 }
898 case M2::ring_CCC:
899 switch (S->ringID())
900 {
901 case M2::ring_CC:
902 return RP::lifter<ARingCC, ARingCCC>(R, S, result_gR, gS);
903 case M2::ring_CCC:
904 return RP::lifter<ARingCCC, ARingCCC>(R, S, result_gR, gS);
905 default:
906 return false;
907 }
908 default:
909#ifndef NDEBUG
910 fprintf(stderr,
911 "oh no: rings not in list\n, R->ringID()=%d S->ringID()=%d\n",
912 R->ringID(),
913 S->ringID());
914#endif
915 break;
916 };
917 return false;
918}
919
920// Note: the only promotion to 'this' allowed is ZZ --> this, which is covered
921// above this code.
922// So there is no need to provide a separate 'promote' function
923
924template <typename RingType>
925bool liftToInt(const RingType &R,
926 const Ring *Rg,
927 const ring_elem f,
929{
930 if (Rg == globalZZ)
931 {
932 typename RingType::Element a(R);
933 R.from_ring_elem(a, f);
934 result = Rg->from_long(R.coerceToLongInteger(a));
935 return true;
936 }
937 return false;
938}
939
940template <>
942 const ring_elem f,
943 ring_elem &result) const
944{
945 return liftToInt(ring(), Rg, f, result);
946}
947template <>
948inline bool ConcreteRing<ARingZZp>::lift(const Ring *Rg,
949 const ring_elem f,
950 ring_elem &result) const
951{
952 return liftToInt(ring(), Rg, f, result);
953}
954template <>
956 const ring_elem f,
957 ring_elem &result) const
958{
959 return liftToInt(ring(), Rg, f, result);
960}
961
962template <>
964 const ring_elem f,
965 ring_elem &result) const
966{
967 // Rf = Z/p[x]/F(x) ---> GF(p,n)
968 // promotion: need to be able to know the value of 'x'.
969 // lift: need to compute (primite_element)^e
970 ElementType a;
971 bool retval = R->promote(Rf, f, a);
972 R->to_ring_elem(result, a);
973 return retval;
974}
975
976template <>
978 const ring_elem f,
979 ring_elem &result) const
980{
981 // Rf = Z/p[x]/F(x) ---> GF(p,n)
982 // promotion: need to be able to know the value of 'x'.
983 // lift: need to compute (primite_element)^e
984
985 ElementType a;
986 R->from_ring_elem(a, f);
987 bool retval = R->lift(Rg, a, result);
988 return retval;
989}
990
991template <>
993 const ring_elem f,
994 ring_elem &result) const
995{
996 Element a(ring());
997 bool retval = ring().promote(Rf, f, a);
998 ring().to_ring_elem(result, a);
999 return retval;
1000}
1001
1002template <>
1004 const ring_elem f,
1005 ring_elem &result) const
1006{
1007 Element a(ring());
1008 ring().from_ring_elem(a, f);
1009 bool retval = ring().lift(Rg, a, result);
1010 return retval;
1011}
1012
1013template <>
1015 const ring_elem f,
1016 ring_elem &result) const
1017{
1018 Element a(ring());
1019 bool retval = ring().promote(Rf, f, a);
1020 ring().to_ring_elem(result, a);
1021 return retval;
1022}
1023
1024template <>
1026 const ring_elem f,
1027 ring_elem &result) const
1028{
1029 Element a(ring());
1030 ring().from_ring_elem(a, f);
1031 bool retval = ring().lift(Rg, a, result);
1032 return retval;
1033}
1034
1035template <>
1036inline bool ConcreteRing<ARingQQ>::lift(const Ring *Rg,
1037 const ring_elem f,
1038 ring_elem &result) const
1039{
1040 if (Rg == globalZZ)
1041 {
1042 mpz_t b;
1043 mpz_init(b);
1044
1045 Element a(*R);
1046 R->from_ring_elem(a, f);
1047
1048 bool retval = R->lift_to_mpz(b, a);
1049 if (retval)
1050 {
1051 result = globalZZ->from_int(b);
1052 }
1053 mpz_clear(b);
1054 return retval;
1055 }
1056 return false;
1057}
1058
1059template <typename RingType>
1061 const ring_elem f) const
1062{
1063 (void) epsilon;
1064 return f;
1065}
1066
1067template <typename RingType>
1069 const ring_elem f) const
1070{
1071 (void) norm;
1072 (void) f;
1073}
1074
1075template <>
1077 const ring_elem f) const
1078{
1079 Element a(*R);
1080 R->from_ring_elem(a, f);
1081 R->zeroize_tiny(epsilon, a);
1083 R->to_ring_elem(result, a);
1084 return result;
1085}
1086
1087template <>
1089 const ring_elem f) const
1090{
1091 Element a(*R);
1092 R->from_ring_elem(a, f);
1093 R->zeroize_tiny(epsilon, a);
1095 R->to_ring_elem(result, a);
1096 return result;
1097}
1098
1099template <>
1101 const ring_elem f) const
1102{
1103 Element a(*R);
1104 R->from_ring_elem(a, f);
1105 R->zeroize_tiny(epsilon, a);
1107 R->to_ring_elem(result, a);
1108 return result;
1109}
1110
1111template <>
1113 const ring_elem f) const
1114{
1115 Element a(*R);
1116 R->from_ring_elem(a, f);
1117 R->zeroize_tiny(epsilon, a);
1119 R->to_ring_elem(result, a);
1120 return result;
1121}
1122
1123template <>
1125 const ring_elem f) const
1126{
1127 ARingRR::Element a(*R); // will be the norm
1128 const ElementType &b = R->from_ring_elem_const(f);
1129 R->abs(a, b);
1130 if (mpfr_cmp_d(norm, a) < 0) mpfr_set_d(norm, a, MPFR_RNDN);
1131}
1132
1133template <>
1135 const ring_elem f) const
1136{
1137 const ARingRR &realR = R->real_ring();
1138 ARingRR::Element a(realR);
1139 const ElementType &b = R->from_ring_elem_const(f);
1140 R->abs(a, b);
1141 if (mpfr_cmp_d(norm, a) < 0) mpfr_set_d(norm, a, MPFR_RNDN);
1142}
1143
1144template <>
1146 const ring_elem f) const
1147{
1148 ARingRRR::Element a(*R); // will be the norm
1149 const ElementType &b = R->from_ring_elem_const(f);
1150 R->abs(a, b);
1151 if (mpfr_cmp(&a.value(), norm) > 0) mpfr_set(norm, &a.value(), MPFR_RNDN);
1152}
1153
1154template <>
1156 const ring_elem f) const
1157{
1158 const ARingRRR &realR = R->real_ring();
1159 ARingRRR::Element a(realR);
1160 const ElementType &b = R->from_ring_elem_const(f);
1161 R->abs(a, b);
1162 if (mpfr_cmp(&a.value(), norm) > 0) mpfr_set(norm, &a.value(), MPFR_RNDN);
1163}
1164
1165template <typename RingType>
1166inline unsigned long ConcreteRing<RingType>::get_precision() const
1167{
1168 return 0;
1169}
1170
1171template <>
1172inline unsigned long ConcreteRing<ARingRR>::get_precision() const
1173{
1174 return R->get_precision();
1175}
1176
1177template <>
1178inline unsigned long ConcreteRing<ARingCC>::get_precision() const
1179{
1180 return R->get_precision();
1181}
1182
1183template <>
1184inline unsigned long ConcreteRing<ARingRRR>::get_precision() const
1185{
1186 return R->get_precision();
1187}
1188
1189template <>
1190inline unsigned long ConcreteRing<ARingRRi>::get_precision() const
1191{
1192 return R->get_precision();
1193}
1194
1195template <>
1196inline unsigned long ConcreteRing<ARingCCC>::get_precision() const
1197{
1198 return R->get_precision();
1199}
1200
1201template <>
1202inline unsigned long ConcreteRing<ARingCCi>::get_precision() const
1203{
1204 return R->get_precision();
1205}
1206
1207template <typename RT>
1208std::pair<bool, long> coerceToLongIntegerFcn(const RT &ring, ring_elem a)
1209{
1210 const typename RT::ElementType &b = ring.from_ring_elem_const(a);
1211 long result = ring.coerceToLongInteger(b);
1212 return std::pair<bool, long>(true, result);
1213}
1214
1215template <>
1217 ring_elem a) const
1218{
1219 return coerceToLongIntegerFcn(ring(), a);
1220}
1221
1222template <>
1224 ring_elem a) const
1225{
1226 return coerceToLongIntegerFcn(ring(), a);
1227}
1228
1229template <>
1231 ring_elem a) const
1232{
1233 return coerceToLongIntegerFcn(ring(), a);
1234}
1235
1236template <>
1238 ring_elem a) const
1239{
1240 long b;
1241 bool succeed = ring().coerceToLongInteger(b, *a.get_mpz());
1242 return std::pair<bool, long>(succeed, b);
1243}
1244
1245template <>
1247 ring_elem a) const
1248{
1249 long b;
1250 fmpz t = reinterpret_cast<fmpz>(const_cast<Nterm *>(a.poly_val));
1251 bool succeed = ring().coerceToLongInteger(b, t);
1252 return std::pair<bool, long>(succeed, b);
1253}
1254
1255inline const RingElement *findMinimalPolynomial(const PolynomialRing &originalR)
1256{
1257 const PolynomialRing *R = originalR.getAmbientRing();
1258 ring_elem f = R->copy(originalR.quotient_element(0));
1259 return RingElement::make_raw(R, f);
1260}
1261
1262template <>
1264{
1265 return findMinimalPolynomial(ring().originalRing());
1266}
1267
1268template <>
1270 const
1271{
1272 return findMinimalPolynomial(ring().originalRing());
1273}
1274
1275template <>
1277 const
1278{
1279 return findMinimalPolynomial(ring().originalRing());
1280}
1281
1282template <typename RT>
1283inline const RingElement *getLiftedRepresentation(const RT &R,
1284 const ring_elem &a)
1285// R should be a Galois Field
1286{
1287 ring_elem c; // in originalRing()
1288 typename RT::Element b(R); // in ring()
1289 R.from_ring_elem(b, a);
1290 R.lift_to_original_ring(c, b);
1291 return RingElement::make_raw(&R.originalRing(), c);
1292}
1293
1294template <>
1296 const ring_elem &a) const
1297{
1299}
1300
1301template <>
1307template <>
1313
1314template <typename ConcreteRT>
1315inline const RingElement *getGen(const ConcreteRT &R)
1316// R should be a Galois Field
1317{
1318 typename ConcreteRT::Element a(R.ring());
1319 ring_elem b;
1320 R.ring().getGenerator(a);
1321 R.ring().to_ring_elem(b, a);
1322 return RingElement::make_raw(&R, b);
1323}
1324
1325template <>
1330template <>
1332{
1333 return getGen<ConcreteRing<ARingGFM2> >(*this);
1334}
1335template <>
1340template <>
1345
1346template <>
1348{
1349 const ElementType &a = ring().from_ring_elem_const(a1);
1350 long result = ring().discreteLog(a);
1351 return result;
1352}
1353
1354}; // namespace M2
1355
1356#include "aring-qq.hpp"
1358extern void initializeRationalRing();
1359extern const RingQQ *globalQQ;
1360#endif
1361
1362// Local Variables:
1363// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1364// indent-tabs-mode: nil
1365// End:
M2::RingQQ RingQQ
void initializeRationalRing()
Definition aring.cpp:26
const RingQQ * globalQQ
Definition aring.cpp:24
static const bool displayArithmeticCalls
Tiny dispatcher header that picks the default ARingQQ from among the QQ aring implementations.
Cross-ring coercion templates: mypromote / mylift between two aring rings, and get_from_* from an ext...
Shared base of the aring framework (namespace M2) that unifies the engine's coefficient rings.
aring-style adapter for double-precision real numbers.
Definition aring-RR.hpp:62
aring-style adapter for arbitrary-precision real numbers, backed by MPFR.
Definition aring-RRR.hpp:70
bool isGaloisField() const
virtual void text_out(buffer &o) const
virtual ring_elem mult(const ring_elem f, const ring_elem g) const
const RingElement * getRepresentation(const ring_elem &a) const
virtual bool from_Interval(gmp_RRi q, ring_elem &result) const
virtual ring_elem var(int v) const
virtual bool is_zero(const ring_elem f) const
virtual ring_elem invert(const ring_elem f) const
virtual void increase_maxnorm(gmp_RRmutable norm, const ring_elem f) const
virtual ring_elem power(const ring_elem f, int n) const
RingType::ElementType ElementType
virtual ring_elem from_long(long n) const
virtual unsigned long get_precision() const
virtual unsigned int computeHashValue(ring_elem a) const
const M2::ARingCCC & ring() const
virtual bool promote(const Ring *S, const ring_elem f, ring_elem &result) const
virtual void remove(ring_elem &f) const
virtual bool lift(const Ring *S, const ring_elem f, ring_elem &result) const
ConcreteRing(const ConcreteRing &ring)=delete
virtual ring_elem negate(const ring_elem f) const
const RingElement * getGenerator() const
virtual bool from_BigReal(gmp_RR q, ring_elem &result) const
virtual ring_elem divide(const ring_elem f, const ring_elem g) const
virtual ring_elem subtract(const ring_elem f, const ring_elem g) const
virtual bool from_complex_double(double re, double im, ring_elem &result) const
virtual ~ConcreteRing()=default
const RingElement * getMinimalPolynomial() const
virtual void syzygy(const ring_elem f, const ring_elem g, ring_elem &x, ring_elem &y) const
virtual int compare_elems(const ring_elem f, const ring_elem g) const
virtual bool from_ComplexInterval(gmp_CCi z, ring_elem &result) const
static ConcreteRing< RingType > * create(std::unique_ptr< RingType > R)
virtual bool is_unit(const ring_elem f) const
ConcreteRing(std::unique_ptr< RingType > R0)
virtual ring_elem from_int(mpz_srcptr n) const
virtual MutableMatrix * makeMutableMatrix(size_t nrows, size_t ncols, bool dense) const
Create either a dense or sparse MutableMatrix of the given size.
virtual ring_elem eval(const RingMap *map, const ring_elem f, int first_var) const
virtual bool from_BigComplex(gmp_CC q, ring_elem &result) const
virtual std::pair< bool, long > coerceToLongInteger(ring_elem a) const
virtual ring_elem zeroize_tiny(gmp_RR epsilon, const ring_elem f) const
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.
virtual bool from_double(double q, ring_elem &result) const
virtual void elem_text_out(buffer &o, const ring_elem f, bool p_one=true, bool p_plus=false, bool p_parens=false) const
std::unique_ptr< M2::ARingCCC > R
virtual M2::RingID ringID() const
virtual long discreteLog(const ring_elem &a) const
static ConcreteRing< RingType > * create(Args &&...args)
virtual ring_elem random() const
virtual bool from_rational(mpq_srcptr q, ring_elem &result) const
virtual bool is_equal(const ring_elem f, const ring_elem g) const
RingType::Element Element
virtual ring_elem copy(const ring_elem f) const
virtual ring_elem add(const ring_elem f, const ring_elem g) const
bool isFinitePrimeField() const
RingQQ(std::unique_ptr< ARingQQ > R0)
ring_elem numerator(ring_elem q) const
ring_elem preferred_associate(ring_elem f) const
CoefficientType coefficient_type() const
ring_elem fraction(ring_elem top, ring_elem bottom) const
bool lower_associate_divisor(ring_elem &f, const ring_elem g) const
bool is_QQ() const
void lower_content(ring_elem &c, const ring_elem g) const
static RingQQ * create()
ring_elem denominator(ring_elem q) const
Ring-level QQ ring, a thin specialisation of ConcreteRing<ARingQQ> that marks itself with is_QQ() and...
Abstract base class for mutable matrices over an arbitrary engine Ring, the in-place counterpart of t...
Definition mat.hpp:79
virtual const PolynomialRing * getAmbientRing() const
Definition polyring.hpp:260
Nterm * quotient_element(int i) const
Definition polyring.hpp:220
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual M2::RingID ringID() const
Definition ring.hpp:164
virtual ring_elem from_long(long n) const =0
long characteristic() const
Definition ring.hpp:159
virtual ring_elem copy(const ring_elem f) const =0
CoefficientType
Definition ring.hpp:222
@ COEFF_QQ
Definition ring.hpp:222
virtual ring_elem from_int(mpz_srcptr n) const =0
Ring()
Definition ring.hpp:136
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
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
RingZZ * globalZZ
Definition relem.cpp:13
void mpz_reallocate_limbs(mpz_ptr _z)
Definition gmp-util.h:46
RingID
Definition aring.hpp:75
@ ring_CCC
Definition aring.hpp:90
@ ring_GFM2
Definition aring.hpp:84
@ ring_RR
Definition aring.hpp:87
@ ring_ZZpFfpack
Definition aring.hpp:82
@ ring_ZZpFlint
Definition aring.hpp:83
@ ring_GFFlintZech
Definition aring.hpp:86
@ ring_RRR
Definition aring.hpp:89
@ ring_RRi
Definition aring.hpp:91
@ ring_GFFlintBig
Definition aring.hpp:85
@ ring_CCi
Definition aring.hpp:92
@ ring_ZZp
Definition aring.hpp:81
@ ring_QQ
Definition aring.hpp:79
@ ring_CC
Definition aring.hpp:88
void size_t s
Definition m2-mem.cpp:271
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemstructtype(S)
Definition m2-mem.h:143
mpfr_srcptr gmp_RR
Definition m2-types.h:148
struct gmp_CC_struct * gmp_CC
Definition m2-types.h:156
mpfr_ptr gmp_RRmutable
Definition m2-types.h:150
mpfi_srcptr gmp_RRi
Definition m2-types.h:153
struct gmp_CCi_struct * gmp_CCi
Definition m2-types.h:162
Umbrella header that ties together MutableMat declarations, implementations, and the SLP variant.
bool promoter(const Ring *R, const Ring *S, const ring_elem fR, ring_elem &resultS)
bool lifter(const Ring *R, const Ring *S, ring_elem &result_gR, const ring_elem gS)
std::pair< bool, long > coerceToLongIntegerFcn(const RT &ring, ring_elem a)
const RingElement * getLiftedRepresentation(const RT &R, const ring_elem &a)
bool get_from_Interval(const RT &R, typename RT::ElementType &a, gmp_RRi b)
const RingElement * getGen(const ConcreteRT &R)
ARingQQGMP ARingQQ
Definition aring-qq.hpp:38
const RingElement * findMinimalPolynomial(const PolynomialRing &originalR)
bool mypromote(const RingR &R, const RingS &S, const typename RingR::ElementType &fR, typename RingS::ElementType &result_fS)
bool get_from_BigComplex(const RT &R, typename RT::ElementType &a, gmp_CC b)
bool get_from_complex_double(const RT &R, typename RT::ElementType &a, double re, double im)
bool get_from_double(const RT &R, typename RT::ElementType &a, double b)
bool liftToInt(const RingType &R, const Ring *Rg, const ring_elem f, ring_elem &result)
bool get_from_ComplexInterval(const RT &R, typename RT::ElementType &a, gmp_CCi b)
bool get_from_BigReal(const RT &R, typename RT::ElementType &a, gmp_RR b)
bool mylift(const RingR &R, const RingS &S, typename RingR::ElementType &result_gR, const typename RingS::ElementType &gS)
Definition aring-CC.cpp:3
STL namespace.
volatile int x
Ring — the legacy abstract base class for every coefficient and polynomial ring.
#define MPQ_VAL(f)
Definition ringelem.hpp:206
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
Nterm * poly_val
Definition ringelem.hpp:86
mpz_srcptr get_mpz() const
Definition ringelem.hpp:127