Macaulay2 Engine
Loading...
Searching...
No Matches
ringelement.cpp
Go to the documentation of this file.
1// Copyright 2002 Michael E. Stillman
2
4
5#include <assert.h>
6#include <memory>
7#include <utility>
8#include <vector>
9
10#include "ExponentList.hpp"
11#include "M2FreeAlgebra.hpp"
13
14#include "aring-CC.hpp"
15#include "aring-CCC.hpp"
16#include "aring-RR.hpp"
17#include "aring-RRR.hpp"
18#include "aring-RRi.hpp"
19#include "aring-CCi.hpp"
20#include "aring-glue.hpp"
21#include "aring.hpp"
22#include "buffer.hpp"
23#include "error.h"
24#include "exceptions.hpp"
25#include "interface/monoid.h"
26#include "monoid.hpp"
27#include "monomial.hpp"
28#include "newdelete.hpp"
29#include "poly.hpp"
30#include "polyring.hpp"
31#include "relem.hpp"
32#include "ring.hpp"
33#include "ringelem.hpp"
34#include "schur.hpp"
35#include "schur2.hpp"
36#include "schurSn.hpp"
37#include "tower.hpp"
38#include "util.hpp"
39
40namespace M2 { class ARingRRR; }
41
42unsigned int rawRingElementHash(const RingElement *a) { return a->hash(); }
43const Ring *IM2_RingElement_ring(const RingElement *a) { return a->get_ring(); }
45{
46 buffer o;
47 f->text_out(o);
48 return o.to_string();
49}
50
52{
53 return RingElement::make_raw(R, R->from_int(d));
54}
55
56const RingElement *IM2_RingElement_from_rational(const Ring *R, mpq_srcptr r)
57{
59 bool ok = R->from_rational(r, result);
60 if (not ok)
61 {
62 ERROR("unable to coerce rational into ring");
63 return nullptr;
64 }
66}
67
69{
70 ring_elem f;
71 if (R->from_BigComplex(z, f)) return RingElement::make_raw(R, f);
72 ERROR("cannot create element of this ring from an element of CC");
73 return nullptr;
74}
75
77{
78 ring_elem f;
79 if (R->from_BigReal(z, f)) return RingElement::make_raw(R, f);
80 ERROR("cannot create element of this ring from an element of RR");
81 return nullptr;
82}
83
85{
86 ring_elem f;
87 if (R->from_Interval(z, f)) return RingElement::make_raw(R, f);
88 ERROR("cannot create element of this ring from an element of RRi");
89 return nullptr;
90}
91
93{
94 ring_elem f;
95 if (R->from_ComplexInterval(z, f)) return RingElement::make_raw(R, f);
96 ERROR("cannot create element of this ring from an element of CCi");
97 return nullptr;
98}
99
101/* If the ring of a is ZZ, or ZZ/p, this returns the underlying representation.
102 Otherwise, NULL is returned, and an error is given */
103{
104 const Ring *R = a->get_ring();
105 if (R->is_ZZ())
106 {
107 // Note: RingElement ZZ elements are on the "gc" side of the memory barrier, and
108 // are read only. Therefore we can just return the same value.
109 return a->get_value().get_mpz();
110 }
111 if (R->isFinitePrimeField())
112 {
113 mpz_ptr result = newitem(__mpz_struct);
114
115 std::pair<bool, long> res = R->coerceToLongInteger(a->get_value());
116 assert(res.first);
117
118 mpz_init_set_si(result, static_cast<int>(res.second));
120 return result;
121 }
122 ERROR("Expected ZZ or ZZ/p as base ring");
123 return nullptr;
124}
125
127{
128 if (!a->get_ring()->is_QQ())
129 {
130 ERROR("expected an element of QQ");
131 return nullptr;
132 }
133 return a->get_value().get_mpq();
134}
135
137{
138 const Ring *R = a->get_ring();
141
142 switch (R->ringID())
143 {
144 case M2::ring_RR:
146 mpfr_init2(result, 53);
147 mpfr_set_d(result, a->get_value().get_double(), MPFR_RNDN);
148 return moveTo_gmpRR(result);
149 case M2::ring_RRR:
150 R1 =
151 dynamic_cast<const M2::ConcreteRing<M2::ARingRRR> *>(R);
153 mpfr_init2(result, R1->get_precision());
154 mpfr_set(result, a->get_value().get_mpfr(), MPFR_RNDN);
155 return moveTo_gmpRR(result);
156 default:
157 ERROR("expected an element of RRR");
158 return nullptr;
159 }
160}
161
163{
164 const Ring *R = a->get_ring();
167
168 switch (R->ringID())
169 {
170 case M2::ring_RR:
172 mpfi_init2(result, 53);
173 mpfi_set_d(result, a->get_value().get_double());
174 return moveTo_gmpRRi(result);
175 case M2::ring_RRR:
176 R1 =
177 dynamic_cast<const M2::ConcreteRing<M2::ARingRRi> *>(R);
179 mpfi_init2(result, R1->get_precision());
180 mpfi_set_fr(result, a->get_value().get_mpfr());
181 return moveTo_gmpRRi(result);
182 case M2::ring_RRi:
183 R1 =
184 dynamic_cast<const M2::ConcreteRing<M2::ARingRRi> *>(R);
186 mpfi_init2(result, R1->get_precision());
187 mpfi_set(result, a->get_value().get_mpfi());
188 return moveTo_gmpRRi(result);
189 default:
190 ERROR("expected an element of RRi");
191 return nullptr;
192 }
193}
194
196{
197 const Ring *R = a->get_ring();
198 auto RCCC = dynamic_cast<const M2::ConcreteRing<M2::ARingCCC> *>(R);
199 if (RCCC != nullptr)
200 {
202 RCCC->ring().from_ring_elem_const(a->get_value());
203 gmp_CC result = RCCC->ring().toBigComplex(b);
204 return result;
205 }
206 auto RCC = dynamic_cast<const M2::ConcreteRing<M2::ARingCC> *>(R);
207 if (RCC != nullptr)
208 {
209 const M2::ARingCC::ElementType &b =
210 RCC->ring().from_ring_elem_const(a->get_value());
211 gmp_CC result = RCC->ring().toBigComplex(b);
212 return result;
213 }
214 ERROR("expected an element of CCC");
215 return nullptr;
216}
217
219{
220 const Ring *R = a->get_ring();
223
224 switch (R->ringID())
225 {
226 case M2::ring_RR:
230 mpfi_init2(result->re, 53);
231 mpfi_init2(result->im, 53);
232 mpfi_set_d(result->re, a->get_value().get_double());
233 mpfi_set_d(result->im, 0);
234 return moveTo_gmpCCi(result);
235 case M2::ring_RRR:
236 R1 =
237 dynamic_cast<const M2::ConcreteRing<M2::ARingCCi> *>(R);
241 mpfi_init2(result->re, R1->get_precision());
242 mpfi_init2(result->im, R1->get_precision());
243 mpfi_set_fr(result->re, a->get_value().get_mpfr());
244 mpfi_set_d(result->im, 0);
245 return moveTo_gmpCCi(result);
246 case M2::ring_RRi:
247 R1 =
248 dynamic_cast<const M2::ConcreteRing<M2::ARingCCi> *>(R);
252 mpfi_init2(result->re, R1->get_precision());
253 mpfi_init2(result->im, R1->get_precision());
254 mpfi_set(result->re, a->get_value().get_mpfi());
255 mpfi_set_d(result->im,0);
256 return moveTo_gmpCCi(result);
257 case M2::ring_CCC:
258 R1 =
259 dynamic_cast<const M2::ConcreteRing<M2::ARingCCi> *>(R);
263 mpfi_init2(result->re, R1->get_precision());
264 mpfi_init2(result->im, R1->get_precision());
265 mpfi_set_fr(result->re, &a->get_value().get_cc()->re);
266 mpfi_set_fr(result->im, &a->get_value().get_cc()->im);
267 return moveTo_gmpCCi(result);
268 case M2::ring_CCi:
269 R1 =
270 dynamic_cast<const M2::ConcreteRing<M2::ARingCCi> *>(R);
274 mpfi_init2(result->re, R1->get_precision());
275 mpfi_init2(result->im, R1->get_precision());
276 mpfi_set(result->re, &a->get_value().get_cci()->re);
277 mpfi_set(result->im, &a->get_value().get_cci()->im);
278 return moveTo_gmpCCi(result);
279 default:
280 ERROR("expected an element of CCi");
281 return nullptr;
282 }
283}
284
285#if 0
286int rawDiscreteLog(const RingElement *h)
287{
288 const Ring *R = h->get_ring();
289
290 const Z_mod *RP = R->cast_to_Z_mod();
291 if (RP != 0)
292 return RP->discrete_log(h->get_value());
293
294 const GF *P = R->cast_to_GF();
295 if (P != 0)
296 return P->discrete_log(h->get_value());
297
298 // Returns -1 if either h is zero, or the ring of h doesn't have a discrete log algorithm
299 return -1;
300}
301#endif
302
304{
305 try
306 {
307 const Ring *R = h->get_ring();
308 return R->discreteLog(h->get_value());
309 } catch (const exc::engine_error& e)
310 {
311 ERROR(e.what());
312 return -1;
313 }
314}
315
317{
318 return R->getGenerator();
319}
320
321const RingElement /* or null */ *IM2_RingElement_make_var(const Ring *R, int v)
322{
323 try
324 {
325 ring_elem a = R->var(v);
326 if (error()) return nullptr;
327 return RingElement::make_raw(R, a);
328 } catch (const exc::engine_error& e)
329 {
330 ERROR(e.what());
331 return nullptr;
332 }
333}
334
336{
337 return a->get_ring()->is_zero(a->get_value());
338}
339
341{
342 const Ring *R = a->get_ring();
343 if (R != b->get_ring()) return 0;
344 return R->is_equal(a->get_value(), b->get_value());
345}
346
348 const RingElement *b)
349{
350 try
351 {
352 const Ring *R = a->get_ring();
353 if (R != b->get_ring())
354 {
355 ERROR(
356 "ring remainder requires both elements to have the same base "
357 "ring");
358 return nullptr;
359 }
360 ring_elem fquot;
361 ring_elem frem =
362 R->remainderAndQuotient(a->get_value(), b->get_value(), fquot);
363 if (error()) return nullptr;
364
365 engine_RawRingElementPair result = new engine_RawRingElementPair_struct;
366 result->a = RingElement::make_raw(R, fquot);
367 result->b = RingElement::make_raw(R, frem);
368 return result;
369 } catch (const exc::engine_error& e)
370 {
371 ERROR(e.what());
372 return nullptr;
373 }
374}
375
377{
378 try
379 {
380 const Ring *R = a->get_ring();
381 if (R != b->get_ring()) return 0;
382 // if (a->is_zero())
383 // {
384 // if (b->is_zero()) return 0;
385 // return 1;
386 // }
387 // if (b->is_zero()) return -1;
388 return R->compare_elems(a->get_value(), b->get_value());
389 } catch (const exc::engine_error& e)
390 {
391 ERROR(e.what());
392 return -2;
393 }
394}
395
397{
398 try
399 {
400 const RingElement *result;
401
402 if (f->promote(S, result)) return result;
403 ERROR("cannot promote given ring element");
404 return nullptr;
405 } catch (const exc::engine_error& e)
406 {
407 ERROR(e.what());
408 return nullptr;
409 }
410}
411
412const RingElement /* or null */ *IM2_RingElement_lift(int *success_return,
413 const Ring *S,
414 const RingElement *f)
415{
416 try
417 {
418 const RingElement *result;
419
420 if (f->lift(S, result))
421 {
422 *success_return = 1;
423 return result;
424 }
425 // ERROR("cannot lift given ring element");
426 return nullptr;
427 } catch (const exc::engine_error& e)
428 {
429 ERROR(e.what());
430 return nullptr;
431 }
432}
433
435{
436 return a->is_homogeneous();
437}
438
440{
441 try
442 {
443 if (a->is_zero())
444 {
445 ERROR("the zero element has no degree");
446 return nullptr;
447 }
448
449 auto D = a->get_ring()->degree_monoid();
450 // TODO: do we need to manually free a->degree()?
451 return to_degree_vector(D, a->degree());
452 } catch (const exc::engine_error& e)
453 {
454 ERROR(e.what());
455 return nullptr;
456 }
457}
458
459const RingElement * /* or null */ rawRingElementAntipode(const RingElement *f)
460{
461 try
462 {
463 const Ring *R = f->get_ring();
464 return RingElement::make_raw(R, R->antipode(f->get_value()));
465 } catch (const exc::engine_error& e)
466 {
467 ERROR(e.what());
468 return nullptr;
469 }
470}
471
473/* The first component of the degree is used, unless the degree monoid is
474 trivial,
475 in which case the degree of each variable is taken to be 1.
476 Returns lo,hi degree. If the ring is not a graded ring or a polynomial ring
477 then (0,0) is returned.
478*/
479{
480 try
481 {
482 int lo, hi;
484 if (error()) return nullptr;
485 gmp_ZZpair p = new gmp_ZZpair_struct;
486 p->a = newitem(__mpz_struct);
487 p->b = newitem(__mpz_struct);
488 mpz_init_set_si(const_cast<mpz_ptr>(p->a), static_cast<long>(lo));
489 mpz_init_set_si(const_cast<mpz_ptr>(p->b), static_cast<long>(hi));
490 mpz_reallocate_limbs(const_cast<mpz_ptr>(p->a));
491 mpz_reallocate_limbs(const_cast<mpz_ptr>(p->b));
492 return p;
493 } catch (const exc::engine_error& e)
494 {
495 ERROR(e.what());
496 return nullptr;
497 }
498}
499
501 const RingElement *a,
502 int v,
503 int deg,
504 M2_arrayint wts)
505{
506 try
507 {
508 return a->homogenize(v, deg, M2_arrayint_to_stdvector<int>(wts));
509 } catch (const exc::engine_error& e)
510 {
511 ERROR(e.what());
512 return nullptr;
513 }
514}
515
516const RingElement /* or null */ *
518{
519 try
520 {
521 return a->homogenize(v, M2_arrayint_to_stdvector<int>(wts));
522 } catch (const exc::engine_error& e)
523 {
524 ERROR(e.what());
525 return nullptr;
526 }
527}
528
529const RingElement /* or null */ *IM2_RingElement_term(const Ring *R,
530 const RingElement *a,
531 const EngineMonomial *m)
532/* R must be a polynomial ring, and 'a' an element of the
533 coefficient ring of R. Returns a*m, if this is a valid
534 element of R. Returns NULL if not (with an error message). */
535{
536 try {
538 if (P != nullptr)
539 {
540 int nvars0 = P->n_vars();
542 if (K != nullptr && K != P->getCoefficients()) nvars0 -= K->n_vars();
543 exponents_t exp = newarray_atomic(int, nvars0);
544 varpower::to_expvector(nvars0, m->ints(), exp);
545 ring_elem val = P->make_logical_term(a->get_ring(), a->get_value(), exp);
546 return RingElement::make_raw(R,val);
547 }
548 auto Q = dynamic_cast<const M2FreeAlgebraOrQuotient *>(R);
549 if (Q != nullptr)
550 {
551 if (Q->coefficientRing() != a->get_ring())
552 {
553 ERROR("wrong coefficient ring");
554 return nullptr;
555 }
556 return RingElement::make_raw(Q,
557 Q->makeTerm(a->get_value(),
558 m->ints()));
559 }
560 ERROR("requires a polynomial ring");
561 return nullptr;
562 }
563 catch (exc::engine_error& e) {
564 ERROR(e.what());
565 return nullptr;
566 }
567}
568
570 int nvars, /* n variables in an outermost monoid */
571 const RingElement *a,
572 int lo,
573 int hi)
574/* Returns the sum of some monomials of 'a', starting at 'lo',
575 going up to 'hi'. If either of these are negative, they are indices
576 from the back of the polynomial.
577 'a' should be an element of a polynomial ring.
578*/
579{
580 return a->get_terms(nvars, lo, hi);
581}
582
584 const Ring *coeffRing, /* ring of the result */
585 const RingElement *a,
586 const EngineMonomial *m)
587/* Return (as an element of the coefficient ring) the coeff
588 of the monomial 'm'.
589 */
590{
591 try
592 {
593 return a->get_coeff(coeffRing, m);
594 } catch (const exc::engine_error& e)
595 {
596 ERROR(e.what());
597 return nullptr;
598 }
599}
600
602 const Ring *coeffRing, /* ring of the result */
603 const RingElement *a)
604{
605 try
606 {
607 return a->lead_coeff(coeffRing);
608 } catch (const exc::engine_error& e)
609 {
610 ERROR(e.what());
611 return nullptr;
612 }
613}
614
616 int nvars, /* number of variables in an outermost monoid */
617 const RingElement *a)
618{
619 try
620 {
621 return a->lead_monom(nvars);
622 } catch (const exc::engine_error& e)
623 {
624 ERROR(e.what());
625 return nullptr;
626 }
627}
628
630 int nvars, /* number of variables in an outermost monoid */
631 const RingElement *a)
632{
633 return a->n_terms(nvars);
634}
635
637 const Ring *coeffRing, /* ring of the result coefficients */
638 const RingElement *f)
639{
640 try {
642 if (P != nullptr)
643 {
644 return P->list_form(coeffRing, f->get_value());
645 }
646 const SchurRing2* S = f->get_ring()->cast_to_SchurRing2();
647 if (S != nullptr)
648 {
649 return S->list_form(coeffRing, f->get_value());
650 }
651 /* added by Frank */
652 const M2FreeAlgebra* ncP = dynamic_cast<const M2FreeAlgebra*>(f->get_ring());
653 if (ncP != nullptr)
654 {
655 return ncP->list_form(coeffRing, f->get_value());
656 }
657 /* added by Frank */
658 const M2FreeAlgebraQuotient* ncQ = dynamic_cast<const M2FreeAlgebraQuotient*>(f->get_ring());
659 if (ncQ != nullptr)
660 {
661 return ncQ->m2FreeAlgebra().list_form(coeffRing, f->get_value());
662 }
663 ERROR("expected a polynomial");
664 return nullptr;
665 }
666 catch (exc::engine_error& e) {
667 ERROR(e.what());
668 return nullptr;
669 }
670}
671
672engine_RawRingElementArray rawGetParts(const M2_arrayint wts,
673 const RingElement *f)
674/* Return an array of RingElement's, each having pure weight, and sorted by
675 strictly increasing weight value. The wt vector values must fit into
676 a word length integer. */
677{
678 try
679 {
681 if (P == nullptr)
682 {
683 ERROR("expected a polynomial");
684 return nullptr;
685 }
686 long relems_len;
687 ring_elem *relems = P->get_parts(
688 M2_arrayint_to_stdvector<int>(wts), f->get_value(), relems_len);
689 engine_RawRingElementArray result =
690 getmemarraytype(engine_RawRingElementArray, relems_len);
691 result->len = static_cast<int>(relems_len);
692 for (int i = 0; i < result->len; i++)
693 result->array[i] = RingElement::make_raw(P, relems[i]);
694 freemem(relems);
695 return result;
696 } catch (const exc::engine_error& e)
697 {
698 ERROR(e.what());
699 return nullptr;
700 }
701}
702
703#if 0
704void convolve(const Ring *R,
705 const VECTOR(ring_elem) &input_relems,
706 VECTOR(ring_elem) &output_relems,
707 int convolve_type)
708{
709 int n = input_relems.size() - 1; // array is 0..n, with the 0 part being ignored.
710 // first set [1, e1] := [1, h1].
711 output_relems[0] = input_relems[0];
712 output_relems[1] = input_relems[1];
713 for (int i=2; i<=n; i++)
714 {
715 ring_elem result = R->copy(input_relems[i]);
716 for (int j=i-1; j>=1; --j)
717 {
718 ring_elem f = R->mult(input_relems[j], output_relems[i-j]);
719 result = R->add(result,f);
720 }
721 output_relems[i] = result;
722 }
723}
724#endif
725
726void convolve(const PolyRing *R,
727 const VECTOR(ring_elem) & input_relems,
728 VECTOR(ring_elem) & output_relems,
729 int convolve_type)
730{
731 const Ring *K = R->getCoefficientRing();
732 ring_elem invn;
733 size_t n =
734 input_relems.size() - 1; // array is 0..n, with the 0 part being ignored.
735 // first set [1, e1] := [1, h1].
736 output_relems[0] = input_relems[0];
737 for (int i = 1; i <= n; i++)
738 {
739 // ASSUMPTION: input_relems[i] is either a variable or - of a variable
740 ring_elem result = R->copy(input_relems[i]);
741 if (convolve_type == 2) R->mult_coeff_to(K->from_long(-i), result);
742 for (int j = i - 1; j >= 1; --j)
743 {
744 ring_elem hr;
745 Nterm *g = input_relems[j];
746 if (g != nullptr)
747 {
748 hr.poly_val =
749 R->mult_by_term(output_relems[i - j], g->coeff, g->monom);
750 R->internal_add_to(result, hr);
751 }
752 }
753 if (convolve_type == 1)
754 {
755 invn = K->invert(K->from_long(i));
756 R->mult_coeff_to(invn, result);
757 }
758 output_relems[i] = result;
759 }
760}
761
763 int convolve_type)
764{
765 // convolve_type == 1: E_n = E_(n-1) * H_1 - E(n-2) * H_2 + ... + (-1)^n * H_n
766 // convolve_type == 2: n * E_n = E_(n-1) * H_1 - E(n-2) * H_2 + ... + (-1)^n *
767 // H_n
768 // others of interest? These are good for translating between symmetric
769 // functions of type E,H,P
770
771 // H_0 is ignored... (OR: should we instead shift everything: first entry of H
772 // is denoted H_1...?)
773
774 try
775 {
776 int len = H->len;
777 if (len <= 1)
778 {
779 ERROR("expected ring element array of length at least 2");
780 return nullptr;
781 }
782 const PolyRing *P = H->array[1]->get_ring()->cast_to_PolyRing();
783 if (P == nullptr)
784 {
785 ERROR("expected a polynomial ring");
786 return nullptr;
787 }
788 VECTOR(ring_elem) input_relems(len);
789 VECTOR(ring_elem) output_relems(len);
790 for (int i = 0; i < len; i++) input_relems[i] = H->array[i]->get_value();
791 convolve(P, input_relems, output_relems, convolve_type);
792
793 engine_RawRingElementArray result =
794 getmemarraytype(engine_RawRingElementArray, len);
795 result->len = len;
796 for (int i = 0; i < result->len; i++)
797 result->array[i] = RingElement::make_raw(P, output_relems[i]);
798
799 return result;
800 } catch (const exc::engine_error& e)
801 {
802 ERROR(e.what());
803 return nullptr;
804 }
805}
806
807const RingElement /* or null */ *rawGetPart(const M2_arrayint wts,
808 const RingElement *f,
809 M2_bool lobound_given,
810 M2_bool hibound_given,
811 long lobound,
812 long hibound)
813/* Return the sum of all of the terms t of f, which satisfy: lobound <= wt.t <=
814 hibound,
815 where, if lobound_given is false, then lobound is -infinity, and if
816 hibound_given
817 is false, then hibound is infinity. */
818{
819 try
820 {
822 if (P == nullptr)
823 {
824 ERROR("expected a polynomial");
825 return nullptr;
826 }
828 f->get_value(),
829 lobound_given,
830 hibound_given,
831 lobound,
832 hibound);
833 return RingElement::make_raw(P, g);
834 } catch (const exc::engine_error& e)
835 {
836 ERROR(e.what());
837 return nullptr;
838 }
839}
840
842/* if f is a variable of its ring, then the index of that variable is returned.
843 If f isnot a variable, then -1 is returned. */
844{
845 const Ring *R = f->get_ring();
846 return R->index_of_var(f->get_value());
847}
848
850/* The list of indices of variables which occur in f is returned. */
851{
852 const Ring *R = f->get_ring();
853 return R->support(f->get_value());
854}
855
856const RingElement /* or null */ *rawAssociateDivisor(const RingElement *f)
857{
858 try
859 {
860 const PolyRing *P = f->get_ring()->cast_to_PolyRing();
861 if (P == nullptr)
862 {
863 ERROR("expected an element of a polynomial ring");
864 return nullptr;
865 }
867 {
868 ERROR("cannot find preferred associates for this ring");
869 return nullptr;
870 }
873 } catch (const exc::engine_error& e)
874 {
875 ERROR(e.what());
876 return nullptr;
877 }
878}
879
880const RingElement /* or null */ *rawRingElementContent(const RingElement *f)
881// returns the content of f (as a matrix over the base coefficient ring)
882{
883 return f->content();
884}
885
887 const RingElement *f)
888// returns the polynomial which results after division by the content
889{
890 return f->remove_content();
891}
892
894 const RingElement *f,
895 const RingElement /* or null */ **result)
896// returns the content of f (as a matrix over the base coefficient ring)
897// result is set to the polynomial which results after division by the content
898{
899 return f->split_off_content(*result);
900}
901
903{
904 try
905 {
906 return a->numerator();
907 } catch (const exc::engine_error& e)
908 {
909 ERROR(e.what());
910 return nullptr;
911 }
912}
913
915 const RingElement *a)
916{
917 try
918 {
919 return a->denominator();
920 } catch (const exc::engine_error& e)
921 {
922 ERROR(e.what());
923 return nullptr;
924 }
925}
926
927const RingElement /* or null */ *IM2_RingElement_fraction(const Ring *R,
928 const RingElement *a,
929 const RingElement *b)
930{
931 try
932 {
933 const RingElement *f = a->fraction(R, b);
934 if (error()) return nullptr;
935 return f;
936 } catch (const exc::engine_error& e)
937 {
938 ERROR(e.what());
939 return nullptr;
940 }
941}
942
944{
945 try
946 {
947 const SchurRing *S = f->get_ring()->cast_to_SchurRing();
948 if (S == nullptr)
949 {
950 ERROR("expected a polynomial over a Schur ring");
951 return nullptr;
952 }
954 return result.get_mpz();
955 } catch (const exc::engine_error& e)
956 {
957 ERROR(e.what());
958 return nullptr;
959 }
960}
961
962const RingElement /* or null */ *rawSchurSnTensorMult(const RingElement *a,
963 const RingElement *b)
964/* the tensor multiplication function in SchurSnRing */
965{
966 try
967 {
968 const SchurSnRing *R = a->get_ring()->cast_to_SchurSnRing();
969 if (R == nullptr)
970 {
971 ERROR("expected a SchurSn ring element");
972 return nullptr;
973 }
974 if (R != b->get_ring())
975 {
976 ERROR("expected SchurSn ring elements");
977 return nullptr;
978 }
980 return RingElement::make_raw(R, result);
981 } catch (const exc::engine_error& e)
982 {
983 ERROR(e.what());
984 return nullptr;
985 }
986}
987
988const RingElement /* or null */ *rawSchurFromPartition(const Ring *R,
989 M2_arrayint part)
990{
991 // R should be a SchurRing2
992 // part should be a partition: a weakly descending list of integers (for now,
993 // non-negative)
994 // if R has a limit on the size of partitions, then
995 try
996 {
997 const SchurRing2 *S = R->cast_to_SchurRing2();
998 if (S == nullptr)
999 {
1000 ERROR("expected a Schur ring");
1001 return nullptr;
1002 }
1003 // Check that part is a partition, and that the number of parts is <=
1004 // number allowed
1005 if (!S->is_valid_partition(part)) return nullptr;
1006 ring_elem result = S->from_partition(part);
1007 return RingElement::make_raw(S, result);
1008 } catch (const exc::engine_error& e)
1009 {
1010 ERROR(e.what());
1011 return nullptr;
1012 }
1013}
1014/* Special routines for tower rings */
1015
1016int rawDegree(int v, const RingElement *f)
1017/* Returns -1 if 0 or not implemented for a given ring. For now, valid only for
1018 * tower rings */
1019{
1020 const Tower *R = f->get_ring()->cast_to_Tower();
1021 if (R == nullptr) return -1;
1022 return R->degreeInVariable(v, f->get_value());
1023}
1024
1025int rawExtensionDegree(int firstvar, const Ring *R1)
1026/* Currently only valid for tower rings. Others return 0. */
1027{
1028 const Tower *R = R1->cast_to_Tower();
1029 if (R == nullptr) return 0;
1030 if (firstvar < 0)
1031 {
1032 ERROR("use rawCharacteristic to find the characteristic");
1033 return -1;
1034 }
1035 return R->extension_degree(firstvar);
1036}
1037
1038const RingElement /* or null */ *rawDiff(int v, const RingElement *f)
1039{
1040 const Tower *R = f->get_ring()->cast_to_Tower();
1041 if (R == nullptr)
1042 {
1043 ERROR("not implemented for this ring");
1044 return nullptr;
1045 }
1046 return RingElement::make_raw(R, R->differentiate(v, f->get_value()));
1047}
1048
1049const RingElement /* or null */ *rawLowerP(const RingElement *f)
1050{
1051 const Tower *R = f->get_ring()->cast_to_Tower();
1052 if (R == nullptr)
1053 {
1054 ERROR("not implemented for this ring");
1055 return nullptr;
1056 }
1057 return RingElement::make_raw(R, R->lowerP(f->get_value()));
1058}
1059
1060const RingElement /* or null */ *rawPowerMod(const RingElement *f,
1061 mpz_srcptr n,
1062 const RingElement *g)
1063{
1064 const Tower *R = f->get_ring()->cast_to_Tower();
1065 if (R == nullptr)
1066 {
1067 ERROR("not implemented for this ring");
1068 return nullptr;
1069 }
1070 if (g->get_ring() != R)
1071 {
1072 ERROR("expected elements in the same ring");
1073 return nullptr;
1074 }
1075 return RingElement::make_raw(R,
1076 R->power_mod(f->get_value(), n, g->get_value()));
1077}
1078
1079// Local Variables:
1080// indent-tabs-mode: nil
1081// End:
Variable-length sparse (variable, exponent) encoding of monomials.
exponents::Exponents exponents_t
Ring-shaped wrapper that exposes a non-commutative FreeAlgebra to the rest of the engine.
Ring-shaped façade around a non-commutative quotient algebra.
M2::ARingCC — machine-precision complex numbers (pair of doubles).
M2::ARingCCC — arbitrary-precision complex numbers (pair of MPFR floats).
M2::ARingCCi — certified complex intervals as Cartesian rectangles of MPFI intervals.
M2::ARingRR — machine-precision real numbers (IEEE 754 double).
M2::ARingRRR — arbitrary-precision real numbers backed by MPFR.
M2::ARingRRi — certified real intervals [a, b] with MPFR endpoints, MPFI arithmetic.
ConcreteRing<RingType> — the templated bridge between aring and the legacy Ring API.
Shared base of the aring framework (namespace M2) that unifies the engine's coefficient rings.
Append-only GC-backed byte buffer used throughout the engine for text output.
Engine-side immutable monomial value type wrapping a varpower- encoded exponent vector.
Definition monomial.hpp:61
unsigned int hash() const
Definition hash.hpp:70
static void to_expvector(int n, ConstExponents a, exponents::Exponents result)
int discrete_log(ring_elem a) const
Definition GF.cpp:162
Engine-side finite field GF(p^n) built on top of (Z/p)[t] / f(t) for a primitive element of the resul...
Definition GF.hpp:62
elem ElementType
Definition aring-CC.hpp:81
aring-style adapter for arbitrary-precision real numbers, backed by MPFR.
Definition aring-RRR.hpp:70
virtual unsigned long get_precision() const
virtual engine_RawArrayPairOrNull list_form(const Ring *coeffR, const ring_elem f) const
Concrete Ring wrapper around an owned FreeAlgebra (no quotient).
Abstract Ring subclass that lifts either a FreeAlgebra or a FreeAlgebraQuotient into the engine's Rin...
const M2FreeAlgebra & m2FreeAlgebra() const
Concrete Ring wrapper around an owned FreeAlgebraQuotient (the quotient counterpart of M2FreeAlgebra)...
void internal_add_to(ring_elem &f, ring_elem &g) const
Definition poly.cpp:675
ring_elem preferred_associate_divisor(ring_elem ff) const
Definition poly.cpp:459
virtual void mult_coeff_to(ring_elem a, ring_elem &f) const
Definition poly.cpp:799
virtual ring_elem mult_by_term(const ring_elem f, const ring_elem c, const_monomial m) const
Definition poly.cpp:781
virtual ring_elem copy(const ring_elem f) const
Definition poly.cpp:653
Concrete PolyRingFlat subclass implementing ordinary commutative polynomial rings K[x_1,...
Definition poly.hpp:64
const Ring * getCoefficientRing() const
Definition polyring.hpp:200
virtual ring_elem get_part(const std::vector< int > &wts, const ring_elem f, bool lobound_given, bool hibound_given, long lobound, long hibound) const =0
virtual const Ring * getCoefficients() const
Definition polyring.hpp:277
virtual ring_elem * get_parts(const std::vector< int > &wts, const ring_elem f, long &result_len) const =0
virtual ring_elem make_logical_term(const Ring *coeffR, const ring_elem a, const_exponents exp) const =0
virtual engine_RawArrayPairOrNull list_form(const Ring *coeffR, const ring_elem f) const =0
int n_vars() const
Definition polyring.hpp:196
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual bool is_ZZ() const
Definition ring.hpp:171
virtual ring_elem var(int v) const
Definition ring.cpp:97
virtual const SchurSnRing * cast_to_SchurSnRing() const
Definition ring.hpp:279
virtual bool from_BigReal(gmp_RR a, ring_elem &result) const
Definition ring.cpp:250
virtual M2::RingID ringID() const
Definition ring.hpp:164
virtual bool from_Interval(gmp_RRi a, ring_elem &result) const
Definition ring.cpp:257
virtual const SchurRing2 * cast_to_SchurRing2() const
Definition ring.hpp:277
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
virtual bool from_ComplexInterval(gmp_CCi z, ring_elem &result) const
Definition ring.cpp:264
virtual bool has_associate_divisors() const
Definition ring.hpp:228
virtual bool is_equal(const ring_elem f, const ring_elem g) const =0
virtual const PolyRing * cast_to_PolyRing() const
Definition ring.hpp:245
virtual ring_elem remainderAndQuotient(const ring_elem f, const ring_elem g, ring_elem &quot) const
Definition ring.cpp:223
virtual bool from_BigComplex(gmp_CC z, ring_elem &result) const
Definition ring.cpp:243
virtual ring_elem invert(const ring_elem f) const =0
virtual ring_elem from_long(long n) const =0
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
virtual const RingElement * getGenerator() const
Definition ring.hpp:305
virtual const GF * cast_to_GF() const
Definition ring.hpp:239
virtual ring_elem copy(const ring_elem f) const =0
virtual ring_elem antipode(ring_elem f) const
Definition ring.hpp:517
virtual int index_of_var(const ring_elem a) const
Definition ring.cpp:423
virtual bool is_zero(const ring_elem f) const =0
virtual long discreteLog(const ring_elem &a) const
Definition ring.hpp:314
virtual bool is_QQ() const
Definition ring.hpp:172
virtual int compare_elems(const ring_elem f, const ring_elem g) const =0
virtual ring_elem from_int(mpz_srcptr n) const =0
virtual ring_elem mult(const ring_elem f, const ring_elem g) const =0
virtual bool isFinitePrimeField() const
Definition ring.hpp:169
virtual const SchurRing * cast_to_SchurRing() const
Definition ring.hpp:275
virtual M2_arrayint support(const ring_elem a) const
Definition ring.cpp:429
const Monoid * degree_monoid() const
Definition ring.cpp:13
virtual const Z_mod * cast_to_Z_mod() const
Definition ring.hpp:237
virtual bool from_rational(const mpq_srcptr q, ring_elem &result) const =0
virtual const Tower * cast_to_Tower() const
Definition ring.hpp:241
void text_out(buffer &o) const
Definition relem.cpp:142
RingElement * fraction(const Ring *R, const RingElement *bottom) const
Definition relem.cpp:388
bool is_homogeneous() const
Definition relem.cpp:225
EngineMonomial * lead_monom(int nvars) const
Definition relem.cpp:197
const_monomial degree() const
Definition relem.hpp:140
RingElement * denominator() const
Definition relem.cpp:374
ring_elem get_value() const
Definition relem.hpp:79
bool promote(const Ring *S, const RingElement *&result) const
Definition relem.cpp:305
const RingElement * split_off_content(const RingElement *&result) const
Definition relem.cpp:351
bool is_zero() const
Definition relem.hpp:167
int n_terms(int nvars) const
Definition relem.cpp:25
RingElement * lead_coeff(const Ring *coeffR) const
Definition relem.cpp:165
RingElement * get_terms(int nvars, int lo, int hi) const
Definition relem.cpp:147
RingElement * numerator() const
Definition relem.cpp:360
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
void degree_weights(const std::vector< int > &wts, int &lo, int &hi) const
Definition relem.cpp:227
const RingElement * remove_content() const
Definition relem.cpp:345
RingElement * get_coeff(const Ring *coeffR, const EngineMonomial *m) const
Definition relem.cpp:185
bool lift(const Ring *S, const RingElement *&result) const
Definition relem.cpp:321
const RingElement * content() const
Definition relem.cpp:337
const Ring * get_ring() const
Definition relem.hpp:81
RingElement * homogenize(int v, const std::vector< int > &wts) const
Definition relem.cpp:245
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
bool is_valid_partition(M2_arrayint part, bool set_error=true) const
Definition schur2.cpp:157
engine_RawArrayPairOrNull list_form(const Ring *coeffR, const ring_elem f) const
Definition schur2.cpp:682
ring_elem from_partition(M2_arrayint part) const
Definition schur2.cpp:184
Refactored Schur (symmetric-function) ring whose elements are schur_poly sums of partitions over a co...
Definition schur2.hpp:152
void dimension(const int *exp, mpz_t result) const
Definition schur.cpp:314
PolyRing subclass implementing the Schur (symmetric-function) ring whose monomials are partitions and...
Definition schur.hpp:82
ring_elem tensor_mult(const ring_elem f, const ring_elem g) const
Definition schurSn.cpp:18
SchurRing2 subclass implementing the symmetric-group character ring (the "Schur ring of `S_n`"),...
Definition schurSn.hpp:51
ring_elem lowerP(const ring_elem f) const
Definition tower.cpp:419
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
int degreeInVariable(int var, const ring_elem f) const
Definition tower.cpp:388
int extension_degree(int nvars) const
Definition tower.cpp:402
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
Engine-side Z/p ring for small primes (p < 32767), using a discrete-log (Zech) representation.
Definition ZZp.hpp:63
M2_string to_string()
Definition buffer.cpp:20
int error()
Definition error.c:48
Engine error-reporting primitives: ERROR, INTERNAL_ERROR, error, error_message.
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
gmp_CCi moveTo_gmpCCi(gmp_CCimutable _z)
Definition gmp-util.h:174
mpfr_srcptr moveTo_gmpRR(mpfr_ptr _z)
Definition gmp-util.h:153
mpfi_srcptr moveTo_gmpRRi(mpfi_ptr _z)
Definition gmp-util.h:159
void mpz_reallocate_limbs(mpz_ptr _z)
Definition gmp-util.h:46
int p
@ ring_CCC
Definition aring.hpp:90
@ ring_RR
Definition aring.hpp:87
@ ring_RRR
Definition aring.hpp:89
@ ring_RRi
Definition aring.hpp:91
@ ring_CCi
Definition aring.hpp:92
M2_arrayint to_degree_vector(const Monoid *M, const_monomial d)
Definition monoid.cpp:46
void freemem(void *s)
Definition m2-mem.cpp:103
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemarraytype(S, len)
Definition m2-mem.h:142
#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
engine_RawRingElementArray engine_RawRingElementArrayOrNull
Definition m2-types.h:176
mpfr_ptr gmp_RRmutable
Definition m2-types.h:150
mpfi_ptr gmp_RRimutable
Definition m2-types.h:152
mpq_srcptr gmp_QQorNull
Definition m2-types.h:146
gmp_CCi gmp_CCiorNull
Definition m2-types.h:163
mpfr_srcptr gmp_RRorNull
Definition m2-types.h:149
char M2_bool
Definition m2-types.h:82
gmp_ZZpair gmp_ZZpairOrNull
Definition m2-types.h:211
gmp_CC gmp_CCorNull
Definition m2-types.h:157
mpfi_srcptr gmp_RRi
Definition m2-types.h:153
mpz_srcptr gmp_ZZ
Definition m2-types.h:141
mpz_srcptr gmp_ZZorNull
Definition m2-types.h:142
struct engine_RawRingElementPair_struct * engine_RawRingElementPair
Definition m2-types.h:206
struct gmp_ZZpair_struct * gmp_ZZpair
Definition m2-types.h:210
engine_RawArrayPair engine_RawArrayPairOrNull
Definition m2-types.h:184
mpfi_srcptr gmp_RRiorNull
Definition m2-types.h:154
struct gmp_CCi_struct * gmp_CCi
Definition m2-types.h:162
struct gmp_CCimutable_struct * gmp_CCimutable
Definition m2-types.h:165
Engine-boundary C API for constructing and inspecting Monoid objects.
Monoid — variable count, naming, grading, and monomial order of a polynomial ring.
EngineMonomial — opaque single-monomial value type used at the engine boundary.
Definition aring-CC.cpp:3
#define newitem(T)
Definition newdelete.hpp:86
#define VECTOR(T)
Definition newdelete.hpp:78
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
our_new_delete — per-class opt-in routing of new / delete through bdwgc.
Concrete commutative PolyRing — standard polynomial ring inheriting from PolyRingFlat.
PolynomialRing — abstract polynomial-ring base, the engine's most-reused class.
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
Ring — the legacy abstract base class for every coefficient and polynomial ring.
ring_elem — the universal value type carried by every Ring* in the engine.
M2_bool IM2_RingElement_is_equal(const RingElement *a, const RingElement *b)
M2_arrayint rawRingElementIndices(const RingElement *f)
int IM2_RingElement_index_if_var(const RingElement *f)
const RingElement * IM2_RingElement_denominator(const RingElement *a)
const RingElement * IM2_RingElement_get_coeff(const Ring *coeffRing, const RingElement *a, const EngineMonomial *m)
const RingElement * rawRingElementRemoveContent(const RingElement *f)
const RingElement * IM2_RingElement_term(const Ring *R, const RingElement *a, const EngineMonomial *m)
const EngineMonomial * IM2_RingElement_lead_monomial(int nvars, const RingElement *a)
M2_bool IM2_RingElement_is_zero(const RingElement *a)
const RingElement * rawLowerP(const RingElement *f)
const RingElement * IM2_RingElement_promote(const Ring *S, const RingElement *f)
gmp_QQorNull IM2_RingElement_to_rational(const RingElement *a)
engine_RawRingElementPair IM2_RingElement_divmod(const RingElement *a, const RingElement *b)
const RingElement * IM2_RingElement_from_ComplexInterval(const Ring *R, gmp_CCi z)
const RingElement * IM2_RingElement_homogenize(const RingElement *a, int v, M2_arrayint wts)
const RingElement * IM2_RingElement_from_BigComplex(const Ring *R, gmp_CC z)
const RingElement * IM2_RingElement_get_terms(int nvars, const RingElement *a, int lo, int hi)
const RingElement * IM2_RingElement_from_Integer(const Ring *R, gmp_ZZ d)
const RingElement * rawGetPart(const M2_arrayint wts, const RingElement *f, M2_bool lobound_given, M2_bool hibound_given, long lobound, long hibound)
const Ring * IM2_RingElement_ring(const RingElement *a)
const RingElement * IM2_RingElement_lead_coeff(const Ring *coeffRing, const RingElement *a)
const RingElement * IM2_RingElement_from_Interval(const Ring *R, gmp_RRi z)
gmp_ZZpairOrNull rawWeightRange(M2_arrayint wts, const RingElement *a)
void convolve(const PolyRing *R, const VECTOR(ring_elem) &input_relems, VECTOR(ring_elem) &output_relems, int convolve_type)
int rawDegree(int v, const RingElement *f)
unsigned int rawRingElementHash(const RingElement *a)
engine_RawRingElementArray rawGetParts(const M2_arrayint wts, const RingElement *f)
const RingElement * rawMultiplicativeGenerator(const Ring *R)
engine_RawRingElementArrayOrNull rawConvolve(engine_RawRingElementArray H, int convolve_type)
gmp_RRiorNull IM2_RingElement_to_Interval(const RingElement *a)
const RingElement * IM2_RingElement_from_rational(const Ring *R, mpq_srcptr r)
gmp_CCiorNull IM2_RingElement_to_ComplexInterval(const RingElement *a)
M2_string IM2_RingElement_to_string(const RingElement *f)
int rawRingElementCompare(const RingElement *a, const RingElement *b)
gmp_RRorNull IM2_RingElement_to_BigReal(const RingElement *a)
const RingElement * rawRingElementSplitContent(const RingElement *f, const RingElement **result)
const RingElement * rawRingElementAntipode(const RingElement *f)
const RingElement * IM2_RingElement_fraction(const Ring *R, const RingElement *a, const RingElement *b)
const RingElement * rawDiff(int v, const RingElement *f)
int IM2_RingElement_n_terms(int nvars, const RingElement *a)
const RingElement * IM2_RingElement_from_BigReal(const Ring *R, gmp_RR z)
const RingElement * rawSchurFromPartition(const Ring *R, M2_arrayint part)
long rawDiscreteLog(const RingElement *h)
const RingElement * IM2_RingElement_make_var(const Ring *R, int v)
const RingElement * rawSchurSnTensorMult(const RingElement *a, const RingElement *b)
engine_RawArrayPairOrNull IM2_RingElement_list_form(const Ring *coeffRing, const RingElement *f)
const RingElement * IM2_RingElement_homogenize_to_degree(const RingElement *a, int v, int deg, M2_arrayint wts)
const RingElement * rawPowerMod(const RingElement *f, mpz_srcptr n, const RingElement *g)
const RingElement * rawAssociateDivisor(const RingElement *f)
const RingElement * rawRingElementContent(const RingElement *f)
M2_arrayint IM2_RingElement_multidegree(const RingElement *a)
const RingElement * IM2_RingElement_lift(int *success_return, const Ring *S, const RingElement *f)
M2_bool IM2_RingElement_is_graded(const RingElement *a)
const RingElement * IM2_RingElement_numerator(const RingElement *a)
gmp_ZZorNull rawSchurDimension(const RingElement *f)
gmp_ZZorNull IM2_RingElement_to_Integer(const RingElement *a)
int rawExtensionDegree(int firstvar, const Ring *R1)
gmp_CCorNull IM2_RingElement_to_BigComplex(const RingElement *a)
Engine-boundary C API for constructing, querying, and operating on RingElement values.
SchurRing2 — refactored Schur ring with length-prefixed partitions and an explicit Ring base.
SchurRing — symmetric-function ring with Schur-basis multiplication via Littlewood-Richardson.
SchurSnRing — SchurRing2 subclass intended for symmetric-group representation rings (Kronecker produc...
ring_elem coeff
Definition ringelem.hpp:158
int monom[1]
Definition ringelem.hpp:160
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
Legacy Tower — Ring-derived iterated extension of Z/p (pre-aring).
mpfr_srcptr get_mpfr() const
Definition ringelem.hpp:130
Nterm * poly_val
Definition ringelem.hpp:86
mpfi_srcptr get_mpfi() const
Definition ringelem.hpp:131
double get_double() const
Definition ringelem.hpp:126
mpq_srcptr get_mpq() const
Definition ringelem.hpp:129
cc_srcptr get_cc() const
Definition ringelem.hpp:133
cci_srcptr get_cci() const
Definition ringelem.hpp:134
mpz_srcptr get_mpz() const
Definition ringelem.hpp:127
std::vector< T > M2_arrayint_to_stdvector(M2_arrayint arr)
Definition util.hpp:96
Conversion helpers between M2 boundary types and standard C++ containers.