2 * @file: UnivariatePolynomial.tpp
3 * @author: Sebastian Junges
5 * @since August 26, 2013
10 #include <carl-common/debug/debug.h>
11 #include <carl-common/meta/platform.h>
12 #include <carl-common/meta/SFINAE.h>
13 #include <carl-logging/carl-logging.h>
14 #include "MultivariatePolynomial.h"
15 #include <carl-arith/core/Sign.h>
17 #include "functions/Derivative.h"
18 #include "functions/Division.h"
26 template<typename Coeff>
27 UnivariatePolynomial<Coeff>::UnivariatePolynomial(const UnivariatePolynomial& p):
28 mMainVar(p.mMainVar), mCoefficients(p.mCoefficients)
30 assert(this->is_consistent());
33 template<typename Coeff>
34 UnivariatePolynomial<Coeff>::UnivariatePolynomial(UnivariatePolynomial&& p) noexcept:
35 mMainVar(p.mMainVar), mCoefficients()
37 mCoefficients = std::move(p.mCoefficients);
38 assert(is_consistent());
41 template<typename Coeff>
42 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator=(const UnivariatePolynomial& p) {
43 mMainVar = p.mMainVar;
44 mCoefficients = p.mCoefficients;
45 assert(is_consistent());
49 template<typename Coeff>
50 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator=(UnivariatePolynomial&& p) noexcept {
51 mMainVar = p.mMainVar;
52 mCoefficients = std::move(p.mCoefficients);
53 assert(is_consistent());
57 template<typename Coeff>
58 UnivariatePolynomial<Coeff>::UnivariatePolynomial(Variable mainVar)
59 : mMainVar(mainVar), mCoefficients()
61 assert(this->is_consistent());
63 template<typename Coeff>
64 UnivariatePolynomial<Coeff>::UnivariatePolynomial(Variable mainVar, const Coeff& coeff, std::size_t degree) :
66 mCoefficients(degree+1, Coeff(0)) // We would like to use 0 here, but Coeff(0) is not always constructable (some methods need more parameter)
70 mCoefficients[degree] = coeff;
74 mCoefficients.clear();
76 strip_leading_zeroes();
77 assert(is_consistent());
80 template<typename Coeff>
81 UnivariatePolynomial<Coeff>::UnivariatePolynomial(Variable mainVar, std::initializer_list<Coeff> coefficients)
82 : mMainVar(mainVar), mCoefficients(coefficients)
84 this->strip_leading_zeroes();
85 assert(this->is_consistent());
88 template<typename Coeff>
89 template<typename C, DisableIf<std::is_same<C, typename UnderlyingNumberType<C>::type>>>
90 UnivariatePolynomial<Coeff>::UnivariatePolynomial(Variable mainVar, std::initializer_list<typename UnderlyingNumberType<C>::type> coefficients)
91 : mMainVar(mainVar), mCoefficients()
93 for (auto c: coefficients) {
94 this->mCoefficients.push_back(Coeff(c));
96 this->strip_leading_zeroes();
97 assert(this->is_consistent());
100 template<typename Coeff>
101 UnivariatePolynomial<Coeff>::UnivariatePolynomial(Variable mainVar, const std::vector<Coeff>& coefficients)
102 : mMainVar(mainVar), mCoefficients(coefficients)
104 this->strip_leading_zeroes();
105 assert(this->is_consistent());
108 template<typename Coeff>
109 UnivariatePolynomial<Coeff>::UnivariatePolynomial(Variable mainVar, std::vector<Coeff>&& coefficients)
110 : mMainVar(mainVar), mCoefficients(coefficients)
112 this->strip_leading_zeroes();
113 assert(this->is_consistent());
116 template<typename Coeff>
117 UnivariatePolynomial<Coeff>::UnivariatePolynomial(Variable mainVar, const std::map<uint, Coeff>& coefficients)
120 mCoefficients.reserve(coefficients.rbegin()->first);
121 for (const auto& expAndCoeff : coefficients)
123 if(expAndCoeff.first != mCoefficients.size())
125 mCoefficients.resize(expAndCoeff.first, Coeff(0));
127 mCoefficients.push_back(expAndCoeff.second);
129 this->strip_leading_zeroes();
130 assert(this->is_consistent());
133 template<typename Coeff>
134 Coeff UnivariatePolynomial<Coeff>::evaluate(const Coeff& value) const
138 for(const Coeff& coeff : mCoefficients)
140 result += (coeff * var);
146 template<typename Coeff>
147 bool UnivariatePolynomial<Coeff>::is_normal() const
149 return unit_part() == Coeff(1);
152 template<typename Coefficient>
153 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::mod(const Coefficient& modulus)
155 for(Coefficient& coeff : mCoefficients)
157 coeff = carl::mod(coeff, modulus);
162 template<typename Coefficient>
163 UnivariatePolynomial<Coefficient> UnivariatePolynomial<Coefficient>::mod(const Coefficient& modulus) const
165 UnivariatePolynomial<Coefficient> result;
166 result.mCoefficients.reserve(mCoefficients.size());
167 for(const Coefficient& coeff : mCoefficients)
169 result.mCoefficients.push_back(mod(coeff, modulus));
171 result.strip_leading_zeroes();
175 template<typename Coeff>
176 UnivariatePolynomial<Coeff> UnivariatePolynomial<Coeff>::pow(std::size_t exp) const
178 if (exp == 0) return UnivariatePolynomial(mMainVar, constant_one<Coeff>::get());
179 if (carl::is_zero(*this)) return UnivariatePolynomial(mMainVar);
180 UnivariatePolynomial<Coeff> res(mMainVar, constant_one<Coeff>::get());
181 UnivariatePolynomial<Coeff> mult(*this);
183 if ((exp & 1) != 0) res *= mult;
185 if(exp > 0) mult = mult * mult;
190 template<typename Coeff>
191 template<typename C, DisableIf<is_number_type<C>>>
192 UnivariatePolynomial<typename UnivariatePolynomial<Coeff>::NumberType> UnivariatePolynomial<Coeff>::toNumberCoefficients() const {
193 std::vector<NumberType> coeffs;
194 coeffs.reserve(this->mCoefficients.size());
195 for (auto c: this->mCoefficients) {
196 assert(c.is_constant());
197 coeffs.push_back(c.constant_part());
199 return UnivariatePolynomial<NumberType>(this->mMainVar, coeffs);
202 template<typename Coeff>
203 template<typename NewCoeff>
204 UnivariatePolynomial<NewCoeff> UnivariatePolynomial<Coeff>::convert() const {
205 std::vector<NewCoeff> coeffs;
206 coeffs.resize(this->mCoefficients.size());
207 for (std::size_t i = 0; i < this->mCoefficients.size(); i++) {
208 coeffs[i] = NewCoeff(this->mCoefficients[i]);
210 return UnivariatePolynomial<NewCoeff>(this->mMainVar, coeffs);
213 template<typename Coeff>
214 template<typename NewCoeff>
215 UnivariatePolynomial<NewCoeff> UnivariatePolynomial<Coeff>::convert(const std::function<NewCoeff(const Coeff&)>& f) const {
216 std::vector<NewCoeff> coeffs;
217 coeffs.resize(this->mCoefficients.size());
218 for (std::size_t i = 0; i < this->mCoefficients.size(); i++) {
219 coeffs[i] = f(this->mCoefficients[i]);
221 return UnivariatePolynomial<NewCoeff>(this->mMainVar, coeffs);
224 template<typename Coeff>
225 UnivariatePolynomial<Coeff> UnivariatePolynomial<Coeff>::normalized() const
227 if(carl::is_zero(*this))
231 return *this/unit_part();
234 template<typename Coeff>
235 Coeff UnivariatePolynomial<Coeff>::unit_part() const {
236 if constexpr (is_field_type<Coeff>::value) {
237 // Coeffs from a field
239 } else if constexpr (is_number_type<Coeff>::value) {
240 // Coeffs from a number ring
241 if (carl::is_zero(*this) || lcoeff() > Coeff(0)) {
247 // Coeffs from a polynomial ring
248 if (carl::is_zero(*this) || carl::is_zero(lcoeff()) || lcoeff().lcoeff() > NumberType(0)) {
256 template<typename Coeff>
257 template<typename C, EnableIf<is_subset_of_rationals_type<C>>>
258 Coeff UnivariatePolynomial<Coeff>::coprime_factor() const
260 assert(!carl::is_zero(*this));
261 auto it = mCoefficients.begin();
262 IntNumberType num = get_num(*it);
263 IntNumberType den = get_denom(*it);
264 for (++it; it != mCoefficients.end(); ++it) {
265 num = carl::gcd(num, get_num(*it));
266 den = carl::lcm(den, get_denom(*it));
268 return Coeff(den)/Coeff(num);
271 template<typename Coeff>
272 template<typename C, DisableIf<is_subset_of_rationals_type<C>>>
273 typename UnderlyingNumberType<Coeff>::type UnivariatePolynomial<Coeff>::coprime_factor() const
275 assert(!carl::is_zero(*this));
276 auto it = mCoefficients.begin();
277 typename UnderlyingNumberType<Coeff>::type factor = it->coprime_factor();
278 for (++it; it != mCoefficients.end(); ++it) {
279 factor = carl::lcm(factor, it->coprime_factor());
284 template<typename Coeff>
285 template<typename C, EnableIf<is_subset_of_rationals_type<C>>>
286 UnivariatePolynomial<typename IntegralType<Coeff>::type> UnivariatePolynomial<Coeff>::coprime_coefficients() const
288 CARL_LOG_TRACE("carl.core", *this << " .coprime_coefficients()");
289 // Notice that even if factor is 1, we create a new polynomial
290 UnivariatePolynomial<typename IntegralType<Coeff>::type> result(mMainVar);
291 if (carl::is_zero(*this)) {
294 result.mCoefficients.reserve(mCoefficients.size());
295 Coeff factor = this->coprime_factor();
296 for (const Coeff& coeff: mCoefficients) {
297 assert(get_denom(coeff * factor) == 1);
298 result.mCoefficients.push_back(get_num(coeff * factor));
303 template<typename Coeff>
304 template<typename C, DisableIf<is_subset_of_rationals_type<C>>>
305 UnivariatePolynomial<Coeff> UnivariatePolynomial<Coeff>::coprime_coefficients() const {
306 if (carl::is_zero(*this)) return *this;
307 UnivariatePolynomial<Coeff> result(mMainVar);
308 result.mCoefficients.reserve(mCoefficients.size());
309 auto factor = this->coprime_factor();
310 for (const Coeff& c: mCoefficients) {
311 result.mCoefficients.push_back(factor * c);
316 template<typename Coeff>
317 template<typename C, EnableIf<is_subset_of_rationals_type<C>>>
318 UnivariatePolynomial<typename IntegralType<Coeff>::type> UnivariatePolynomial<Coeff>::coprime_coefficients_sign_preserving() const
320 CARL_LOG_TRACE("carl.core", *this << " .coprime_coefficients_sign_preserving()");
321 // Notice that even if factor is 1, we create a new polynomial
322 UnivariatePolynomial<typename IntegralType<Coeff>::type> result(mMainVar);
323 if (carl::is_zero(*this)) {
326 result.mCoefficients.reserve(mCoefficients.size());
327 Coeff factor = carl::abs(this->coprime_factor());
328 for (const Coeff& coeff: mCoefficients) {
329 assert(get_denom(coeff * factor) == 1);
330 result.mCoefficients.push_back(get_num(coeff * factor));
335 template<typename Coeff>
336 template<typename C, DisableIf<is_subset_of_rationals_type<C>>>
337 UnivariatePolynomial<Coeff> UnivariatePolynomial<Coeff>::coprime_coefficients_sign_preserving() const {
338 if (this->is_zero()) return *this;
339 UnivariatePolynomial<Coeff> result(mMainVar);
340 result.mCoefficients.reserve(mCoefficients.size());
341 auto factor = carl::abs(this->coprime_factor());
342 for (const Coeff& c: mCoefficients) {
343 result.mCoefficients.push_back(factor * c);
348 template<typename Coeff>
349 bool UnivariatePolynomial<Coeff>::divides(const UnivariatePolynomial& divisor) const
351 ///@todo Is this correct?
352 return carl::is_zero(divisor.divideBy(*this).remainder);
355 template<typename Coeff>
356 template<typename C, EnableIf<is_instantiation_of<GFNumber, C>>>
357 UnivariatePolynomial<typename IntegralType<Coeff>::type> UnivariatePolynomial<Coeff>::to_integer_domain() const
359 UnivariatePolynomial<typename IntegralType<Coeff>::type> res(mMainVar);
360 res.mCoefficients.reserve(mCoefficients.size());
361 for(const Coeff& c : mCoefficients)
363 assert(carl::is_integer(c));
364 res.mCoefficients.push_back(c.representing_integer());
366 res.strip_leading_zeroes();
370 template<typename Coeff>
371 template<typename C, DisableIf<is_instantiation_of<GFNumber, C>>>
372 UnivariatePolynomial<typename IntegralType<Coeff>::type> UnivariatePolynomial<Coeff>::to_integer_domain() const
374 UnivariatePolynomial<typename IntegralType<Coeff>::type> res(mMainVar);
375 res.mCoefficients.reserve(mCoefficients.size());
376 for(const Coeff& c : mCoefficients)
378 assert(carl::is_integer(c));
379 res.mCoefficients.push_back(get_num(c));
381 res.strip_leading_zeroes();
385 template<typename Coeff>
386 //template<typename T = Coeff, EnableIf<!std::is_same<IntegralType<Coeff>, bool>::value>>
387 UnivariatePolynomial<GFNumber<typename IntegralType<Coeff>::type>> UnivariatePolynomial<Coeff>::toFiniteDomain(const GaloisField<typename IntegralType<Coeff>::type>* galoisField) const
389 UnivariatePolynomial<GFNumber<typename IntegralType<Coeff>::type>> res(mMainVar);
390 res.mCoefficients.reserve(mCoefficients.size());
391 for(const Coeff& c : mCoefficients)
393 assert(carl::is_integer(c));
394 res.mCoefficients.push_back(GFNumber<typename IntegralType<Coeff>::type>(c,galoisField));
396 res.strip_leading_zeroes();
401 template<typename Coeff>
402 template<typename N, EnableIf<is_subset_of_rationals_type<N>>>
403 typename UnivariatePolynomial<Coeff>::NumberType UnivariatePolynomial<Coeff>::numeric_content() const
405 if (carl::is_zero(*this)) return NumberType(0);
406 // Obtain main denominator for all coefficients.
407 IntNumberType mainDenom = this->main_denom();
409 // now, some coefficient * mainDenom is always integral.
410 // we convert such a product to an integral data type by get_num()
411 UnivariatePolynomial<Coeff>::NumberType c = this->numeric_content(0) * mainDenom;
412 assert(get_denom(c) == 1);
413 IntNumberType res = get_num(c);
414 for (std::size_t i = 1; i < this->mCoefficients.size(); i++) {
415 c = this->numeric_content(i) * mainDenom;
416 assert(get_denom(c) == 1);
417 res = carl::gcd(get_num(c), res);
419 return NumberType(res) / mainDenom;
422 template<typename Coeff>
423 template<typename C, EnableIf<is_number_type<C>>>
424 typename UnivariatePolynomial<Coeff>::IntNumberType UnivariatePolynomial<Coeff>::main_denom() const
426 IntNumberType denom = 1;
427 for (const auto& c: mCoefficients) {
428 denom = carl::lcm(denom, get_denom(c));
430 CARL_LOG_TRACE("carl.core", "mainDenom of " << *this << " is " << denom);
433 template<typename Coeff>
434 template<typename C, DisableIf<is_number_type<C>>>
435 typename UnivariatePolynomial<Coeff>::IntNumberType UnivariatePolynomial<Coeff>::main_denom() const
437 IntNumberType denom = 1;
438 for (const auto& c: mCoefficients) {
439 denom = carl::lcm(denom, c.main_denom());
444 template<typename Coeff>
445 Coeff UnivariatePolynomial<Coeff>::synthetic_division(const Coeff& zeroOfDivisor)
447 if(coefficients().empty()) return Coeff(0);
448 if(coefficients().size() == 1) return coefficients().back();
449 std::vector<Coeff> secondRow;
450 secondRow.reserve(coefficients().size());
451 secondRow.push_back(Coeff(0));
452 std::vector<Coeff> thirdRow(coefficients().size(), Coeff(0));
453 size_t posThirdRow = coefficients().size()-1;
454 auto coeff = coefficients().rbegin();
455 thirdRow[posThirdRow] = (*coeff) + secondRow.front();
457 while(coeff != coefficients().rend())
459 secondRow.push_back(zeroOfDivisor*thirdRow[posThirdRow]);
461 thirdRow[posThirdRow] = (*coeff) + secondRow.back();
464 assert(posThirdRow == 0);
465 CARL_LOG_TRACE("carl.core.upoly", "UnivSynDiv: (" << *this << ")[x -> " << zeroOfDivisor << "] = " << thirdRow.front());
466 if(thirdRow.front() == 0)
468 thirdRow.erase(thirdRow.begin());
469 this->mCoefficients.swap(thirdRow);
470 CARL_LOG_TRACE("carl.core.upoly", "UnivSynDiv: reduced by ((" << carl::abs(get_denom(thirdRow.front())) << ")*" << main_var() << " + (" << (thirdRow.front()<0 ? "-" : "") << carl::abs(get_num(thirdRow.front())) << ")) -> " << *this);
473 return thirdRow.front();
476 template<typename Coeff>
477 UnivariatePolynomial<Coeff> UnivariatePolynomial<Coeff>::operator -() const
479 UnivariatePolynomial result(mMainVar);
480 result.mCoefficients.reserve(mCoefficients.size());
481 for(const auto& c : mCoefficients) {
482 result.mCoefficients.push_back(-c);
488 template<typename Coefficient>
489 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator+=(const Coefficient& rhs)
491 if(rhs == Coefficient(0)) return *this;
492 if(mCoefficients.empty())
494 // Adding non-zero rhs to zero.
495 mCoefficients.resize(1, rhs);
499 mCoefficients.front() += rhs;
500 if(mCoefficients.size() == 1 && mCoefficients.front() == Coefficient(0))
503 mCoefficients.clear();
509 template<typename Coeff>
510 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator+=(const UnivariatePolynomial& rhs)
512 assert(mMainVar == rhs.mMainVar);
514 if(carl::is_zero(rhs))
519 if(mCoefficients.size() < rhs.mCoefficients.size())
521 for(std::size_t i = 0; i < mCoefficients.size(); ++i)
523 mCoefficients[i] += rhs.mCoefficients[i];
525 mCoefficients.insert(mCoefficients.end(), rhs.mCoefficients.end() - sint(rhs.mCoefficients.size() - mCoefficients.size()), rhs.mCoefficients.end());
529 for(std::size_t i = 0; i < rhs.mCoefficients.size(); ++i)
531 mCoefficients[i] += rhs.mCoefficients[i];
534 strip_leading_zeroes();
539 UnivariatePolynomial<C> operator+(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
541 UnivariatePolynomial<C> res(lhs);
547 UnivariatePolynomial<C> operator+(const UnivariatePolynomial<C>& lhs, const C& rhs)
549 UnivariatePolynomial<C> res(lhs);
555 UnivariatePolynomial<C> operator+(const C& lhs, const UnivariatePolynomial<C>& rhs)
561 template<typename Coefficient>
562 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator-=(const Coefficient& rhs)
564 // CARL_LOG_INEFFICIENT();
565 return *this += -rhs;
568 template<typename Coeff>
569 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator-=(const UnivariatePolynomial& rhs)
571 // CARL_LOG_INEFFICIENT();
572 return *this += -rhs;
577 UnivariatePolynomial<C> operator-(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
579 UnivariatePolynomial<C> res(lhs);
585 UnivariatePolynomial<C> operator-(const UnivariatePolynomial<C>& lhs, const C& rhs)
587 UnivariatePolynomial<C> res(lhs);
593 UnivariatePolynomial<C> operator-(const C& lhs, const UnivariatePolynomial<C>& rhs)
598 template<typename Coefficient>
599 template<typename C, EnableIf<is_number_type<C>>>
600 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator*=(Variable rhs) {
601 if (rhs == this->mMainVar) {
602 this->mCoefficients.insert(this->mCoefficients.begin(), Coefficient(0));
605 assert(!carl::is_number_type<Coefficient>::value);
608 template<typename Coefficient>
609 template<typename C, DisableIf<is_number_type<C>>>
610 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator*=(Variable rhs) {
611 if (rhs == this->mMainVar) {
612 this->mCoefficients.insert(this->mCoefficients.begin(), Coefficient(0));
615 assert(!carl::is_number_type<Coefficient>::value);
616 for (auto& c: this->mCoefficients) c *= rhs;
620 template<typename Coefficient>
621 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator*=(const Coefficient& rhs)
623 if(rhs == Coefficient(0))
625 mCoefficients.clear();
628 for(Coefficient& c : mCoefficients)
633 if(is_finite_type<Coefficient>::value)
635 strip_leading_zeroes();
642 template<typename Coeff>
643 template<typename I, DisableIf<std::is_same<Coeff, I>>...>
644 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator*=(const typename IntegralType<Coeff>::type& rhs)
646 static_assert(std::is_same<Coeff, I>::value, "Do not provide template parameters");
649 mCoefficients.clear();
652 for(Coeff& c : mCoefficients)
659 template<typename Coeff>
660 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator*=(const UnivariatePolynomial& rhs)
662 assert(mMainVar == rhs.mMainVar);
663 if(carl::is_zero(rhs))
665 mCoefficients.clear();
669 std::vector<Coeff> newCoeffs;
670 newCoeffs.reserve(mCoefficients.size() + rhs.mCoefficients.size());
671 for(std::size_t e = 0; e < mCoefficients.size() + rhs.degree(); ++e)
673 newCoeffs.push_back(Coeff(0));
674 for(std::size_t i = 0; i < mCoefficients.size() && i <= e; ++i)
676 if(e - i < rhs.mCoefficients.size())
678 newCoeffs.back() += mCoefficients[i] * rhs.mCoefficients[e-i];
682 mCoefficients.swap(newCoeffs);
683 strip_leading_zeroes();
689 UnivariatePolynomial<C> operator*(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
691 UnivariatePolynomial<C> res(lhs);
697 UnivariatePolynomial<C> operator*(const UnivariatePolynomial<C>& lhs, Variable rhs) {
698 return std::move(UnivariatePolynomial<C>(lhs) *= rhs);
701 UnivariatePolynomial<C> operator*(Variable lhs, const UnivariatePolynomial<C>& rhs) {
702 return std::move(UnivariatePolynomial<C>(rhs) *= lhs);
706 UnivariatePolynomial<C> operator*(const UnivariatePolynomial<C>& lhs, const C& rhs)
708 UnivariatePolynomial<C> res(lhs);
714 UnivariatePolynomial<C> operator*(const C& lhs, const UnivariatePolynomial<C>& rhs)
720 UnivariatePolynomial<C> operator*(const UnivariatePolynomial<C>& lhs, const IntegralTypeIfDifferent<C>& rhs)
722 UnivariatePolynomial<C> res(lhs);
728 UnivariatePolynomial<C> operator*(const IntegralTypeIfDifferent<C>& lhs, const UnivariatePolynomial<C>& rhs)
735 template<typename Coeff>
736 template<typename C, EnableIf<is_field_type<C>>>
737 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator/=(const Coeff& rhs)
739 assert(rhs != Coeff(0));
740 for(Coeff& c : mCoefficients)
747 template<typename Coeff>
748 template<typename C, DisableIf<is_field_type<C>>>
749 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator/=(const Coeff& rhs)
751 assert(rhs != Coeff(0));
752 for(Coeff& c : mCoefficients)
754 c = quotient(c, rhs);
756 /// TODO not fully sure whether this is necessary
757 this->strip_leading_zeroes();
764 UnivariatePolynomial<C> operator/(const UnivariatePolynomial<C>& lhs, const C& rhs)
767 if(carl::is_zero(lhs)) return lhs;
768 UnivariatePolynomial<C> res(lhs);
773 bool operator==(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
775 assert(lhs.is_consistent());
776 assert(rhs.is_consistent());
777 if(lhs.mMainVar == rhs.mMainVar)
779 return lhs.mCoefficients == rhs.mCoefficients;
783 // in different variables, polynomials can still be equal if constant.
784 if(carl::is_zero(lhs) && carl::is_zero(rhs)) return true;
785 if ((lhs.mCoefficients.size() == 1) && (rhs.mCoefficients.size() == 1) && (lhs.mCoefficients == rhs.mCoefficients)) return true;
786 // Convert to multivariate and compare that.
787 return MultivariatePolynomial<typename carl::UnderlyingNumberType<C>::type>(lhs) == MultivariatePolynomial<typename carl::UnderlyingNumberType<C>::type>(rhs);
791 bool operator==(const UnivariatePolynomialPtr<C>& lhs, const UnivariatePolynomialPtr<C>& rhs)
793 if (lhs == nullptr && rhs == nullptr) return true;
794 if (lhs == nullptr || rhs == nullptr) return false;
799 bool operator==(const UnivariatePolynomial<C>& lhs, const C& rhs)
801 if (lhs.coefficients().size() == 0) {
802 return carl::is_zero(rhs);
804 return (lhs.coefficients().size() == 1) && lhs.lcoeff() == rhs;
808 bool operator==(const C& lhs, const UnivariatePolynomial<C>& rhs)
815 bool operator!=(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
817 return !(lhs == rhs);
820 bool operator!=(const UnivariatePolynomialPtr<C>& lhs, const UnivariatePolynomialPtr<C>& rhs)
822 if (lhs == nullptr && rhs == nullptr) return false;
823 if (lhs == nullptr || rhs == nullptr) return true;
828 bool UnivariatePolynomial<C>::less(const UnivariatePolynomial<C>& rhs, const PolynomialComparisonOrder& order) const {
830 case PolynomialComparisonOrder::CauchyBound: /*{
831 C a = this->cauchyBound();
832 C b = rhs.cauchyBound();
833 if (a < b) return true;
836 case PolynomialComparisonOrder::LowDegree:
837 if (carl::is_zero(rhs)) return false;
838 if (carl::is_zero(*this) || this->degree() < rhs.degree()) return true;
840 case PolynomialComparisonOrder::Memory:
847 bool operator<(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
849 if(lhs.mMainVar == rhs.mMainVar)
851 if(lhs.coefficients().size() == rhs.coefficients().size())
853 auto iterLhs = lhs.coefficients().rbegin();
854 auto iterRhs = rhs.coefficients().rbegin();
855 while(iterLhs != lhs.coefficients().rend())
857 assert(iterRhs != rhs.coefficients().rend());
858 if(*iterLhs == *iterRhs)
865 return *iterLhs < *iterRhs;
869 return lhs.coefficients().size() < rhs.coefficients().size();
871 return lhs.mMainVar < rhs.mMainVar;
875 std::ostream& operator<<(std::ostream& os, const UnivariatePolynomial<C>& rhs)
877 if(carl::is_zero(rhs)) return os << "0";
878 for(size_t i = 0; i < rhs.mCoefficients.size()-1; ++i )
880 const C& c = rhs.mCoefficients[rhs.mCoefficients.size()-i-1];
883 if (!(c == 1)) os << "(" << c << ")*";
884 os << rhs.mMainVar << "^" << rhs.mCoefficients.size()-i-1 << " + ";
887 os << rhs.mCoefficients[0];
891 template<typename Coefficient>
892 template<typename C, EnableIf<is_number_type<C>>>
893 bool UnivariatePolynomial<Coefficient>::is_consistent() const {
894 if (!mCoefficients.empty()) {
895 assert(!carl::is_zero(lcoeff()));
900 template<typename Coefficient>
901 template<typename C, DisableIf<is_number_type<C>>>
902 bool UnivariatePolynomial<Coefficient>::is_consistent() const {
903 if (!mCoefficients.empty()) {
904 assert(!carl::is_zero(lcoeff()));
906 for (const auto& c: mCoefficients) {
907 assert(!c.has(main_var()));
908 assert(c.is_consistent());