Macaulay2 Engine
Loading...
Searching...
No Matches

◆ rawRoots()

engine_RawRingElementArrayOrNull rawRoots ( const RingElement * g,
long prec,
int unique )

Definition at line 54 of file polyroots.cpp.

57{
58 (void) unique;
59 const Ring *R = p->get_ring();
61 const Monoid *M = P->getMonoid();
62 if (P == nullptr) {
63 ERROR("expected a polynomial ring");
64 return nullptr;
65 }
66 if (P->n_vars() != 1) {
67 ERROR("expected a univariate polynomial ring");
68 return nullptr;
69 }
70 if (p->is_zero()) {
71 ERROR("expected a nonzero polynomial");
72 return nullptr;
73 }
74 const Ring *K = P->getCoefficients();
75 int lodeg,hideg; // lowest,highest degree
76 P->degree_of_var(0,p->get_value(),lodeg,hideg);
77 if (prec == -1)
78 prec = (K->get_precision() == 0 ? 53 : K->get_precision());
79
80 mps_context *s = mps_context_new ();
81 mps_monomial_poly *mps_p = mps_monomial_poly_new (s, hideg);
82 mps_context_select_algorithm(s, MPS_ALGORITHM_SECULAR_GA);
83
84 const auto ID = K->ringID();
85 for (Nterm *t = p->get_value(); t != nullptr; t = t->next) {
86 int deg;
87 M->to_expvector(t->monom, &deg); // number of vars = 1
88 if (ID==M2::ring_RR or ID==M2::ring_CC) {
90 if (ID==M2::ring_RR) {
91 cc.re = t->coeff.get_double();
92 cc.im = 0;
93 } else cc = *t->coeff.get_cc_doubles();
94 mps_monomial_poly_set_coefficient_d (s, mps_p, deg, cc.re, cc.im);
95 } else if (ID==M2::ring_RRR or ID==M2::ring_CCC) {
96 mpc_t mpc_cc;
97 mpc_init2(mpc_cc,K->get_precision());
98 if (ID==M2::ring_RRR) {
99 mpfr_get_f(mpc_cc->r,t->coeff.get_mpfr(),MPFR_RNDN);
100 } else {
101 mpfr_get_f(mpc_cc->r,&t->coeff.get_cc()->re,MPFR_RNDN);
102 mpfr_get_f(mpc_cc->i,&t->coeff.get_cc()->im,MPFR_RNDN);
103 }
104 mps_monomial_poly_set_coefficient_f (s, mps_p, deg, mpc_cc);
105 mpc_clear(mpc_cc);
106 } else if ((ID==M2::ring_old and K->is_ZZ()) or ID==M2::ring_QQ) {
107 mpq_t q, zero;
108 mpq_init(zero);
109 mpq_init(q);
110 if (ID==M2::ring_QQ)
111 mpq_set(q, t->coeff.get_mpq());
112 else mpq_set_z(q, t->coeff.get_mpz());
113 mps_monomial_poly_set_coefficient_q(s, mps_p, deg, q, zero);
114 mpq_clear(q);
115 mpq_clear(zero);
116 } else {
117 ERROR("'roots' expects coefficients in ZZ, QQ, RR or CC");
118 return nullptr;
119 }
120 }
121
122 /* Set the input polynomial */
123 mps_context_set_input_poly (s, MPS_POLYNOMIAL (mps_p));
124 mps_context_set_output_prec (s, prec);
125 mps_context_set_output_goal (s, MPS_OUTPUT_GOAL_APPROXIMATE);
126
127 /* Actually solve the polynomial */
128 mps_mpsolve (s);
129
130 // result to be returned
132 result = getmemarraytype(engine_RawRingElementArray, hideg);
133 result->len = static_cast<int>(hideg);
134
136 if (prec <= 53) {
137 /* Allocate space to hold the results. We check only floating point results in here */
138 cplx_t *result_mps = cplx_valloc (hideg);
139
140 /* Save roots computed in the vector results */
141 mps_context_get_roots_d (s, &result_mps, nullptr);
142
143 /* Print out roots */
144 // for (int i = 0; i < hideg; i++) {
145 // cplx_out_str (stdout, result_mps[i]);
146 // printf ("\n");
147 // }
148
150 // copy to mps_result to result
151
152 const Ring *C = IM2_Ring_CCC(prec);
153 for (int i = 0; i < hideg; i++) {
154 auto& mps_root = result_mps[i];
155 ring_elem m2_root;
156 C->from_complex_double(cplx_Re(mps_root), cplx_Im(mps_root),
157 m2_root);
158 result->array[i] = RingElement::make_raw(C, m2_root);
159 }
160
161 free (result_mps);
162 } else { // prec > 53
163 mpc_t *roots = nullptr;
164 rdpe_t *radii = nullptr;
165
166 mps_context_get_roots_m (s, &roots, &radii);
167 /* Sort roots in the order of increasing real part */
168 //sort_roots(hideg, roots, radii);
169 // for (int i = 0; i < hideg; i++) {
170 // mpc_out_str (stdout, 10, prec/4, roots[i]);
171 // printf ("\n");
172 // }
173
174 const Ring *C = IM2_Ring_CCC(prec);
175 const M2::ARingCCC C0(prec);
176
177 M2::ARingCCC::Element cc (C0);
178 for (int i = 0; i < hideg; i++) {
179 auto& mps_root = roots[i];
180 mpfr_set_f(&cc.value().re,mpc_Re(mps_root),MPFR_RNDN);
181 mpfr_set_f(&cc.value().im,mpc_Im(mps_root),MPFR_RNDN);
182 ring_elem m2_root;
183 C0.to_ring_elem(m2_root, cc);
184 result->array[i] = RingElement::make_raw(C, m2_root);
185 }
186
187 free(roots);
188 free(radii);
189 }
190
191 mps_monomial_poly_free(s, (mps_polynomial *)mps_p);
192 mps_context_free(s);
193 return result;
194}
aring-style adapter for arbitrary-precision complex numbers, stored as (MPFR, MPFR) pairs.
Definition aring-CCC.hpp:71
void to_expvector(const_monomial m, exponents_t result_exp) const
Definition monoid.cpp:747
Engine-side commutative monomial monoid: variable names, ordering, multidegree machinery,...
Definition monoid.hpp:89
virtual const Monoid * getMonoid() const
Definition polyring.hpp:282
virtual const Ring * getCoefficients() const
Definition polyring.hpp:277
virtual void degree_of_var(int n, const ring_elem a, int &lo, int &hi) 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 M2::RingID ringID() const
Definition ring.hpp:164
virtual unsigned long get_precision() const
Definition ring.cpp:438
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
virtual bool from_complex_double(double re, double im, ring_elem &result) const
Definition ring.cpp:276
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
xxx xxx xxx
Definition ring.hpp:102
int p
int zero
@ ring_CCC
Definition aring.hpp:90
@ ring_old
refers to all rings which are not ConcreteRing's.
Definition aring.hpp:94
@ ring_RR
Definition aring.hpp:87
@ ring_RRR
Definition aring.hpp:89
@ ring_QQ
Definition aring.hpp:79
@ ring_CC
Definition aring.hpp:88
const Ring * IM2_Ring_CCC(unsigned long prec)
Definition ring.cpp:108
void size_t s
Definition m2-mem.cpp:271
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemarraytype(S, len)
Definition m2-mem.h:142
engine_RawRingElementArray engine_RawRingElementArrayOrNull
Definition m2-types.h:176
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156

References Ring::cast_to_PolynomialRing(), PolynomialRing::degree_of_var(), ERROR, Ring::from_complex_double(), Ring::get_precision(), PolynomialRing::getCoefficients(), getmemarraytype, PolynomialRing::getMonoid(), cc_doubles_struct::im, IM2_Ring_CCC(), Ring::is_ZZ(), RingElement::make_raw(), PolynomialRing::n_vars(), p, cc_doubles_struct::re, result(), M2::ring_CC, M2::ring_CCC, M2::ring_old, M2::ring_QQ, M2::ring_RR, M2::ring_RRR, Ring::ringID(), s, Monoid::to_expvector(), M2::ARingCCC::to_ring_elem(), and zero.