14template <
typename C,
typename D, D M>
18template <
typename T,
typename D, D M>
23template <
typename T,
typename C,
typename D, D M>
27template <
typename C,
typename D, D M>
34template <
typename T,
typename C,
typename D, D M>
35[[nodiscard]]
int signOfProductsDiff(
const SparsePolynomial<C,D,M>& a,
const SparsePolynomial<C,D,M>& b,
36 const SparsePolynomial<C,D,M>& c,
const SparsePolynomial<C,D,M>& d );
43template <
typename C,
typename D, D M>
46 static_assert(
M > 0 );
49 using Term = std::pair<D, C>;
70 auto it = std::lower_bound( terms_.begin(), terms_.end(), d,
71 [](
const Term & t, D d ) { return t.first < d; } );
72 if ( it != terms_.end() && it->first == d )
77 [[nodiscard]]
bool empty()
const {
return terms_.empty(); }
83 [[nodiscard]]
const std::vector<Term> &
get()
const {
return terms_; }
89 template <
typename T,
typename C2,
typename D2, D2 M2>
96 std::vector<Term> terms_;
99template <
typename C,
typename D, D M>
103 for (
size_t i = 0; i < terms_.size(); ++i )
105 assert( terms_[i].first <=
M );
106 assert( terms_[i].second != 0 );
107 assert( i == 0 || terms_[i - 1].first < terms_[i].first );
112template <
typename C,
typename D, D M>
118 terms_.emplace_back( D(0), c0 );
120 terms_.emplace_back( d1, c1 );
123template <
typename C,
typename D, D M>
132 terms_.emplace_back( D(0), c0 );
139 terms_.emplace_back( d1, c1 );
141 terms_.emplace_back( d2, c2 );
144template <
typename C,
typename D, D M>
147 std::sort( terms.begin(), terms.end(), [](
const Term & x,
const Term & y ) { return x.first < y.first; } );
148 assert( terms.empty() || terms.back().first <=
M );
150 res.terms_ = std::move( terms );
155template <
typename C,
typename D, D M>
158 if ( !terms_.empty() )
159 return terms_.front().second > 0;
165template <
typename C,
typename D, D M>
166void SparsePolynomial<C,D,M>::mergeTerms_()
169 for (
size_t i = 0; i < terms_.size(); )
171 auto deg = terms_[i].first;
172 auto cf = std::move( terms_[i].second );
173 for ( ++i; i < terms_.size() && terms_[i].first == deg; ++i )
174 cf += terms_[i].second;
176 terms_[out++] = { deg, std::move( cf ) };
178 terms_.resize( out );
181template <
typename C,
typename D, D M>
184 std::vector<Term> res;
185 res.reserve( terms_.size() + b.terms_.size() );
186 std::merge( std::make_move_iterator( terms_.begin() ), std::make_move_iterator( terms_.end() ),
187 b.terms_.begin(), b.terms_.end(), std::back_inserter( res ),
188 [](
const Term & x,
const Term & y ) { return x.first < y.first; } );
189 terms_ = std::move( res );
194template <
typename C,
typename D, D M>
197 std::vector<Term> res;
198 res.reserve( terms_.size() + b.terms_.size() );
199 auto itA = terms_.begin();
200 auto itB = b.terms_.begin();
201 while ( itA != terms_.end() && itB != b.terms_.end() )
203 if ( itB->first < itA->first )
205 res.emplace_back( itB->first, -itB->second );
210 res.push_back( std::move( *itA ) );
214 for ( ; itA != terms_.end(); ++itA )
215 res.push_back( std::move( *itA ) );
216 for ( ; itB != b.terms_.end(); ++itB )
217 res.emplace_back( itB->first, -itB->second );
218 terms_ = std::move( res );
223template <
typename T,
typename C,
typename D, D M>
227 using Term =
typename Res::Term;
228 std::vector<Term> res;
229 res.reserve( a.terms_.size() * b.terms_.size() );
230 for (
const auto & [degA, cfA] : a.terms_ )
233 for (
const auto & [degB, cfB] : b.terms_ )
236 const auto deg = degA + degB;
239 res.emplace_back( deg, T( cfA ) * T( cfB ) );
242 return Res::fromUnsortedTerms( std::move( res ) );
245template <
typename T,
typename C,
typename D, D M>
257 auto greater = [](
const RowTerm & x,
const RowTerm & y ) {
return x.deg > y.deg; };
258 std::vector<RowTerm> heap;
259 heap.reserve( a.
get().size() + c.
get().size() );
261 if ( !b.
get().empty() )
262 for (
int i = 0; i < (int)a.
get().
size() && a.
get()[i].first + b.
get()[0].first <=
M; ++i )
263 heap.push_back( { a.
get()[i].first + b.
get()[0].first, i, 0,
false } );
264 if ( !d.
get().empty() )
265 for (
int i = 0; i < (int)c.
get().
size() && c.
get()[i].first + d.
get()[0].first <=
M; ++i )
266 heap.push_back( { c.
get()[i].first + d.
get()[0].first, i, 0,
true } );
267 std::make_heap( heap.begin(), heap.end(), greater );
269 while ( !heap.empty() )
271 const auto deg = heap.front().deg;
272 decltype( std::declval<T>() * std::declval<T>() ) coeff{};
275 std::pop_heap( heap.begin(), heap.end(), greater );
276 auto r = heap.back();
278 const auto & f = ( r.neg ? c : a ).
get();
279 const auto & g = ( r.neg ? d : b ).
get();
280 const auto prod = T( f[r.i].second ) * T( g[r.j].second );
285 if ( ++r.j < (
int)g.size() && ( r.deg = f[r.i].first + g[r.j].first ) <=
M )
288 std::push_heap( heap.begin(), heap.end(), greater );
291 while ( !heap.empty() && heap.front().deg == deg );
Definition MRSparsePolynomial.h:45
constexpr const V & get(const Box< V > &box) noexcept
get<0> returns min, get<1> returns max
Definition MRBox.h:400
SparsePolynomialProduct< T, D, M > mulAs(const SparsePolynomial< C, D, M > &a, const SparsePolynomial< C, D, M > &b)
Definition MRSparsePolynomial.h:224
ImVec2 size(const ViewportRectangle &rect)
Definition MRViewport.h:32
bool empty() const
returns true if no single polynomial coefficient is defined
Definition MRSparsePolynomial.h:77
SparsePolynomial & operator-=(const SparsePolynomial &b)
Definition MRSparsePolynomial.h:195
SparsePolynomial()=default
constructs zero polynomial
std::pair< D, C > Term
a not-zero coefficient with its degree
Definition MRSparsePolynomial.h:49
const std::vector< Term > & get() const
gets read-only access to all not-zero coefficients
Definition MRSparsePolynomial.h:83
bool isPositive() const
returns true if the coefficient for the smallest not-zero degress is positive
Definition MRSparsePolynomial.h:156
friend SparsePolynomialProduct< T, D2, M2 > mulAs(const SparsePolynomial< C2, D2, M2 > &a, const SparsePolynomial< C2, D2, M2 > &b)
int signOfProductsDiff(const SparsePolynomial< C, D, M > &a, const SparsePolynomial< C, D, M > &b, const SparsePolynomial< C, D, M > &c, const SparsePolynomial< C, D, M > &d)
Definition MRSparsePolynomial.h:246
void setZeroCoeff(D d)
sets coefficient for given degree to zero
Definition MRSparsePolynomial.h:68
Color operator*(float a, const Color &b)
Definition MRColor.h:119
SparsePolynomial & operator+=(const SparsePolynomial &b)
Definition MRSparsePolynomial.h:182
friend SparsePolynomial operator+(SparsePolynomial a, const SparsePolynomial &b)
Definition MRSparsePolynomial.h:87
friend SparsePolynomial operator-(SparsePolynomial a, const SparsePolynomial &b)
Definition MRSparsePolynomial.h:88
static SparsePolynomial fromUnsortedTerms(std::vector< Term > &&terms)
constructs polynomial from arbitrary terms with degrees not above M: sorts them by degree,...
Definition MRSparsePolynomial.h:145
SparsePolynomial< decltype(std::declval< T >() *std::declval< T >()), D, M > SparsePolynomialProduct
the type of the polynomial with coefficients of the type of the product of two values of type T
Definition MRSparsePolynomial.h:19
only for bindings generation
Definition MRCameraOrientationPlugin.h:8