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);
353 assert(false); // not implemented
357 template<typename Coeff>
358 template<typename C, EnableIf<is_instantiation_of<GFNumber, C>>>
359 UnivariatePolynomial<typename IntegralType<Coeff>::type> UnivariatePolynomial<Coeff>::to_integer_domain() const
361 UnivariatePolynomial<typename IntegralType<Coeff>::type> res(mMainVar);
362 res.mCoefficients.reserve(mCoefficients.size());
363 for(const Coeff& c : mCoefficients)
365 assert(carl::is_integer(c));
366 res.mCoefficients.push_back(c.representing_integer());
368 res.strip_leading_zeroes();
372 template<typename Coeff>
373 template<typename C, DisableIf<is_instantiation_of<GFNumber, C>>>
374 UnivariatePolynomial<typename IntegralType<Coeff>::type> UnivariatePolynomial<Coeff>::to_integer_domain() const
376 UnivariatePolynomial<typename IntegralType<Coeff>::type> res(mMainVar);
377 res.mCoefficients.reserve(mCoefficients.size());
378 for(const Coeff& c : mCoefficients)
380 assert(carl::is_integer(c));
381 res.mCoefficients.push_back(get_num(c));
383 res.strip_leading_zeroes();
387 template<typename Coeff>
388 //template<typename T = Coeff, EnableIf<!std::is_same<IntegralType<Coeff>, bool>::value>>
389 UnivariatePolynomial<GFNumber<typename IntegralType<Coeff>::type>> UnivariatePolynomial<Coeff>::toFiniteDomain(const GaloisField<typename IntegralType<Coeff>::type>* galoisField) const
391 UnivariatePolynomial<GFNumber<typename IntegralType<Coeff>::type>> res(mMainVar);
392 res.mCoefficients.reserve(mCoefficients.size());
393 for(const Coeff& c : mCoefficients)
395 assert(carl::is_integer(c));
396 res.mCoefficients.push_back(GFNumber<typename IntegralType<Coeff>::type>(c,galoisField));
398 res.strip_leading_zeroes();
403 template<typename Coeff>
404 template<typename N, EnableIf<is_subset_of_rationals_type<N>>>
405 typename UnivariatePolynomial<Coeff>::NumberType UnivariatePolynomial<Coeff>::numeric_content() const
407 if (carl::is_zero(*this)) return NumberType(0);
408 // Obtain main denominator for all coefficients.
409 IntNumberType mainDenom = this->main_denom();
411 // now, some coefficient * mainDenom is always integral.
412 // we convert such a product to an integral data type by get_num()
413 UnivariatePolynomial<Coeff>::NumberType c = this->numeric_content(0) * mainDenom;
414 assert(get_denom(c) == 1);
415 IntNumberType res = get_num(c);
416 for (std::size_t i = 1; i < this->mCoefficients.size(); i++) {
417 c = this->numeric_content(i) * mainDenom;
418 assert(get_denom(c) == 1);
419 res = carl::gcd(get_num(c), res);
421 return NumberType(res) / mainDenom;
424 template<typename Coeff>
425 template<typename C, EnableIf<is_number_type<C>>>
426 typename UnivariatePolynomial<Coeff>::IntNumberType UnivariatePolynomial<Coeff>::main_denom() const
428 IntNumberType denom = 1;
429 for (const auto& c: mCoefficients) {
430 denom = carl::lcm(denom, get_denom(c));
432 CARL_LOG_TRACE("carl.core", "mainDenom of " << *this << " is " << denom);
435 template<typename Coeff>
436 template<typename C, DisableIf<is_number_type<C>>>
437 typename UnivariatePolynomial<Coeff>::IntNumberType UnivariatePolynomial<Coeff>::main_denom() const
439 IntNumberType denom = 1;
440 for (const auto& c: mCoefficients) {
441 denom = carl::lcm(denom, c.main_denom());
446 template<typename Coeff>
447 Coeff UnivariatePolynomial<Coeff>::synthetic_division(const Coeff& zeroOfDivisor)
449 if(coefficients().empty()) return Coeff(0);
450 if(coefficients().size() == 1) return coefficients().back();
451 std::vector<Coeff> secondRow;
452 secondRow.reserve(coefficients().size());
453 secondRow.push_back(Coeff(0));
454 std::vector<Coeff> thirdRow(coefficients().size(), Coeff(0));
455 size_t posThirdRow = coefficients().size()-1;
456 auto coeff = coefficients().rbegin();
457 thirdRow[posThirdRow] = (*coeff) + secondRow.front();
459 while(coeff != coefficients().rend())
461 secondRow.push_back(zeroOfDivisor*thirdRow[posThirdRow]);
463 thirdRow[posThirdRow] = (*coeff) + secondRow.back();
466 assert(posThirdRow == 0);
467 CARL_LOG_TRACE("carl.core.upoly", "UnivSynDiv: (" << *this << ")[x -> " << zeroOfDivisor << "] = " << thirdRow.front());
468 if(thirdRow.front() == 0)
470 thirdRow.erase(thirdRow.begin());
471 this->mCoefficients.swap(thirdRow);
472 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);
475 return thirdRow.front();
478 template<typename Coeff>
479 UnivariatePolynomial<Coeff> UnivariatePolynomial<Coeff>::operator -() const
481 UnivariatePolynomial result(mMainVar);
482 result.mCoefficients.reserve(mCoefficients.size());
483 for(const auto& c : mCoefficients) {
484 result.mCoefficients.push_back(-c);
490 template<typename Coefficient>
491 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator+=(const Coefficient& rhs)
493 if(rhs == Coefficient(0)) return *this;
494 if(mCoefficients.empty())
496 // Adding non-zero rhs to zero.
497 mCoefficients.resize(1, rhs);
501 mCoefficients.front() += rhs;
502 if(mCoefficients.size() == 1 && mCoefficients.front() == Coefficient(0))
505 mCoefficients.clear();
511 template<typename Coeff>
512 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator+=(const UnivariatePolynomial& rhs)
514 assert(mMainVar == rhs.mMainVar);
516 if(carl::is_zero(rhs))
521 if(mCoefficients.size() < rhs.mCoefficients.size())
523 for(std::size_t i = 0; i < mCoefficients.size(); ++i)
525 mCoefficients[i] += rhs.mCoefficients[i];
527 mCoefficients.insert(mCoefficients.end(), rhs.mCoefficients.end() - sint(rhs.mCoefficients.size() - mCoefficients.size()), rhs.mCoefficients.end());
531 for(std::size_t i = 0; i < rhs.mCoefficients.size(); ++i)
533 mCoefficients[i] += rhs.mCoefficients[i];
536 strip_leading_zeroes();
541 UnivariatePolynomial<C> operator+(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
543 UnivariatePolynomial<C> res(lhs);
549 UnivariatePolynomial<C> operator+(const UnivariatePolynomial<C>& lhs, const C& rhs)
551 UnivariatePolynomial<C> res(lhs);
557 UnivariatePolynomial<C> operator+(const C& lhs, const UnivariatePolynomial<C>& rhs)
563 template<typename Coefficient>
564 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator-=(const Coefficient& rhs)
566 // CARL_LOG_INEFFICIENT();
567 return *this += -rhs;
570 template<typename Coeff>
571 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator-=(const UnivariatePolynomial& rhs)
573 // CARL_LOG_INEFFICIENT();
574 return *this += -rhs;
579 UnivariatePolynomial<C> operator-(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
581 UnivariatePolynomial<C> res(lhs);
587 UnivariatePolynomial<C> operator-(const UnivariatePolynomial<C>& lhs, const C& rhs)
589 UnivariatePolynomial<C> res(lhs);
595 UnivariatePolynomial<C> operator-(const C& lhs, const UnivariatePolynomial<C>& rhs)
600 template<typename Coefficient>
601 template<typename C, EnableIf<is_number_type<C>>>
602 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator*=(Variable rhs) {
603 if (rhs == this->mMainVar) {
604 this->mCoefficients.insert(this->mCoefficients.begin(), Coefficient(0));
607 assert(!carl::is_number_type<Coefficient>::value);
610 template<typename Coefficient>
611 template<typename C, DisableIf<is_number_type<C>>>
612 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator*=(Variable rhs) {
613 if (rhs == this->mMainVar) {
614 this->mCoefficients.insert(this->mCoefficients.begin(), Coefficient(0));
617 assert(!carl::is_number_type<Coefficient>::value);
618 for (auto& c: this->mCoefficients) c *= rhs;
622 template<typename Coefficient>
623 UnivariatePolynomial<Coefficient>& UnivariatePolynomial<Coefficient>::operator*=(const Coefficient& rhs)
625 if(rhs == Coefficient(0))
627 mCoefficients.clear();
630 for(Coefficient& c : mCoefficients)
635 if(is_finite_type<Coefficient>::value)
637 strip_leading_zeroes();
644 template<typename Coeff>
645 template<typename I, DisableIf<std::is_same<Coeff, I>>...>
646 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator*=(const typename IntegralType<Coeff>::type& rhs)
648 static_assert(std::is_same<Coeff, I>::value, "Do not provide template parameters");
651 mCoefficients.clear();
654 for(Coeff& c : mCoefficients)
661 template<typename Coeff>
662 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator*=(const UnivariatePolynomial& rhs)
664 assert(mMainVar == rhs.mMainVar);
665 if(carl::is_zero(rhs))
667 mCoefficients.clear();
671 std::vector<Coeff> newCoeffs;
672 newCoeffs.reserve(mCoefficients.size() + rhs.mCoefficients.size());
673 for(std::size_t e = 0; e < mCoefficients.size() + rhs.degree(); ++e)
675 newCoeffs.push_back(Coeff(0));
676 for(std::size_t i = 0; i < mCoefficients.size() && i <= e; ++i)
678 if(e - i < rhs.mCoefficients.size())
680 newCoeffs.back() += mCoefficients[i] * rhs.mCoefficients[e-i];
684 mCoefficients.swap(newCoeffs);
685 strip_leading_zeroes();
691 UnivariatePolynomial<C> operator*(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
693 UnivariatePolynomial<C> res(lhs);
699 UnivariatePolynomial<C> operator*(const UnivariatePolynomial<C>& lhs, Variable rhs) {
700 return std::move(UnivariatePolynomial<C>(lhs) *= rhs);
703 UnivariatePolynomial<C> operator*(Variable lhs, const UnivariatePolynomial<C>& rhs) {
704 return std::move(UnivariatePolynomial<C>(rhs) *= lhs);
708 UnivariatePolynomial<C> operator*(const UnivariatePolynomial<C>& lhs, const C& rhs)
710 UnivariatePolynomial<C> res(lhs);
716 UnivariatePolynomial<C> operator*(const C& lhs, const UnivariatePolynomial<C>& rhs)
722 UnivariatePolynomial<C> operator*(const UnivariatePolynomial<C>& lhs, const IntegralTypeIfDifferent<C>& rhs)
724 UnivariatePolynomial<C> res(lhs);
730 UnivariatePolynomial<C> operator*(const IntegralTypeIfDifferent<C>& lhs, const UnivariatePolynomial<C>& rhs)
737 template<typename Coeff>
738 template<typename C, EnableIf<is_field_type<C>>>
739 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator/=(const Coeff& rhs)
741 assert(rhs != Coeff(0));
742 for(Coeff& c : mCoefficients)
749 template<typename Coeff>
750 template<typename C, DisableIf<is_field_type<C>>>
751 UnivariatePolynomial<Coeff>& UnivariatePolynomial<Coeff>::operator/=(const Coeff& rhs)
753 assert(rhs != Coeff(0));
754 for(Coeff& c : mCoefficients)
756 c = quotient(c, rhs);
758 /// TODO not fully sure whether this is necessary
759 this->strip_leading_zeroes();
766 UnivariatePolynomial<C> operator/(const UnivariatePolynomial<C>& lhs, const C& rhs)
769 if(carl::is_zero(lhs)) return lhs;
770 UnivariatePolynomial<C> res(lhs);
775 bool operator==(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
777 assert(lhs.is_consistent());
778 assert(rhs.is_consistent());
779 if(lhs.mMainVar == rhs.mMainVar)
781 return lhs.mCoefficients == rhs.mCoefficients;
785 // in different variables, polynomials can still be equal if constant.
786 if(carl::is_zero(lhs) && carl::is_zero(rhs)) return true;
787 if ((lhs.mCoefficients.size() == 1) && (rhs.mCoefficients.size() == 1) && (lhs.mCoefficients == rhs.mCoefficients)) return true;
788 // Convert to multivariate and compare that.
789 return MultivariatePolynomial<typename carl::UnderlyingNumberType<C>::type>(lhs) == MultivariatePolynomial<typename carl::UnderlyingNumberType<C>::type>(rhs);
793 bool operator==(const UnivariatePolynomialPtr<C>& lhs, const UnivariatePolynomialPtr<C>& rhs)
795 if (lhs == nullptr && rhs == nullptr) return true;
796 if (lhs == nullptr || rhs == nullptr) return false;
801 bool operator==(const UnivariatePolynomial<C>& lhs, const C& rhs)
803 if (lhs.coefficients().size() == 0) {
804 return carl::is_zero(rhs);
806 return (lhs.coefficients().size() == 1) && lhs.lcoeff() == rhs;
810 bool operator==(const C& lhs, const UnivariatePolynomial<C>& rhs)
817 bool operator!=(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
819 return !(lhs == rhs);
822 bool operator!=(const UnivariatePolynomialPtr<C>& lhs, const UnivariatePolynomialPtr<C>& rhs)
824 if (lhs == nullptr && rhs == nullptr) return false;
825 if (lhs == nullptr || rhs == nullptr) return true;
830 bool UnivariatePolynomial<C>::less(const UnivariatePolynomial<C>& rhs, const PolynomialComparisonOrder& order) const {
832 case PolynomialComparisonOrder::CauchyBound: /*{
833 C a = this->cauchyBound();
834 C b = rhs.cauchyBound();
835 if (a < b) return true;
838 case PolynomialComparisonOrder::LowDegree:
839 if (carl::is_zero(rhs)) return false;
840 if (carl::is_zero(*this) || this->degree() < rhs.degree()) return true;
842 case PolynomialComparisonOrder::Memory:
849 bool operator<(const UnivariatePolynomial<C>& lhs, const UnivariatePolynomial<C>& rhs)
851 if(lhs.mMainVar == rhs.mMainVar)
853 if(lhs.coefficients().size() == rhs.coefficients().size())
855 auto iterLhs = lhs.coefficients().rbegin();
856 auto iterRhs = rhs.coefficients().rbegin();
857 while(iterLhs != lhs.coefficients().rend())
859 assert(iterRhs != rhs.coefficients().rend());
860 if(*iterLhs == *iterRhs)
867 return *iterLhs < *iterRhs;
871 return lhs.coefficients().size() < rhs.coefficients().size();
873 return lhs.mMainVar < rhs.mMainVar;
877 std::ostream& operator<<(std::ostream& os, const UnivariatePolynomial<C>& rhs)
879 if(carl::is_zero(rhs)) return os << "0";
880 for(size_t i = 0; i < rhs.mCoefficients.size()-1; ++i )
882 const C& c = rhs.mCoefficients[rhs.mCoefficients.size()-i-1];
885 if (!(c == 1)) os << "(" << c << ")*";
886 os << rhs.mMainVar << "^" << rhs.mCoefficients.size()-i-1 << " + ";
889 os << rhs.mCoefficients[0];
893 template<typename Coefficient>
894 template<typename C, EnableIf<is_number_type<C>>>
895 bool UnivariatePolynomial<Coefficient>::is_consistent() const {
896 if (!mCoefficients.empty()) {
897 assert(!carl::is_zero(lcoeff()));
902 template<typename Coefficient>
903 template<typename C, DisableIf<is_number_type<C>>>
904 bool UnivariatePolynomial<Coefficient>::is_consistent() const {
905 if (!mCoefficients.empty()) {
906 assert(!carl::is_zero(lcoeff()));
908 for (const auto& c: mCoefficients) {
909 assert(!c.has(main_var()));
910 assert(c.is_consistent());