carl  24.04
Computer ARithmetic Library
UnivariatePolynomial.h
Go to the documentation of this file.
1 /**
2  * @file UnivariatePolynomial.h
3  * @ingroup unirp
4  * @author Sebastian Junges
5  */
6 
7 #pragma once
8 
11 #include <carl-common/util/hash.h>
12 #include <carl-arith/core/Sign.h>
14 
15 #include <functional>
16 #include <list>
17 #include <map>
18 #include <memory>
19 #include <vector>
20 
21 #include "../typetraits.h"
22 
23 namespace carl {
24 //
25 // Forward declarations
26 //
27 template<typename Coefficient> class UnivariatePolynomial;
28 
29 template<typename Coefficient> class IntRepRealAlgebraicNumber;
30 
31 template<typename Coefficient>
32 using UnivariatePolynomialPtr = std::shared_ptr<UnivariatePolynomial<Coefficient>>;
33 
34 template<typename Coefficient>
35 using FactorMap = std::map<UnivariatePolynomial<Coefficient>, uint>;
36 }
37 
38 #include "MultivariatePolynomial.h"
39 
40 
42 
43 namespace carl
44 {
45 
48 };
49 
50 /**
51  * This class represents a univariate polynomial with coefficients of an arbitrary type.
52  *
53  * A univariate polynomial is defined by a variable (the _main variable_) and the coefficients.
54  * The coefficients may be of any type. The intention is to use a numbers or polynomials as coefficients.
55  * If polynomials are used as coefficients, this can be seen as a multivariate polynomial with a distinguished main variable.
56  *
57  * Most methods are specifically adapted for polynomial coefficients, if necessary.
58  * @ingroup unirp
59  */
60 template<typename Coefficient>
62 {
63  /**
64  * Declare all instantiations of univariate polynomials as friends.
65  */
66  template<class T> friend class UnivariatePolynomial;
67 private:
68  /// The main variable.
70  /// The coefficients.
71  std::vector<Coefficient> mCoefficients;
72 
73 public:
74  /**
75  * The number type that is ultimately used for the coefficients.
76  */
78  /**
79  * The integral type that belongs to the number type.
80  */
82 
83  using CACHE = void;
84  using CoeffType = Coefficient;
87 
88  // Rule of five
89  /**
90  * Default constructor shall not exist. Use UnivariatePolynomial(Variable) instead.
91  */
93  /**
94  * Copy constructor.
95  */
97  /**
98  * Move constructor.
99  */
101  /**
102  * Copy assignment operator.
103  */
105  /**
106  * Move assignment operator.
107  */
109 
110  /**
111  * Construct a zero polynomial with the given main variable.
112  * @param mainVar New main variable.
113  */
114  explicit UnivariatePolynomial(Variable mainVar);
115  /**
116  * Construct \f$ coeff \cdot mainVar^{degree} \f$.
117  * @param mainVar New main variable.
118  * @param coeff Leading coefficient.
119  * @param degree Degree.
120  */
121  UnivariatePolynomial(Variable mainVar, const Coefficient& coeff, std::size_t degree = 0);
122 
123  /**
124  * Construct polynomial with the given coefficients.
125  * @param mainVar New main variable.
126  * @param coefficients List of coefficients.
127  */
128  UnivariatePolynomial(Variable mainVar, std::initializer_list<Coefficient> coefficients);
129 
130  /**
131  * Construct polynomial with the given coefficients from the underlying number type of the coefficient type.
132  * @param mainVar New main variable.
133  * @param coefficients List of coefficients.
134  */
135  template<typename C = Coefficient, DisableIf<std::is_same<C, typename UnderlyingNumberType<C>::type>> = dummy>
136  UnivariatePolynomial(Variable mainVar, std::initializer_list<typename UnderlyingNumberType<C>::type> coefficients);
137 
138  /**
139  * Construct polynomial with the given coefficients.
140  * @param mainVar New main variable.
141  * @param coefficients Vector of coefficients.
142  */
143  UnivariatePolynomial(Variable mainVar, const std::vector<Coefficient>& coefficients);
144  /**
145  * Construct polynomial with the given coefficients, moving the coefficients.
146  * @param mainVar New main variable.
147  * @param coefficients Vector of coefficients.
148  */
149  UnivariatePolynomial(Variable mainVar, std::vector<Coefficient>&& coefficients);
150  /**
151  * Construct polynomial with the given coefficients.
152  * @param mainVar New main variable.
153  * @param coefficients Assignment of degree to coefficients.
154  */
155  UnivariatePolynomial(Variable mainVar, const std::map<uint, Coefficient>& coefficients);
156 
157  /**
158  * Destructor.
159  */
161 
162  /**
163  * Checks if the polynomial is equal to zero.
164  * @return If polynomial is zero.
165  */
166  [[deprecated("use carl::is_zero(p) instead.")]]
167  bool is_zero() const
168  {
169  return mCoefficients.size() == 0;
170  }
171 
172  /**
173  * Checks if the polynomial is equal to one.
174  * @return If polynomial is one.
175  */
176  [[deprecated("use carl::is_one(p) instead.")]]
177  bool is_one() const
178  {
179  return mCoefficients.size() == 1 && mCoefficients.back() == Coefficient(1);
180  }
181 
182  /**
183  * Creates a polynomial of value one with the same main variable.
184  * @return One.
185  */
188  if (mCoefficients.empty()) {
189  return UnivariatePolynomial(mMainVar, Coefficient(1));
190  } else {
191  return UnivariatePolynomial(mMainVar, Coefficient(1, lcoeff().gf()));
192  }
193  } else {
194  return UnivariatePolynomial(mMainVar, Coefficient(1));
195  }
196  }
197 
198  /**
199  * Returns the leading coefficient.
200  * Asserts, that the polynomial is not empty.
201  * @return The leading coefficient.
202  */
203  const Coefficient& lcoeff() const
204  {
205  assert(mCoefficients.size() > 0);
206  return mCoefficients.back();
207  }
208  /**
209  * Returns the trailing coefficient.
210  * Asserts, that the polynomial is not empty.
211  * @return The trailing coefficient.
212  */
213  const Coefficient& tcoeff() const {
214  assert(mCoefficients.size() > 0);
215  return mCoefficients.front();
216  }
217 
218  /**
219  * Checks whether the polynomial is constant with respect to the main variable.
220  * @return If polynomial is constant.
221  */
222  [[deprecated("use carl::is_constant(p) instead.")]]
223  bool is_constant() const
224  {
225  assert(is_consistent());
226  return mCoefficients.size() <= 1;
227  }
228 
230  {
231  assert(is_consistent());
232  return mCoefficients.size() <= 2;
233  }
234 
235  /**
236  * Checks whether the polynomial is only a number.
237  * @return If polynomial is a number.
238  */
239  bool is_number() const
240  {
242  return mCoefficients.size() <= 1;
243  } else {
244  if (mCoefficients.empty()) return true;
245  return (mCoefficients.size() <= 1) && lcoeff().is_number();
246  }
247  }
248 
249  /**
250  * Returns the constant part of this polynomial.
251  * @return Constant part.
252  */
254  {
255  if (mCoefficients.empty()) return NumberType(0);
257  return tcoeff();
258  } else {
259  return tcoeff().constant_part();
260  }
261  }
262 
263  /**
264  * Checks if the polynomial is univariate, that means if only one variable occurs.
265  * @return true.
266  */
267  bool is_univariate() const {
269  return true;
270  } else {
271  for (const auto& c: coefficients()) {
272  if (!c.is_number()) return false;
273  }
274  return true;
275  }
276  }
277 
278  /**
279  * Get the maximal exponent of the main variable.
280  * As the degree of the zero polynomial is \f$-\infty\f$, we assert that this polynomial is not zero. This must be checked by the caller before calling this method.
281  * @see @cite GCL92, page 38
282  * @return Degree.
283  */
284  uint degree() const {
285  assert(!mCoefficients.empty());
286  return uint(mCoefficients.size()-1);
287  }
288 
289  /**
290  * Returns the total degree of the polynomial, that is the maximum degree of any monomial.
291  * As the degree of the zero polynomial is \f$-\infty\f$, we assert that this polynomial is not zero. This must be checked by the caller before calling this method.
292  * @see @cite GCL92, page 38
293  * @return Total degree.
294  */
295  [[deprecated("use carl::total_degree(p) instead.")]]
296  uint total_degree() const {
298  return degree();
299  } else {
300  if (is_zero()) return 0;
301  uint max = 0;
302  for (std::size_t deg = 0; deg < mCoefficients.size(); deg++) {
303  if (!mCoefficients[deg].is_zero()) {
304  uint tdeg = deg + mCoefficients[deg].total_degree();
305  if (tdeg > max) max = tdeg;
306  }
307  }
308  return max;
309  }
310  }
311 
312  /**
313  * Removes the leading term from the polynomial.
314  */
315  void truncate() {
316  assert(!mCoefficients.empty());
317  this->mCoefficients.resize(this->mCoefficients.size()-1);
318  this->strip_leading_zeroes();
319  }
320 
321  /**
322  * Retrieves the coefficients defining this polynomial.
323  * @return Coefficients.
324  */
325  const std::vector<Coefficient>& coefficients() const & {
326  return mCoefficients;
327  }
328  /// Returns the coefficients as non-const reference.
329  std::vector<Coefficient>& coefficients() & {
330  return mCoefficients;
331  }
332  /// Returns the coefficients as rvalue. The polynomial may be in an undefined state afterwards!
333  std::vector<Coefficient>&& coefficients() && {
334  return std::move(mCoefficients);
335  }
336 
337  /**
338  * Retrieves the main variable of this polynomial.
339  * @return Main variable.
340  */
341  Variable main_var() const {
342  return mMainVar;
343  }
344 
345  /**
346  * Checks if the given variable occurs in the polynomial.
347  * @param v Variable.
348  * @return If v occurs in the polynomial.
349  */
350  bool has(Variable v) const {
351  if (v == main_var()) return true;
353  for (const auto& c: mCoefficients) {
354  if (c.has(v)) return true;
355  }
356  }
357  return false;
358  }
359 
360  /**
361  * Calculates a factor that would make the coefficients of this polynomial coprime integers.
362  *
363  * We consider a set of integers coprime, if they share no common factor.
364  * Technically, the coprime factor is \f$ lcm(N) / gcd(D) \f$ where `N` is the set of the numerators and `D` is the set of the denominators of all coefficients.
365  * @return Coprime factor of this polynomial.
366  */
367  template<typename C = Coefficient, EnableIf<is_subset_of_rationals_type<C>> = dummy>
368  Coefficient coprime_factor() const;
369  template<typename C = Coefficient, DisableIf<is_subset_of_rationals_type<C>> = dummy>
371 
372  /**
373  * Constructs a new polynomial that is scaled such that the coefficients are coprime.
374  * It is calculated by multiplying it with the coprime factor.
375  * By definition, this results in a polynomial with integral coefficients.
376  * @return This polynomial multiplied with the coprime factor.
377  */
378  template<typename C = Coefficient, EnableIf<is_subset_of_rationals_type<C>> = dummy>
380 
381  template<typename C = Coefficient, DisableIf<is_subset_of_rationals_type<C>> = dummy>
383 
384 
385  template<typename C = Coefficient, EnableIf<is_subset_of_rationals_type<C>> = dummy>
387 
388  template<typename C = Coefficient, DisableIf<is_subset_of_rationals_type<C>> = dummy>
390 
391  /**
392  * Checks whether the polynomial is unit normal.
393  * A polynomial is unit normal, if the leading coefficient is unit normal, that is if it is either one or minus one.
394  * @see @cite GCL92, page 39
395  * @return If polynomial is normal.
396  */
397  bool is_normal() const;
398  /**
399  * The normal part of a polynomial is the polynomial divided by the unit part.
400  * @see @cite GCL92, page 42.
401  * @return This polynomial divided by the unit part.
402  */
404 
405  /**
406  * The unit part of a polynomial over a field is its leading coefficient for nonzero polynomials,
407  * and one for zero polynomials.
408  * The unit part of a polynomial over a ring is the sign of the polynomial for nonzero polynomials,
409  * and one for zero polynomials.
410  * @see @cite GCL92, page 42.
411  * @return The unit part of the polynomial.
412  */
413  Coefficient unit_part() const;
414 
415  /**
416  * Constructs a new polynomial `q` such that \f$ q(x) = p(-x) \f$ where `p` is this polynomial.
417  * @return New polynomial with negated variable.
418  */
421  for (std::size_t deg = 0; deg < res.coefficients().size(); deg++) {
422  if (deg % 2 == 1) res.mCoefficients[deg] = -res.mCoefficients[deg];
423  }
424  return res;
425  }
426 
427  /**
428  * Reverse coefficients safely.
429  */
432  std::reverse(res.mCoefficients.begin(), res.mCoefficients.end());
433  while(carl::is_zero(*std::prev(res.mCoefficients.end())) && std::prev(res.mCoefficients.end()) != res.mCoefficients.begin()) {
434  res.mCoefficients.erase(std::prev(res.mCoefficients.end()));
435  }
436  assert(res.is_consistent());
437  return res;
438  }
439 
440  /**
441  * Checks if this polynomial is divisible by the given divisor, that is if the remainder is zero.
442  * @param divisor Polynomial.
443  * @return If divisor divides this polynomial.
444  */
445  bool divides(const UnivariatePolynomial& divisor) const;
446 
447  /**
448  * Replaces every coefficient `c` by `c mod modulus`.
449  * @param modulus Modulus.
450  * @return This.
451  */
452  UnivariatePolynomial& mod(const Coefficient& modulus);
453  /**
454  * Constructs a new polynomial where every coefficient `c` is replaced by `c mod modulus`.
455  * @param modulus Modulus.
456  * @return New polynomial.
457  */
458  UnivariatePolynomial mod(const Coefficient& modulus) const;
459 
460  /**
461  * Returns this polynomial to the given power.
462  * @param exp Exponent.
463  * @return This to the power of exp.
464  */
465  [[deprecated("Use carl::pow() instead.")]]
466  UnivariatePolynomial pow(std::size_t exp) const;
467 
468  [[deprecated("Use carl::evaluate() instead.")]]
469  Coefficient evaluate(const Coefficient& value) const;
470 
471  /**
472  * Calculates the sign of the polynomial at some point.
473  * @param value Point to evaluate.
474  * @return Sign at value.
475  */
476  [[deprecated("Use carl::sgn(carl::evaluate()) instead.")]]
477  carl::Sign sgn(const Coefficient& value) const {
478  return carl::sgn(this->evaluate(value));
479  }
480 
481  template<typename SubstitutionType, typename C = Coefficient, EnableIf<is_instantiation_of<MultivariatePolynomial, C>> = dummy>
482  UnivariatePolynomial<Coefficient> evaluateCoefficient(const std::map<Variable, SubstitutionType>&) const
483  {
485  }
486  template<typename SubstitutionType, typename C = Coefficient, DisableIf<is_instantiation_of<MultivariatePolynomial, C>> = dummy>
487  UnivariatePolynomial<Coefficient> evaluateCoefficient(const std::map<Variable, SubstitutionType>&) const
488  {
489  // TODO check behaviour here.
490  return *this;
491  }
492 
493  template<typename T = Coefficient, EnableIf<has_normalize<T>> = dummy>
495  {
496  static_assert(std::is_same<T,Coefficient>::value, "No template parameters should be given");
497  for(Coefficient& c : mCoefficients)
498  {
499  c.normalize();
500  }
501  return *this;
502  }
503  template<typename T = Coefficient, DisableIf<has_normalize<T>> = dummy>
505  {
506  static_assert(std::is_same<T,Coefficient>::value, "No template parameters should be given");
507  CARL_LOG_WARN("carl.core", "normalize not possible");
508  return *this;
509  }
510  /**
511  * Works only from rationals, if the numbers are already integers.
512  * @return
513  */
514  template<typename C=Coefficient, EnableIf<is_instantiation_of<GFNumber, C>> = dummy>
516  template<typename C=Coefficient, DisableIf<is_instantiation_of<GFNumber, C>> = dummy>
518 
520 
521  /**
522  * Asserts that is_univariate() is true.
523  */
524  template<typename C=Coefficient, DisableIf<is_number_type<C>> = dummy>
526 
527  template<typename NewCoeff>
529  template<typename NewCoeff>
530  UnivariatePolynomial<NewCoeff> convert(const std::function<NewCoeff(const Coefficient&)>& f) const;
531 
532  /**
533  * Returns the numeric content part of the i'th coefficient.
534  *
535  * If the coefficients are numbers, this is simply the i'th coefficient.
536  * If the coefficients are polynomials, this is the numeric content part of the i'th coefficient.
537  * @param i number of the coefficient
538  * @return numeric content part of i'th coefficient.
539  */
540  NumberType numeric_content(std::size_t i) const
541  {
543  return this->mCoefficients[i];
544  } else {
545  return this->mCoefficients[i].numeric_content();
546  }
547  }
548 
549  /**
550  * Returns the numeric unit part of the polynomial.
551  *
552  * If the coefficients are numbers, this is the sign of the leading coefficient.
553  * If the coefficients are polynomials, this is the unit part of the leading coefficient.s
554  * @return unit part of the polynomial.
555  */
557  {
559  return (this->lcoeff() >= Coefficient(0) ? NumberType(1) : NumberType(-1));
560  } else {
561  return this->lcoeff().numeric_unit();
562  }
563  }
564 
565  /**
566  * Obtains the numeric content part of this polynomial.
567  *
568  * The numeric content part of a polynomial is defined as the gcd() of the numeric content parts of all coefficients.
569  * This is only possible if the underlying number type is either integral or fractional.
570  *
571  * As for fractional numbers, we consider the following definition:
572  * gcd( a/b, c/d ) = gcd( a/b*l, c/d*l ) / l
573  * where l = lcm(b,d).
574  * @return numeric content part of the polynomial.
575  * @see UnivariatePolynomials::numeric_content(std::size_t)
576  */
577  template<typename N=NumberType, EnableIf<is_subset_of_rationals_type<N>> = dummy>
579 
580  /**
581  * Compute the main denominator of all numeric coefficients of this polynomial.
582  * This method only applies if the Coefficient type is a number.
583  * @return the main denominator of all coefficients of this polynomial.
584  */
585  template<typename C=Coefficient, EnableIf<is_number_type<C>> = dummy>
587  template<typename C=Coefficient, DisableIf<is_number_type<C>> = dummy>
589 
590  Coefficient synthetic_division(const Coefficient& zeroOfDivisor);
591 
592  /**
593  * Checks if zero is a real root of this polynomial.
594  * @return True if zero is a root.
595  */
596  bool zero_is_root() const {
597  assert(!mCoefficients.empty());
598  return carl::is_zero(mCoefficients[0]);
599  }
600 
601 public:
602  /// @name Equality comparison operators
603  /// @{
604  /**
605  * Checks if the two arguments are equal.
606  * @param lhs First argument.
607  * @param rhs Second argument.
608  * @return `lhs == rhs`
609  */
610  template<typename C>
611  friend bool operator==(const C& lhs, const UnivariatePolynomial<C>& rhs);
612  template<typename C>
613  friend bool operator==(const UnivariatePolynomial<C>& lhs, const C& rhs);
614  template<typename C>
615  friend bool operator==(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs);
616  template<typename C>
618  /// @}
619 
620  /// @name Inequality comparison operators
621  /// @{
622  /**
623  * Checks if the two arguments are not equal.
624  * @param lhs First argument.
625  * @param rhs Second argument.
626  * @return `lhs != rhs`
627  */
628  template<typename C>
629  friend bool operator!=(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs);
630  template<typename C>
632  /// @}
633 
635  template<typename C>
636  friend bool operator<(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs);
637 
639 
640  /// @name In-place addition operators
641  /// @{
642  /**
643  * Add something to this polynomial and return the changed polynomial.
644  * @param rhs Right hand side.
645  * @return Changed polynomial.
646  */
647  UnivariatePolynomial& operator+=(const Coefficient& rhs);
649  /// @}
650 
651  /// @name Addition operators
652  /// @{
653  /**
654  * Performs an addition involving a polynomial.
655  * @param lhs First argument.
656  * @param rhs Second argument.
657  * @return `lhs + rhs`
658  */
659  template<typename C>
661  template<typename C>
663  template<typename C>
665  /// @}
666 
667  /// @name In-place subtraction operators
668  /// @{
669  /**
670  * Subtract something from this polynomial and return the changed polynomial.
671  * @param rhs Right hand side.
672  * @return Changed polynomial.
673  */
674  UnivariatePolynomial& operator-=(const Coefficient& rhs);
676  /// @}
677 
678  /// @name Subtraction operators
679  /// @{
680  /**
681  * Performs a subtraction involving a polynomial.
682  * @param lhs First argument.
683  * @param rhs Second argument.
684  * @return `lhs - rhs`
685  */
686  template<typename C>
688  template<typename C>
690  template<typename C>
692  /// @}
693 
694  /// @name In-place multiplication operators
695  /// @{
696  /**
697  * Multiply this polynomial with something and return the changed polynomial.
698  * @param rhs Right hand side.
699  * @return Changed polynomial.
700  */
701  template<typename C=Coefficient, EnableIf<is_number_type<C>> = dummy>
703  template<typename C=Coefficient, DisableIf<is_number_type<C>> = dummy>
705  UnivariatePolynomial& operator*=(const Coefficient& rhs);
706  template<typename I = Coefficient, DisableIf<std::is_same<Coefficient, I>>...>
709  /// @}
710 
711  /// @name Multiplication operators
712  /// @{
713  /**
714  * Perform a multiplication involving a polynomial.
715  * @param lhs Left hand side.
716  * @param rhs Right hand side.
717  * @return `lhs * rhs`
718  */
719  template<typename C>
721  template<typename C>
723  template<typename C>
725  template<typename C>
727  template<typename C>
729  template<typename C>
731  template<typename C>
733  template<typename C, typename O, typename P>
735  template<typename C, typename O, typename P>
737  /// @}
738 
739  /// @name In-place division operators
740  /// @{
741  /**
742  * Divide this polynomial by something and return the changed polynomial.
743  * @param rhs Right hand side.
744  * @return Changed polynomial.
745  */
746  template<typename C = Coefficient, EnableIf<is_field_type<C>> = dummy>
747  UnivariatePolynomial& operator/=(const Coefficient& rhs);
748  template<typename C = Coefficient, DisableIf<is_field_type<C>> = dummy>
749  UnivariatePolynomial& operator/=(const Coefficient& rhs);
750  /// @}
751 
752  /// @name Division operators
753  /// @{
754  /**
755  * Perform a division involving a polynomial.
756  * @param lhs Left hand side.
757  * @param rhs Right hand side.
758  * @return `lhs / rhs`
759  */
760  template<typename C>
762  /// @}
763 
764  /**
765  * Streaming operator for univariate polynomials.
766  * @param os Output stream.
767  * @param rhs Polynomial.
768  * @return `os`
769  */
770  template <typename C>
771  friend std::ostream& operator<<(std::ostream& os, const UnivariatePolynomial<C>& rhs);
772 
773  /**
774  * Asserts that this polynomial over numeric coefficients complies with the requirements and assumptions for UnivariatePolynomial objects.
775  *
776  * <ul>
777  * <li>The leading term is not zero.</li>
778  * </ul>
779  */
780  template<typename C=Coefficient, EnableIf<is_number_type<C>> = dummy>
781  bool is_consistent() const;
782 
783  /**
784  * Asserts that this polynomial over polynomial coefficients complies with the requirements and assumptions for UnivariatePolynomial objects.
785  *
786  * <ul>
787  * <li>The leading term is not zero.</li>
788  * <li>The main variable does not occur in any coefficient.</li>
789  * </ul>
790  */
791  template<typename C=Coefficient, DisableIf<is_number_type<C>> = dummy>
792  bool is_consistent() const;
793 
795  {
796  while(mCoefficients.size() > 0 && carl::is_zero(lcoeff()))
797  {
798  mCoefficients.pop_back();
799  }
800  }
801 };
802 
803 /**
804  * Checks if the polynomial is equal to zero.
805  * @return If polynomial is zero.
806  */
807 template<typename Coefficient>
809  return p.coefficients().size() == 0;
810 }
811 
812 /**
813  * Checks if the polynomial is equal to one.
814  * @return If polynomial is one.
815  */
816 template<typename Coefficient>
818  return p.coefficients().size() == 1 && carl::is_one(p.coefficients().front());
819 }
820 
821 /// Add the variables of the given polynomial to the variables.
822 template<typename Coeff>
824  if (!is_constant(p)) vars.add(p.main_var());
825  if constexpr (!carl::is_number_type<Coeff>::value) {
826  for (const auto& c : p.coefficients()) {
827  variables(c, vars);
828  }
829  }
830 }
831 
832 template<typename T>
833 struct is_polynomial_type<carl::UnivariatePolynomial<T>>: std::true_type {};
834 /**
835  * States that UnderlyingNumberType of UnivariatePolynomial<T> is UnderlyingNumberType<C>::type.
836  * @ingroup typetraits_UnderlyingNumberType
837  */
838 template<typename C>
839 struct UnderlyingNumberType<UnivariatePolynomial<C>>: has_subtype<typename UnderlyingNumberType<C>::type> {};
840 
841 }
842 
843 namespace std {
844 /**
845  * Specialization of `std::hash` for univariate polynomials.
846  */
847 template<typename Coefficient>
848 struct hash<carl::UnivariatePolynomial<Coefficient>> {
849  /**
850  * Calculates the hash of univariate polynomial.
851  * @param p UnivariatePolynomial.
852  * @return Hash of p.
853  */
855  return carl::hash_all(p.main_var(), p.coefficients());
856  }
857 };
858 
859 /**
860  * Specialization of `std::less` for univariate polynomials.
861  */
862 template<typename Coefficient>
863 struct less<carl::UnivariatePolynomial<Coefficient>> {
866  /**
867  * Compares two univariate polynomials.
868  * @param lhs First polynomial.
869  * @param rhs Second polynomial
870  * @return `lhs < rhs`.
871  */
873  return lhs.less(rhs, order);
874  }
875  /**
876  * Compares two pointers to univariate polynomials.
877  * @param lhs First polynomial.
878  * @param rhs Second polynomial
879  * @return `lhs < rhs`.
880  */
882  if (lhs == nullptr) return rhs != nullptr;
883  if (rhs == nullptr) return true;
884  return lhs->less(*rhs, order);
885  }
886  /**
887  * Compares two shared pointers to univariate polynomials.
888  * @param lhs First polynomial.
889  * @param rhs Second polynomial
890  * @return `lhs < rhs`.
891  */
893  return (*this)(lhs.get(), rhs.get());
894  }
895 };
896 
897 }
898 
899 #include "UnivariatePolynomial.tpp"
A small wrapper that configures logging for carl.
#define CARL_LOG_WARN(channel, msg)
Definition: carl-logging.h:41
#define CARL_LOG_NOTIMPLEMENTED()
Definition: carl-logging.h:48
Gives the underlying number type of a complex object.
Definition: typetraits.h:336
carl is the main namespace for the library.
std::uint64_t uint
Definition: numbers.h:16
bool is_constant(const ContextPolynomial< Coeff, Ordering, Policies > &p)
Sign
This class represents the sign of a number .
Definition: Sign.h:20
Interval< Number > exp(const Interval< Number > &i)
Definition: Exponential.h:10
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
const dtl::enabled dummy
Definition: SFINAE.h:53
std::map< UnivariatePolynomial< Coefficient >, uint > FactorMap
typename std::enable_if<!std::is_same< C, typename IntegralType< C >::type >::value, typename IntegralType< C >::type >::type IntegralTypeIfDifferent
Definition: typetraits.h:321
Sign sgn(const Number &n)
Obtain the sign of the given number.
Definition: Sign.h:54
std::size_t hash_all(Args &&... args)
Hashes an arbitrary number of values.
Definition: hash.h:71
void variables(const BasicConstraint< Pol > &c, carlVariables &vars)
std::shared_ptr< UnivariatePolynomial< Coefficient > > UnivariatePolynomialPtr
bool is_one(const Interval< Number > &i)
Check if this interval is a point-interval containing 1.
Definition: Interval.h:1462
UnivariatePolynomial< Coefficient > reverse(UnivariatePolynomial< Coefficient > &&p)
Reverses the order of the coefficients of this polynomial.
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
void add(Variable v)
Definition: Variables.h:141
A finite field.
Definition: GaloisField.h:32
This template is designed to provide types that are related to other types.
Definition: typetraits.h:75
T type
A type associated with the type.
Definition: typetraits.h:77
This class represents a univariate polynomial with coefficients of an arbitrary type.
UnivariatePolynomial< NewCoeff > convert(const std::function< NewCoeff(const Coefficient &)> &f) const
UnivariatePolynomial & operator+=(const Coefficient &rhs)
Add something to this polynomial and return the changed polynomial.
UnivariatePolynomial(Variable mainVar, const std::map< uint, Coefficient > &coefficients)
Construct polynomial with the given coefficients.
UnivariatePolynomial(Variable mainVar, std::vector< Coefficient > &&coefficients)
Construct polynomial with the given coefficients, moving the coefficients.
UnivariatePolynomial< Coefficient > coprime_coefficients_sign_preserving() const
friend UnivariatePolynomial< C > operator*(const UnivariatePolynomial< C > &lhs, const IntegralTypeIfDifferent< C > &rhs)
Perform a multiplication involving a polynomial.
bool is_constant() const
Checks whether the polynomial is constant with respect to the main variable.
UnivariatePolynomial & mod(const Coefficient &modulus)
Replaces every coefficient c by c mod modulus.
bool is_number() const
Checks whether the polynomial is only a number.
friend UnivariatePolynomial< C > operator*(const IntegralTypeIfDifferent< C > &lhs, const UnivariatePolynomial< C > &rhs)
Perform a multiplication involving a polynomial.
UnivariatePolynomial(Variable mainVar, std::initializer_list< Coefficient > coefficients)
Construct polynomial with the given coefficients.
friend UnivariatePolynomial< C > operator-(const C &lhs, const UnivariatePolynomial< C > &rhs)
Performs a subtraction involving a polynomial.
bool less(const UnivariatePolynomial< Coefficient > &rhs, const PolynomialComparisonOrder &order=PolynomialComparisonOrder::Default) const
UnivariatePolynomial one() const
Creates a polynomial of value one with the same main variable.
UnivariatePolynomial< typename IntegralType< Coefficient >::type > coprime_coefficients() const
Constructs a new polynomial that is scaled such that the coefficients are coprime.
friend bool operator!=(const UnivariatePolynomial< C > &lhs, const UnivariatePolynomial< C > &rhs)
Checks if the two arguments are not equal.
bool is_normal() const
Checks whether the polynomial is unit normal.
UnivariatePolynomial & operator=(UnivariatePolynomial &&p) noexcept
Move assignment operator.
UnivariatePolynomial(Variable mainVar)
Construct a zero polynomial with the given main variable.
Coefficient coprime_factor() const
Calculates a factor that would make the coefficients of this polynomial coprime integers.
const std::vector< Coefficient > & coefficients() const &
Retrieves the coefficients defining this polynomial.
Variable mMainVar
The main variable.
Variable main_var() const
Retrieves the main variable of this polynomial.
friend bool operator!=(const UnivariatePolynomialPtr< C > &lhs, const UnivariatePolynomialPtr< C > &rhs)
Checks if the two arguments are not equal.
UnivariatePolynomial(Variable mainVar, const std::vector< Coefficient > &coefficients)
Construct polynomial with the given coefficients.
const Coefficient & lcoeff() const
Returns the leading coefficient.
~UnivariatePolynomial()=default
Destructor.
const Coefficient & tcoeff() const
Returns the trailing coefficient.
friend bool operator==(const UnivariatePolynomial< C > &lhs, const UnivariatePolynomial< C > &rhs)
Checks if the two arguments are equal.
friend UnivariatePolynomial< C > operator*(const UnivariatePolynomial< C > &lhs, Variable rhs)
Perform a multiplication involving a polynomial.
friend UnivariatePolynomial< C > operator*(Variable lhs, const UnivariatePolynomial< C > &rhs)
Perform a multiplication involving a polynomial.
UnivariatePolynomial(Variable mainVar, const Coefficient &coeff, std::size_t degree=0)
Construct .
friend UnivariatePolynomial< C > operator*(const UnivariatePolynomial< C > &lhs, const C &rhs)
Perform a multiplication involving a polynomial.
NumberType numeric_unit() const
Returns the numeric unit part of the polynomial.
friend UnivariatePolynomial< C > operator+(const C &lhs, const UnivariatePolynomial< C > &rhs)
Performs an addition involving a polynomial.
std::vector< Coefficient > && coefficients() &&
Returns the coefficients as rvalue. The polynomial may be in an undefined state afterwards!
Coefficient synthetic_division(const Coefficient &zeroOfDivisor)
bool is_consistent() const
Asserts that this polynomial over numeric coefficients complies with the requirements and assumptions...
bool has(Variable v) const
Checks if the given variable occurs in the polynomial.
UnivariatePolynomial & operator*=(const UnivariatePolynomial &rhs)
Multiply this polynomial with something and return the changed polynomial.
bool is_zero() const
Checks if the polynomial is equal to zero.
UnivariatePolynomial & operator*=(const Coefficient &rhs)
Multiply this polynomial with something and return the changed polynomial.
UnivariatePolynomial & operator-=(const UnivariatePolynomial &rhs)
Subtract something from this polynomial and return the changed polynomial.
friend UnivariatePolynomial< C > operator*(const C &lhs, const UnivariatePolynomial< C > &rhs)
Perform a multiplication involving a polynomial.
friend UnivariatePolynomial< C > operator-(const UnivariatePolynomial< C > &lhs, const C &rhs)
Performs a subtraction involving a polynomial.
UnivariatePolynomial & operator*=(const typename IntegralType< Coefficient >::type &rhs)
Multiply this polynomial with something and return the changed polynomial.
UnivariatePolynomial & operator-=(const Coefficient &rhs)
Subtract something from this polynomial and return the changed polynomial.
bool is_one() const
Checks if the polynomial is equal to one.
UnivariatePolynomial< NewCoeff > convert() const
UnivariatePolynomial & operator+=(const UnivariatePolynomial &rhs)
Add something to this polynomial and return the changed polynomial.
carl::Sign sgn(const Coefficient &value) const
Calculates the sign of the polynomial at some point.
bool divides(const UnivariatePolynomial &divisor) const
Checks if this polynomial is divisible by the given divisor, that is if the remainder is zero.
friend UnivariatePolynomial< C > operator*(const UnivariatePolynomial< C > &lhs, const UnivariatePolynomial< C > &rhs)
Perform a multiplication involving a polynomial.
friend class UnivariatePolynomial
Declare all instantiations of univariate polynomials as friends.
friend UnivariatePolynomial< C > operator+(const UnivariatePolynomial< C > &lhs, const C &rhs)
Performs an addition involving a polynomial.
UnivariatePolynomial()=delete
Default constructor shall not exist.
IntNumberType main_denom() const
Compute the main denominator of all numeric coefficients of this polynomial.
UnderlyingNumberType< Coefficient >::type numeric_content() const
Obtains the numeric content part of this polynomial.
UnivariatePolynomial(Variable mainVar, std::initializer_list< typename UnderlyingNumberType< C >::type > coefficients)
Construct polynomial with the given coefficients from the underlying number type of the coefficient t...
UnivariatePolynomial & normalizeCoefficients()
uint total_degree() const
Returns the total degree of the polynomial, that is the maximum degree of any monomial.
Coefficient unit_part() const
The unit part of a polynomial over a field is its leading coefficient for nonzero polynomials,...
friend std::ostream & operator<<(std::ostream &os, const UnivariatePolynomial< C > &rhs)
Streaming operator for univariate polynomials.
friend UnivariatePolynomial< MultivariatePolynomial< C, O, P > > operator*(const C &lhs, const UnivariatePolynomial< MultivariatePolynomial< C, O, P >> &rhs)
Perform a multiplication involving a polynomial.
UnivariatePolynomial & operator=(const UnivariatePolynomial &p)
Copy assignment operator.
UnivariatePolynomial operator-() const
UnivariatePolynomial< Coefficient > evaluateCoefficient(const std::map< Variable, SubstitutionType > &) const
UnderlyingNumberType< Coefficient >::type coprime_factor() const
void truncate()
Removes the leading term from the polynomial.
friend bool operator==(const C &lhs, const UnivariatePolynomial< C > &rhs)
Checks if the two arguments are equal.
UnivariatePolynomial(UnivariatePolynomial &&p) noexcept
Move constructor.
friend bool operator==(const UnivariatePolynomial< C > &lhs, const C &rhs)
Checks if the two arguments are equal.
UnivariatePolynomial & operator*=(Variable rhs)
Multiply this polynomial with something and return the changed polynomial.
std::vector< Coefficient > mCoefficients
The coefficients.
typename UnderlyingNumberType< Coefficient >::type NumberType
The number type that is ultimately used for the coefficients.
UnivariatePolynomial mod(const Coefficient &modulus) const
Constructs a new polynomial where every coefficient c is replaced by c mod modulus.
std::vector< Coefficient > & coefficients() &
Returns the coefficients as non-const reference.
friend bool operator==(const UnivariatePolynomialPtr< C > &lhs, const UnivariatePolynomialPtr< C > &rhs)
Checks if the two arguments are equal.
UnivariatePolynomial(const UnivariatePolynomial &p)
Copy constructor.
NumberType numeric_content(std::size_t i) const
Returns the numeric content part of the i'th coefficient.
UnivariatePolynomial reverse_coefficients() const
Reverse coefficients safely.
uint degree() const
Get the maximal exponent of the main variable.
NumberType constant_part() const
Returns the constant part of this polynomial.
Coefficient evaluate(const Coefficient &value) const
UnivariatePolynomial pow(std::size_t exp) const
Returns this polynomial to the given power.
friend UnivariatePolynomial< MultivariatePolynomial< C, O, P > > operator*(const UnivariatePolynomial< MultivariatePolynomial< C, O, P >> &lhs, const C &rhs)
Perform a multiplication involving a polynomial.
friend bool operator<(const UnivariatePolynomial< C > &lhs, const UnivariatePolynomial< C > &rhs)
bool zero_is_root() const
Checks if zero is a real root of this polynomial.
UnivariatePolynomial negate_variable() const
Constructs a new polynomial q such that where p is this polynomial.
UnivariatePolynomial & operator/=(const Coefficient &rhs)
Divide this polynomial by something and return the changed polynomial.
UnivariatePolynomial< NumberType > toNumberCoefficients() const
Asserts that is_univariate() is true.
UnivariatePolynomial< typename IntegralType< Coefficient >::type > to_integer_domain() const
Works only from rationals, if the numbers are already integers.
friend UnivariatePolynomial< C > operator/(const UnivariatePolynomial< C > &lhs, const C &rhs)
Perform a division involving a polynomial.
UnivariatePolynomial< Coefficient > coprime_coefficients() const
friend UnivariatePolynomial< C > operator+(const UnivariatePolynomial< C > &lhs, const UnivariatePolynomial< C > &rhs)
Performs an addition involving a polynomial.
bool is_univariate() const
Checks if the polynomial is univariate, that means if only one variable occurs.
UnivariatePolynomial normalized() const
The normal part of a polynomial is the polynomial divided by the unit part.
UnivariatePolynomial< typename IntegralType< Coefficient >::type > coprime_coefficients_sign_preserving() const
friend UnivariatePolynomial< C > operator-(const UnivariatePolynomial< C > &lhs, const UnivariatePolynomial< C > &rhs)
Performs a subtraction involving a polynomial.
UnivariatePolynomial< GFNumber< typename IntegralType< Coefficient >::type > > toFiniteDomain(const GaloisField< typename IntegralType< Coefficient >::type > *galoisField) const
typename IntegralType< NumberType >::type IntNumberType
The integral type that belongs to the number type.
The general-purpose multivariate polynomial class.
States if a type is a number type.
Definition: typetraits.h:237
std::size_t operator()(const carl::UnivariatePolynomial< Coefficient > &p) const
Calculates the hash of univariate polynomial.
bool operator()(const carl::UnivariatePolynomialPtr< Coefficient > &lhs, const carl::UnivariatePolynomialPtr< Coefficient > &rhs) const
Compares two shared pointers to univariate polynomials.
bool operator()(const carl::UnivariatePolynomial< Coefficient > &lhs, const carl::UnivariatePolynomial< Coefficient > &rhs) const
Compares two univariate polynomials.
bool operator()(const carl::UnivariatePolynomial< Coefficient > *lhs, const carl::UnivariatePolynomial< Coefficient > *rhs) const
Compares two pointers to univariate polynomials.
less(carl::PolynomialComparisonOrder _order=carl::PolynomialComparisonOrder::Default) noexcept