carl  24.04
Computer ARithmetic Library
Resultant.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "Content.h"
4 #include "Degree.h"
5 #include "Derivative.h"
6 #include "Division.h"
7 #include "Power.h"
8 #include "PrimitivePart.h"
9 #include "Remainder.h"
11 
12 #include <list>
13 #include <vector>
14 
15 namespace carl {
17  Generic,
18  Lazard,
19  Ducos,
20  Default = Lazard
21 };
22 
23 template<typename Coeff>
24 class UnivariatePolynomial;
25 
26 template<typename Coeff>
27 std::list<UnivariatePolynomial<Coeff>> subresultants(const UnivariatePolynomial<Coeff>&, const UnivariatePolynomial<Coeff>&, SubresultantStrategy = SubresultantStrategy::Default);
28 template<typename Coeff>
29 std::vector<UnivariatePolynomial<Coeff>> principalSubresultantsCoefficients(const UnivariatePolynomial<Coeff>&, const UnivariatePolynomial<Coeff>&, SubresultantStrategy = SubresultantStrategy::Default);
30 template<typename Coeff>
31 UnivariatePolynomial<Coeff> resultant(const UnivariatePolynomial<Coeff>&, const UnivariatePolynomial<Coeff>&, SubresultantStrategy = SubresultantStrategy::Default);
32 template<typename Coeff>
33 UnivariatePolynomial<Coeff> discriminant(const UnivariatePolynomial<Coeff>&, SubresultantStrategy = SubresultantStrategy::Default);
34 } // namespace carl
35 
36 #include "../UnivariatePolynomial.h"
37 
38 namespace carl {
39 
40 /**
41  * Implements a subresultants algorithm with optimizations described in @cite Ducos00 .
42  * @param pol1 First polynomial.
43  * @param pol2 First polynomial.
44  * @param strategy Strategy.
45  * @return Subresultants of pol1 and pol2.
46  */
47 template<typename Coeff>
48 std::list<UnivariatePolynomial<Coeff>> subresultants(
49  const UnivariatePolynomial<Coeff>& pol1,
50  const UnivariatePolynomial<Coeff>& pol2,
52  /* The algorithm consists of three parts:
53  * Part 1: Initialization, i.e. preparation of the input so that the requirements of the core algorithm in parts 2 and 3 are met.
54  * Part 2: First part of the main loop. If the two subresultants which were added before (initially the two inputs) differ by more
55  * than 1 in their degree, an intermediate subresultant is computed by reducing the last one added with the leading coefficient
56  * of the one before this one.
57  * Part 3: Second part of the main loop. The pseudo remainder of the last two subresultants (the one possibly added in Part 2 disregarded)
58  * is computed and added to the subresultant sequence.
59  */
60 
61  /* Part 1
62  * Check and normalize input, initialize local variables.
63  */
64  assert(pol1.main_var() == pol2.main_var());
65  CARL_LOG_TRACE("carl.core.resultant", "subresultants(" << pol1 << ", " << pol2 << ")");
66  std::list<UnivariatePolynomial<Coeff>> subresultants;
67  Variable variable = pol1.main_var();
68 
69  assert(!carl::is_zero(pol1));
70  assert(!carl::is_zero(pol2));
71  // We initialize p and q with pol1 and pol2.
72  UnivariatePolynomial<Coeff> p(pol1), q(pol2);
73 
74  // pDeg >= qDeg shall hold, so switch if it does not hold
75  if (p.degree() < q.degree()) {
76  std::swap(p, q);
77  }
78  CARL_LOG_TRACE("carl.core.resultant", "p = " << p);
79  CARL_LOG_TRACE("carl.core.resultant", "q = " << q);
80 
81  subresultants.push_front(p);
82  if (carl::is_zero(q)) {
83  CARL_LOG_TRACE("carl.core.resultant", "q is Zero.");
84  return subresultants;
85  }
86  subresultants.push_front(q);
87 
88  // SPECIAL CASE: both, p and q, are constant
89  if (is_constant(q)) {
90  CARL_LOG_TRACE("carl.core.resultant", "q is constant.");
91  return subresultants;
92  }
93 
94  // Explicitly check preconditions
95  assert(p.degree() >= q.degree());
96  assert(q.degree() >= 1);
97 
98  // BUG in Duco's article(?):
99  //ex subresLcoeff = GiNaC::pow( a.lcoeff(), a.degree() - b.degree() ); // initialized on the basis of the smaller-degree polynomial
100  //Coeff subresLcoeff(a.lcoeff()); // initialized on the basis of the smaller-degree polynomial
101  Coeff subresLcoeff = carl::pow(q.lcoeff(), p.degree() - q.degree());
102  CARL_LOG_TRACE("carl.core.resultant", "subresLcoeff = " << subresLcoeff);
103 
105  q = pseudo_remainder(p, -q);
106  p = tmp;
107  CARL_LOG_TRACE("carl.core.resultant", "q = pseudo_remainder(p,-q) = " << q);
108  CARL_LOG_TRACE("carl.core.resultant", "p = " << p);
109  //CARL_LOG_TRACE("carl.core.resultant", "p = q");
110  //CARL_LOG_TRACE("carl.core.resultant", "q = pseudo_remainder(p,-q)");
111 
112  /* Parts 2 and 3
113  * Main loop filling the subresultants chain step by step.
114  */
115  // MAIN: start main loop containing different computation strategies
116  while (true) {
117  CARL_LOG_TRACE("carl.core.resultant", "Looping...");
118  CARL_LOG_TRACE("carl.core.resultant", "p = " << p);
119  CARL_LOG_TRACE("carl.core.resultant", "q = " << q);
120  if (carl::is_zero(q)) return subresultants;
121  uint pDeg = p.degree();
122  uint qDeg = q.degree();
123  subresultants.push_front(q);
124 
125  // Part 2
126  assert(pDeg >= qDeg);
127  uint delta = pDeg - qDeg;
128  CARL_LOG_TRACE("carl.core.resultant", "delta = " << delta);
129 
130  /** Case distinction on delta: either we choose b as next subresultant or we could reduce b (delta > 1)
131  * and add the reduced version c as next subresultant. The reduction is done by division, which
132  * depends on the internal variable order of GiNaC and might fail although for some order it would succeed.
133  * In this case, we just do not reduce b. (A relaxed reduction could also be applied.)
134  *
135  * After the if-else block, bDeg is the degree of the front-most element of subresultants, be it c or b.
136  */
137  UnivariatePolynomial<Coeff> c(variable);
138  if (delta > 1) {
139  // compute c
140  // Notation hints: Compared to [Duc98], here S_{d-1} is b and S_d is a, and S_e is c.
141  switch (strategy) {
143  CARL_LOG_TRACE("carl.core.resultant", "Part 2: Generic strategy");
144  UnivariatePolynomial<Coeff> reductionCoeff = carl::pow(q.lcoeff(), delta - 1) * q;
145  Coeff dividant = carl::pow(subresLcoeff, delta - 1);
146  bool res = carl::try_divide(reductionCoeff, dividant, c);
147  if (res) {
148  subresultants.push_front(c);
149  assert(!carl::is_zero(c));
150  qDeg = c.degree();
151  } else {
152  c = q;
153  }
154  break;
155  }
158  CARL_LOG_TRACE("carl.core.resultant", "Part 2: Ducos/Lazard strategy");
159  // "dichotomous Lazard": efficient exponentiation
160  uint deltaReduced = delta - 1;
161  CARL_LOG_TRACE("carl.core.resultant", "deltaReduced = " << deltaReduced);
162  // should be true by the loop condition
163  assert(deltaReduced > 0);
164 
165  Coeff lcoeffQ = q.lcoeff();
166  UnivariatePolynomial<Coeff> reductionCoeff(variable, lcoeffQ);
167 
168  CARL_LOG_TRACE("carl.core.resultant", "lcoeffQ = " << lcoeffQ);
169  CARL_LOG_TRACE("carl.core.resultant", "reductionCoeff = " << reductionCoeff);
170 
171  uint exponent = highestPower(deltaReduced);
172  deltaReduced -= exponent;
173  CARL_LOG_TRACE("carl.core.resultant", "exponent = " << exponent);
174  CARL_LOG_TRACE("carl.core.resultant", "deltaReduced = " << deltaReduced);
175 
176  while (exponent != 1) {
177  exponent /= 2;
178  CARL_LOG_TRACE("carl.core.resultant", "exponent = " << exponent);
179  bool res = carl::try_divide(reductionCoeff * reductionCoeff, subresLcoeff, reductionCoeff);
180  if (res && deltaReduced >= exponent) {
181  carl::try_divide(reductionCoeff * lcoeffQ, subresLcoeff, reductionCoeff);
182  deltaReduced -= exponent;
183  }
184  }
185  CARL_LOG_TRACE("carl.core.resultant", "reductionCoeff = " << reductionCoeff);
186  reductionCoeff *= q;
187  CARL_LOG_TRACE("carl.core.resultant", "reductionCoeff = " << reductionCoeff);
188  bool res = carl::try_divide(reductionCoeff, subresLcoeff, c);
189  if (res) {
190  subresultants.push_front(c);
191  assert(!carl::is_zero(c));
192  qDeg = c.degree();
193  CARL_LOG_TRACE("carl.core.resultant", "qDeg = " << qDeg);
194  } else {
195  c = q;
196  }
197  CARL_LOG_TRACE("carl.core.resultant", "c = " << c);
198  break;
199  }
200  }
201  } else {
202  c = q;
203  }
204  if (qDeg == 0) return subresultants;
205 
206  CARL_LOG_TRACE("carl.core.resultant", "Mid");
207  //CARL_LOG_TRACE("carl.core.resultant", "p = " << p);
208  //CARL_LOG_TRACE("carl.core.resultant", "q = " << q);
209 
210  // Part 3
211  switch (strategy) {
212  // Compared to [Duc98], here S_{d-1} is b and S_d is a, S_e is c, and s_d is subresLcoeff.
215  CARL_LOG_TRACE("carl.core.resultant", "Part 3: Generic/Lazard strategy");
216  if (carl::is_zero(p)) return subresultants;
217 
218  /* If b was constant, the degree properties for subresultants are still met, enforcing us to disregard whether
219  * the above division was successful (in this case, reducedNewB remains unchanged).
220  * If it was successful, the resulting term is safely added to the list, yielding an optimized resultant.
221  */
222  UnivariatePolynomial<Coeff> reducedNewB = pseudo_remainder(p, -q);
223  bool r = carl::try_divide(reducedNewB, carl::pow(subresLcoeff, delta) * p.lcoeff(), q);
224  assert(r);
225  break;
226  }
228  CARL_LOG_TRACE("carl.core.resultant", "Part 3: Ducos strategy");
229  // Ducos' optimization
230  Coeff lcoeffQ = q.lcoeff();
231  Coeff lcoeffC = c.lcoeff();
232  std::vector<Coeff> h(pDeg);
233 
234  for (uint d = 0; d < qDeg; d++) {
235  h[d] = lcoeffC * carl::pow(Coeff(variable), d);
236  }
237  if (pDeg != qDeg) { // => aDeg > bDeg
238  h[qDeg] = Coeff(lcoeffC * carl::pow(Coeff(variable), qDeg) - c); // H_e
239  }
240  for (uint d = qDeg + 1; d < pDeg; d++) {
241  Coeff t = h[d - 1] * variable;
242  UnivariatePolynomial<Coeff> reducedNewB = carl::to_univariate_polynomial(t, variable).coefficients()[qDeg] * q;
243  bool res = carl::try_divide(reducedNewB, lcoeffQ, reducedNewB);
244  assert(res || is_constant(reducedNewB));
245  h[d] = Coeff(t - reducedNewB);
246  }
247 
248  UnivariatePolynomial<Coeff> sum(p.main_var(), h.front() * p.coefficients()[0]);
249  for (uint d = 1; d < pDeg; d++) {
250  sum += h[d] * p.coefficients()[d];
251  }
252  UnivariatePolynomial<Coeff> normalizedSum(p.main_var());
253  bool res = carl::try_divide(sum, p.lcoeff(), normalizedSum);
254  assert(res || is_constant(sum));
255 
256  UnivariatePolynomial<Coeff> t(variable, {0, h.back()});
257  UnivariatePolynomial<Coeff> reducedNewB = ((t + normalizedSum) * lcoeffQ - carl::to_univariate_polynomial(t.coefficients()[qDeg], variable));
258  carl::try_divide(reducedNewB, p.lcoeff(), reducedNewB);
259  if (delta % 2 == 0) {
260  q = -reducedNewB;
261  } else {
262  q = reducedNewB;
263  }
264  break;
265  }
266  }
267  p = c;
268  subresLcoeff = p.lcoeff();
269  }
270 }
271 
272 template<typename Coeff>
273 std::vector<UnivariatePolynomial<Coeff>> principalSubresultantsCoefficients(
277  // Attention: Mathematica / Wolframalpha has one entry less (the last one) which is identical to p!
278  std::list<UnivariatePolynomial<Coeff>> subres = subresultants(p, q, strategy);
279  CARL_LOG_DEBUG("carl.upoly", "PSC of " << p << " and " << q << " on " << p.main_var() << ": " << subres);
280  std::vector<UnivariatePolynomial<Coeff>> subresCoeffs;
281  for (const auto& s : subres) {
282  assert(!carl::is_zero(s));
283  subresCoeffs.emplace_back(s.main_var(), s.lcoeff());
284  }
285  return subresCoeffs;
286 }
287 
288 template<typename Coeff>
293  assert(p.main_var() == q.main_var());
295 
297 
298  CARL_LOG_TRACE("carl.core.resultant", "resultant(" << p << ", " << q << ") = " << res);
299  if (is_constant(res)) {
300  return res;
301  } else {
303  }
304 }
305 
306 template<typename Coeff>
311  if (res.is_number()) return res;
312  uint d = p.degree();
313  Coeff sign = ((d * (d - 1) / 2) % 2 == 0) ? Coeff(1) : Coeff(-1);
314  Coeff redCoeff = sign * p.lcoeff();
315  bool result = carl::try_divide(res, redCoeff, res);
316  assert(result);
317  CARL_LOG_TRACE("carl.core.discriminant", "discriminant(" << p << ") = " << res);
318  return res;
319 }
320 
321 namespace resultant_debug {
322 /**
323  * A reimplementation of the resultant algorithm from z3.
324  * Used for a comparative analysis of our own algorithm.
325  */
326 template<typename Coeff>
329  const UnivariatePolynomial<Coeff>& q) {
330  //std::cout << "resultant(" << p << ", " << q << ", " << q.main_var() << ")" << std::endl;
331  if (carl::is_zero(p) || carl::is_zero(q)) {
332  //std::cout << "Zero" << std::endl;
334  }
335 
336  if (is_constant(p)) {
337  //std::cout << "A is const" << std::endl;
338  if (is_constant(q)) {
340  } else {
341  return carl::pow(p, q.degree());
342  }
343  }
344  if (is_constant(q)) {
345  //std::cout << "B is const" << std::endl;
346  return carl::pow(q, q.degree());
347  }
348 
351 
352  //std::cout << "Content" << std::endl;
353  Coeff cA = content(nA);
354  Coeff cB = content(nB);
355  Coeff A(primitive_part(nA));
356  Coeff B(primitive_part(nB));
357  //std::cout << "Done" << std::endl;
358  cA = carl::pow(cA, p.degree());
359  cB = carl::pow(cB, q.degree());
360  Coeff t = cA * cB;
361 
362  //std::cout << "Pre" << std::endl;
363  int s = 1;
364  std::size_t degA = A.degree(q.main_var());
365  std::size_t degB = B.degree(q.main_var());
366  if (degA < degB) {
367  std::swap(A, B);
368  if (degA % 2 == 1 && degB % 2 == 1) s = -1;
369  }
370 
371  Coeff R;
372  Coeff g(1);
373  Coeff h(1);
374  Coeff new_h;
375  bool div_res = false;
376 
377  while (true) {
378  //std::cout << "Loop " << A << ", " << B << std::endl;
379  //std::cout << "A = " << A << ", B = " << B << std::endl;
380  degA = A.degree(q.main_var());
381  degB = B.degree(q.main_var());
382  //std::cout << "Degrees: " << degA << " / " << degB << std::endl;
383  assert(degA >= degB);
384  std::size_t delta = degA - degB;
385  //std::cout << "1: delta = " << delta << std::endl;
386  if (degA % 2 == 1 && degB % 2 == 1) s = -s;
387  R = carl::pseudo_remainder(A, B, q.main_var());
388  A = B;
389  //std::cout << "R = " << R << std::endl;
390  //std::cout << "g = " << g << std::endl;
391  div_res = carl::try_divide(R, g, B);
392  assert(div_res);
393  for (std::size_t i = 0; i < delta; i++) {
394  //std::cout << "i = " << i << std::endl;
395  div_res = carl::try_divide(B, h, B);
396  assert(div_res);
397  }
398  g = A.lcoeff(q.main_var());
399  //std::cout << "2: delta = " << delta << std::endl;
400  //std::cout << "g = " << g << std::endl;
401  new_h = carl::pow(g, delta);
402  //std::cout << "Pow done" << delta << std::endl;
403  if (delta > 1) {
404  for (std::size_t i = 0; i < delta - 1; i++) {
405  div_res = carl::try_divide(new_h, h, new_h);
406  assert(div_res);
407  }
408  }
409  h = new_h;
410  if (B.degree(q.main_var()) == 0) {
411  std::size_t degA = A.degree(q.main_var());
412  new_h = B.lcoeff(q.main_var());
413  new_h = carl::pow(new_h, degA);
414  if (degA > 1) {
415  for (std::size_t i = 0; i < degA - 1; i++) {
416  div_res = carl::try_divide(new_h, h, new_h);
417  assert(div_res);
418  }
419  }
420  h = new_h;
421  if (s < 0) return UnivariatePolynomial<Coeff>(q.main_var(), -t * h);
422  return UnivariatePolynomial<Coeff>(q.main_var(), t * h);
423  }
424  }
425 }
426 
427 /**
428  * Eliminates the leading factor of p with q.
429  */
430 template<typename Coeff>
433  const UnivariatePolynomial<Coeff>& q) {
434  //std::cout << "eliminate " << p << " with " << q << std::endl;
435  assert(p.main_var() == q.main_var());
436  assert(p.degree() >= q.degree());
437  std::size_t degdiff = p.degree() - q.degree();
438  if (degdiff == 0)
439  return p * q.lcoeff() - q * p.lcoeff();
440  else
441  return p * q.lcoeff() - q * p.lcoeff() * UnivariatePolynomial<Coeff>(p.main_var(), Coeff(1), degdiff);
442 }
443 
444 /**
445  * An implementation of the naive resultant algorithm based on the silvester matrix.
446  */
447 template<typename Coeff>
450  const UnivariatePolynomial<Coeff>& q) {
451  if (carl::is_zero(p) || carl::is_zero(q)) {
453  }
454  if (is_constant(p)) {
455  if (is_constant(q)) {
457  } else {
458  return carl::pow(p, q.degree());
459  }
460  }
461  if (is_constant(q)) {
462  return carl::pow(q, p.degree());
463  }
464  if (p == q) return UnivariatePolynomial<Coeff>(p.main_var());
465 
468  if (f.degree() > g.degree()) std::swap(f, g);
469 
470  // Three stages:
471  // 1. Eliminate leading coefficients of all g-rows with f at once
472  // -> Until last g-row can be eliminated with last f-row
473  // 2. Eliminate leading coefficients of g-rows with f while still possible
474  // -> Until no g-row can be eliminated with last f-row.
475  // Now, there is a deg(f)-square-matrix at the lower right.
476  // 3. Eliminate the square matrix at the lower right.
477 
478  // Sylvester Matrix of f and g:
479  // f2 f1 f0
480  // f2 f1 f0
481  // f2 f1 f0
482  // g3 g2 g1 g0
483  // g3 g2 g1 g0
484  //
485  // First we eliminate g3 with f, resulting in:
486  // f2 f1 f0
487  // f2 f1 f0
488  // f2 f1 f0
489  // g2' g1' g0
490  // g2' g1' g0
491  //
492  // Now we eliminate g2', result looks like this:
493  // f2 f1 f0
494  // f2 f1 f0
495  // f2 f1 f0
496  // g1* g0*
497  // g1* g0*
498  //
499  // And finally, we eliminate g3' from the first g-row:
500  // f2 f1 f0
501  // f2 f1 f0
502  // f2 f1 f0
503  // g0' t
504  // g1* g0*
505  //
506  // Now, the first degree(f) columns are diagonal.
507  //std::cout << "f = " << f << std::endl;
508  //std::cout << "g = " << g << std::endl;
509  UnivariatePolynomial<Coeff> gRest = g;
510  // Do the elimination that works the same for all g-rows
511  for (std::size_t i = 0; i < g.degree() - f.degree() + 1; i++) {
512  //std::cout << gRest << " % " << f << std::endl;
513  gRest = eliminate(gRest, f);
514  //std::cout << "-> " << gRest << std::endl;
515  }
516  // Store result of first eliminations in matrix.
517  //PolyMatrix<Coeff> matrix(f.degree() + g.degree(), f.main_var());
518  for (std::size_t i = 0; i < g.degree(); i++) {
519  // Store f-rows
520  //matrix.set(i, g.degree()-i-1, f);
521  }
522  // Finish eliminations of g-rows.
523  std::vector<UnivariatePolynomial<Coeff>> m;
524  m.resize(f.degree(), UnivariatePolynomial<Coeff>(f.main_var()));
525  //matrix.set(g.degree() + f.degree()-1, 0, gRest);
526  m[f.degree() - 1] = gRest;
527  for (std::size_t i = 1; i < f.degree(); i++) {
528  gRest = eliminate(gRest * g.main_var(), f);
529  //matrix.set(g.degree() + f.degree()-1-i, 0, gRest);
530  m[f.degree() - 1 - i] = gRest;
531  }
532  //std::cout << m << std::endl;
533  for (std::size_t i = 0; i < m.size() - 1; i++) {
534  for (std::size_t j = i + 1; j < m.size(); j++) {
535  m[j] = eliminate(m[j], m[i]);
536  }
537  }
538  //std::cout << m << std::endl;
539 
540  Coeff determinant = f.lcoeff(); //.pow(f.degree());
541  //std::cout << "det = " << determinant << std::endl;
542  for (std::size_t i = 0; i < m.size(); i++) {
543  //std::cout << " *= " << m[i].coefficients()[m.size()-1-i] << std::endl;
544  if (m[i].degree() >= m.size() - 1 - i) {
545  determinant *= m[i].coefficients()[m.size() - 1 - i];
546  } else {
547  determinant = Coeff(0);
548  }
549  }
550  //determinant = m.back().tcoeff();
551  determinant = determinant.coprime_coefficients();
552  //std::cout << "det = " << determinant << std::endl;
553 
554  return UnivariatePolynomial<Coeff>(f.main_var(), determinant);
555 }
556 } // namespace resultant_debug
557 
558 } // namespace carl
Implements utility functions concerning the (total) degree of monomials, terms and polynomials.
#define CARL_LOG_TRACE(channel, msg)
Definition: carl-logging.h:44
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
carl is the main namespace for the library.
Coeff content(const UnivariatePolynomial< Coeff > &p)
The content of a polynomial is the gcd of the coefficients of the normal part of a polynomial.
Definition: Content.h:22
UnivariatePolynomial< C > to_univariate_polynomial(const MultivariatePolynomial< C, O, P > &p)
Convert a univariate polynomial that is currently (mis)represented by a 'MultivariatePolynomial' into...
const T & derivative(const T &t, Variable, std::size_t n=1)
Computes the n'th derivative of a number, which is either the number itself (for n = 0) or zero.
Definition: Derivative.h:23
bool try_divide(const Term< Coeff > &t, const Coeff &c, Term< Coeff > &res)
Definition: Division.h:28
std::uint64_t uint
Definition: numbers.h:16
std::vector< UnivariatePolynomial< Coeff > > principalSubresultantsCoefficients(const UnivariatePolynomial< Coeff > &, const UnivariatePolynomial< Coeff > &, SubresultantStrategy=SubresultantStrategy::Default)
Definition: Resultant.h:273
void swap(Variable &lhs, Variable &rhs)
Definition: Variables.h:202
bool is_constant(const ContextPolynomial< Coeff, Ordering, Policies > &p)
auto discriminant(const ContextPolynomial< Coeff, Ordering, Policies > &p)
Definition: Functions.h:17
SubresultantStrategy
Definition: Resultant.h:16
std::list< UnivariatePolynomial< Coeff > > subresultants(const UnivariatePolynomial< Coeff > &, const UnivariatePolynomial< Coeff > &, SubresultantStrategy=SubresultantStrategy::Default)
Implements a subresultants algorithm with optimizations described in .
Definition: Resultant.h:48
std::size_t exponent
Type of an exponent.
Definition: Monomial.h:29
Number highestPower(const Number &n)
Returns the highest power of two below n.
Definition: operations.h:192
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
typename UnderlyingNumberType< P >::type Coeff
UnivariatePolynomial< Coeff > primitive_part(const UnivariatePolynomial< Coeff > &p)
The primitive part of p is the normal part of p divided by the content of p.
Definition: PrimitivePart.h:19
UnivariatePolynomial< Coeff > pseudo_remainder(const UnivariatePolynomial< Coeff > &dividend, const UnivariatePolynomial< Coeff > &divisor)
Calculates the pseudo-remainder.
Definition: Remainder.h:105
auto resultant(const ContextPolynomial< Coeff, Ordering, Policies > &p, const ContextPolynomial< Coeff, Ordering, Policies > &q)
Definition: Functions.h:22
Interval< Number > pow(const Interval< Number > &i, Integer exp)
Definition: Power.h:11
UnivariatePolynomial< Coeff > resultant_z3(const UnivariatePolynomial< Coeff > &p, const UnivariatePolynomial< Coeff > &q)
A reimplementation of the resultant algorithm from z3.
Definition: Resultant.h:327
UnivariatePolynomial< Coeff > eliminate(const UnivariatePolynomial< Coeff > &p, const UnivariatePolynomial< Coeff > &q)
Eliminates the leading factor of p with q.
Definition: Resultant.h:431
UnivariatePolynomial< Coeff > resultant_det(const UnivariatePolynomial< Coeff > &p, const UnivariatePolynomial< Coeff > &q)
An implementation of the naive resultant algorithm based on the silvester matrix.
Definition: Resultant.h:448
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
This class represents a univariate polynomial with coefficients of an arbitrary type.
bool is_number() const
Checks whether the polynomial is only a number.
const std::vector< Coefficient > & coefficients() const &
Retrieves the coefficients defining this polynomial.
Variable main_var() const
Retrieves the main variable of this polynomial.
const Coefficient & lcoeff() const
Returns the leading coefficient.
uint degree() const
Get the maximal exponent of the main variable.
UnivariatePolynomial normalized() const
The normal part of a polynomial is the polynomial divided by the unit part.