Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
multipoly.h
Go to the documentation of this file.
1/*
2 * MultiPoly<N, CoeffT> class template
3 *
4 * Authors:
5 * Marco Cecchetti <mrcekets at gmail.com>
6 *
7 * Copyright 2008 authors
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it either under the terms of the GNU Lesser General Public
11 * License version 2.1 as published by the Free Software Foundation
12 * (the "LGPL") or, at your option, under the terms of the Mozilla
13 * Public License Version 1.1 (the "MPL"). If you do not alter this
14 * notice, a recipient may use your version of this file under either
15 * the MPL or the LGPL.
16 *
17 * You should have received a copy of the LGPL along with this library
18 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * You should have received a copy of the MPL along with this library
21 * in the file COPYING-MPL-1.1
22 *
23 * The contents of this file are subject to the Mozilla Public License
24 * Version 1.1 (the "License"); you may not use this file except in
25 * compliance with the License. You may obtain a copy of the License at
26 * http://www.mozilla.org/MPL/
27 *
28 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
29 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
30 * the specific language governing rights and limitations.
31 */
32
33#ifndef _GEOM_SL_MULTIPOLY_H_
34#define _GEOM_SL_MULTIPOLY_H_
35
36#include <utility>
37
38#include <array>
39#include <functional>
40#include <type_traits>
41
44
45
46namespace Geom { namespace SL {
47
48/*
49 * MultiPoly<N, CoeffT> class template
50 *
51 * It represents a multi-variate polynomial with N indeterminates
52 * and coefficients of type CoeffT, but it doesn't support explicit
53 * symbol attaching; the indeterminates should be thought as implicitly
54 * defined in an automatic enumerative style: x_(0),...,x_(N-1) .
55 *
56 */
57
58template <size_t N, typename CoeffT>
60{
61public:
63 typedef CoeffT coeff_type;
64 static const size_t rank = N;
65
66public:
68 {
69 }
70
72 : m_poly(std::move(p))
73 {
74 }
75
76 // create a mv polynomial of type c*X^I
81
82 // create a mv polynomial p(x_(N-M),...,x_(N-1))*X'^I
83 // where I.size() == N-M and X'=(x_(0),...,x_(N-M-1))
84 template <size_t M>
87 typename std::enable_if_t<(M > 0) && (M < N)>* = 0)
88 {
90 }
91
92 /*
93 * assignment operators
94 */
96 {
97 m_poly = p;
98 return (*this);
99 }
100
102 {
104 (*this) = MultiPoly(c);
105 return (*this);
106 }
107
108 // return the degree of the mv polynomial wrt the ordering OrderT
109 template <typename OrderT>
114
115 // return the coefficient of the term with the highest degree
116 // wrt the ordering OrderT
117 template <typename OrderT>
119 {
120 return (*this)(degree<OrderT>());
121 }
122
123 template <typename OrderT>
125 {
126 return (*this)(degree<OrderT>());
127 }
128
129 // return the coefficient of the term of degree 0 (wrt all indeterminates)
131 {
132 return (*this)(multi_index_zero(N));
133 }
134
136 {
137 return (*this)(multi_index_zero(N));
138 }
139
140 // access coefficient methods with no out-of-range checking
145
150
151 // safe coefficient get method
156
157 // safe coefficient set method
162
163 // access the mv poly of rank N-1 with no out-of-range checking
164 typename poly_type::coeff_type const&
165 operator[] (size_t const& i) const
166 {
167 return m_poly[i];
168 }
169
170 typename poly_type::coeff_type &
171 operator[] (size_t const& i)
172 {
173 return m_poly[i];
174 }
175
176 // safe access to the mv poly of rank N-1
177 typename poly_type::coeff_type const&
178 coefficient(size_t const& i) const
179 {
180 return m_poly.coefficient(i);
181 }
182
183 void coefficient (size_t const& i,
184 typename poly_type::coeff_type const& c)
185 {
186 m_poly.coefficient(i, c);
187 }
188
189 /*
190 * polynomail evaluation:
191 * T can be any type that is able to be + and * with the coefficient type
192 */
193 template <typename T>
194 T operator() (std::array<T, N> const& X) const
195 {
197 }
198
199 template <typename T>
200 typename std::enable_if_t<(N == 1), T>
201 operator() (T const& x0) const
202 {
203 std::array<T, N> X = {{x0}};
205 }
206
207 template <typename T>
208 typename std::enable_if_t<(N == 2), T>
209 operator() (T const& x0, T const& x1) const
210 {
211 std::array<T, N> X = {{x0, x1}};
213 }
214
215 template <typename T>
216 typename std::enable_if_t<(N == 3), T>
217 operator() (T const& x0, T const& x1, T const& x2) const
218 {
219 std::array<T, N> X = {{x0, x1, x2}};
221 }
222
223 /*
224 * trim leading zero coefficients
225 */
230
231 /*
232 * select the sub multi-variate polynomial with rank M
233 * which is unambiguously characterized by the multi-index I
234 * requirements:
235 * - M > 0 && M < N;
236 * - multi-index size == N-M
237 */
238 template <size_t M>
239 typename mvpoly<M, CoeffT>::type const&
241 typename std::enable_if_t<(M > 0) && (M < N)>* = 0) const
242 {
244 }
245
246 poly_type const& get_poly() const
247 {
248 return m_poly;
249 }
250
251 bool is_zero() const
252 {
253 return ((*this) == zero);
254 }
255
256 // return the opposite mv poly
258 {
259 MultiPoly r(-m_poly);
260 return r;
261 }
262
263 /*
264 * multipoly-multipoly mutating operators
265 */
267 {
268 m_poly += p.m_poly;
269 return (*this);
270 }
271
273 {
274 m_poly -= p.m_poly;
275 return (*this);
276 }
277
279 {
280 m_poly *= p.m_poly;
281 return (*this);
282 }
283
285 {
287 return (*this);
288 }
289
290 bool operator==(MultiPoly const& q) const
291 {
292 return (m_poly == q.m_poly);
293 }
294
295 bool operator!=(MultiPoly const& q) const
296 {
297 return !((*this) == q);
298 }
299
300 /*
301 * multipoly-coefficient mutating operators
302 */
303 MultiPoly& operator+=(CoeffT const& c)
304 {
306 return (*this);
307 }
308
309 MultiPoly& operator-=(CoeffT const& c)
310 {
312 return (*this);
313 }
314
315 MultiPoly& operator*=(CoeffT const& c)
316 {
318 for_each<0>(m_poly, std::bind(mvpoly<0, CoeffT>::multiply_to, std::placeholders::_1, c));
319 return (*this);
320 }
321
322 MultiPoly& operator/=(CoeffT const& c)
323 {
325 for_each<0>(m_poly, std::bind(mvpoly<0, CoeffT>::divide_to, std::placeholders::_1, c));
326 return (*this);
327 }
328
329 /*
330 * multipoly-polynomial mutating operators
331 */
333 {
334 m_poly += p;
335 return (*this);
336 }
337
339 {
340 m_poly -= p;
341 return (*this);
342 }
343
345 {
346 m_poly *= p;
347 return (*this);
348 }
349
350 /*
351 * multipoly<N>-multipoly<M> mutating operators
352 * requirements:
353 * - M > 0 && M < N;
354 * - they must have the same coefficient type.
355 */
356
357 template <size_t M>
358 typename std::enable_if_t<(M > 0) && (M < N), MultiPoly> &
365
366 template <size_t M>
367 typename std::enable_if_t<(M > 0) && (M < N), MultiPoly> &
374
375 template <size_t M>
376 typename std::enable_if_t<(M > 0) && (M < N), MultiPoly> &
378 {
380 for_each<M>(m_poly, std::bind(mvpoly<M, CoeffT>::multiply_to, std::placeholders::_1, p.m_poly));
381 return (*this);
382 }
383
384 /*
385 * we need MultiPoly instantiations to be each other friend
386 * in order to be able of implementing operations between
387 * MultiPoly instantiations with a different ranks
388 */
389 template<size_t M, typename C>
390 friend class MultiPoly;
391
392 template< typename charT, size_t M, typename C>
393 friend
394 std::basic_ostream<charT> &
395 operator<< (std::basic_ostream<charT> & os, const MultiPoly<M, C> & p);
396
397 static const MultiPoly zero;
398 static const MultiPoly one;
399 static const coeff_type zero_coeff;
400 static const coeff_type one_coeff;
401
402private:
404
405}; // end class MultiPoly
406
407
408/*
409 * zero and one element spezcialization for MultiPoly
410 */
411template <size_t N, typename CoeffT>
412struct zero<MultiPoly<N, CoeffT>, false>
413{
415 {
416 CoeffT _0c = zero<CoeffT>()();
417 MultiPoly<N, CoeffT> _0(_0c);
418 return _0;
419 }
420};
421
422
423template <size_t N, typename CoeffT>
424struct one<MultiPoly<N, CoeffT>, false>
425{
427 {
428 CoeffT _1c = one<CoeffT>()();
429 MultiPoly<N, CoeffT> _1(_1c);
430 return _1;
431 }
432};
433
434
435/*
436 * initialization of MultiPoly static data members
437 */
438template <size_t N, typename CoeffT>
439const MultiPoly<N, CoeffT> MultiPoly<N, CoeffT>::one
441
442template <size_t N, typename CoeffT>
443const MultiPoly<N, CoeffT> MultiPoly<N, CoeffT>::zero
445
446template <size_t N, typename CoeffT>
449
450template <size_t N, typename CoeffT>
453
454
455/*
456 * operator<< extended to print out a mv poly type
457 */
458template <typename charT, size_t N, typename CoeffT>
459inline
460std::basic_ostream<charT> &
461operator<< (std::basic_ostream<charT> & os, const MultiPoly<N, CoeffT> & p)
462{
463 return operator<<(os, p.m_poly);
464}
465
466/*
467 * equivalent to multiply by X^I
468 */
469template <size_t N, typename CoeffT>
470inline
471MultiPoly<N, CoeffT>
472operator<< (MultiPoly<N, CoeffT> const& p, multi_index_type const& I)
473{
474 MultiPoly<N, CoeffT> r(p);
475 r <<= I;
476 return r;
477}
478
479/*
480 * MultiPoly<M, CoeffT> - MultiPoly<N, CoeffT> binary mathematical operators
481 */
482
483template <size_t M, size_t N, typename CoeffT>
484inline
485typename std::enable_if_t<(M > 0) && (M <= N), MultiPoly<N, CoeffT> >
487 MultiPoly<M, CoeffT> const& q )
488{
490 r += q;
491 return r;
492}
493
494template <size_t M, size_t N, typename CoeffT>
495inline
496typename std::enable_if_t<(N > 0) && (M > N), MultiPoly<M, CoeffT> >
498 MultiPoly<M, CoeffT> const& q )
499{
501 r += p;
502 return r;
503}
504
505template <size_t M, size_t N, typename CoeffT>
506inline
507typename std::enable_if_t<(M > 0) && (M <= N), MultiPoly<N, CoeffT> >
509 MultiPoly<M, CoeffT> const& q )
510{
512 r -= q;
513 return r;
514}
515
516template <size_t M, size_t N, typename CoeffT>
517inline
518typename std::enable_if_t<(N > 0) && (M > N), MultiPoly<M, CoeffT> >
520 MultiPoly<M, CoeffT> const& q )
521{
523 r += p;
524 return r;
525}
526
527
528template <size_t M, size_t N, typename CoeffT>
529inline
530typename std::enable_if_t<(M > 0) && (M <= N), MultiPoly<N, CoeffT> >
532 MultiPoly<M, CoeffT> const& q )
533{
535 r *= q;
536 return r;
537}
538
539template <size_t M, size_t N, typename CoeffT>
540inline
541typename std::enable_if_t<(N > 0) && (M > N), MultiPoly<M, CoeffT> >
543 MultiPoly<M, CoeffT> const& q )
544{
546 r *= p;
547 return r;
548}
549
550/*
551 * MultiPoly-coefficient and coefficient-MultiPoly binary mathematical operators
552 */
553
554template <size_t N, typename CoeffT>
555inline
557{
559 r += c;
560 return r;
561}
562
563template <size_t N, typename CoeffT>
564inline
566{
568 r += c;
569 return r;
570}
571
572template <size_t N, typename CoeffT>
573inline
575{
577 r -= c;
578 return r;
579}
580
581template <size_t N, typename CoeffT>
582inline
584{
586 r += c;
587 return r;
588}
589
590template <size_t N, typename CoeffT>
591inline
593{
595 r *= c;
596 return r;
597}
598
599template <size_t N, typename CoeffT>
600inline
602{
604 r *= c;
605 return r;
606}
607
608
609template <size_t N, typename CoeffT>
610inline
612{
614 r /= c;
615 return r;
616}
617
618
619
620
621/*
622template< size_t N, typename CoeffT >
623MultiPoly<N, CoeffT>
624factor( MultiPoly<N, CoeffT> const& f,
625 MultiPoly<N, CoeffT> const& g )
626{
627 typedef MultiPoly<N, CoeffT> poly_type;
628
629 if (g == poly_type::one) return f;
630 poly_type h(g), q, r(f);
631 multi_index_type deg_r = r.template degree<ordering::lex>();
632 multi_index_type deg_g = g.template degree<ordering::lex>();
633 multi_index_type deg0 = multi_index_zero(deg_g.size());
634 CoeffT ltg = g(deg_g);
635 if (is_equal(deg_g, deg0)) return (f / ltg);
636 //h(deg_g) = 0;
637// std::cout << "deg_g = " << deg_g << std::endl;
638// std::cout << "ltg = " << ltg << std::endl;
639 CoeffT lt, ltr;
640 multi_index_type deg(1, deg_g.size());
641 size_t iter = 0;
642 while (!is_equal(deg, deg0) && iter < 10000)
643 {
644 ++iter;
645 deg = deg_r - deg_g;
646 ltr = r(deg_r);
647 lt = ltr / ltg;
648 q.coefficient(deg, lt);
649 //r(deg_r) = 0;
650 r -= ((lt * g) << deg);
651 deg_r = r.template degree<ordering::lex>();
652// std::cout << "deg_r = " << deg_r << std::endl;
653// std::cout << "ltr = " << ltr << std::endl;
654// std::cout << "deg = " << deg << std::endl;
655// std::cout << "lt = " << lt << std::endl;
656// std::cout << "q = " << q << std::endl;
657// std::cout << "r = " << r << std::endl;
658
659// break;
660 }
661 //std::cout << "iter = " << iter << std::endl;
662 return q;
663}
664*/
665
666
667} /*end namespace Geom*/ } /*end namespace SL*/
668
669
670
671
672#endif /* _MULTIPOLY_H_ */
673
674
675/*
676 Local Variables:
677 mode:c++
678 c-file-style:"stroustrup"
679 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
680 indent-tabs-mode:nil
681 fill-column:99
682 End:
683*/
684// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
coeff_type const & leading_coefficient() const
Definition multipoly.h:118
poly_type const & get_poly() const
Definition multipoly.h:246
friend std::basic_ostream< charT > & operator<<(std::basic_ostream< charT > &os, const MultiPoly< M, C > &p)
bool operator==(MultiPoly const &q) const
Definition multipoly.h:290
poly_type::coeff_type const & coefficient(size_t const &i) const
Definition multipoly.h:178
coeff_type const & trailing_coefficient() const
Definition multipoly.h:130
MultiPoly & operator*=(poly_type const &p)
Definition multipoly.h:344
MultiPoly & operator=(coeff_type const &c)
Definition multipoly.h:101
MultiPoly & operator*=(CoeffT const &c)
Definition multipoly.h:315
MultiPoly & operator+=(MultiPoly const &p)
Definition multipoly.h:266
static const MultiPoly zero
Definition multipoly.h:397
MultiPoly operator-() const
Definition multipoly.h:257
poly_type::coeff_type const & operator[](size_t const &i) const
Definition multipoly.h:165
coeff_type & leading_coefficient()
Definition multipoly.h:124
MultiPoly & operator/=(CoeffT const &c)
Definition multipoly.h:322
coeff_type const & coefficient(multi_index_type const &I) const
Definition multipoly.h:152
MultiPoly & operator-=(poly_type const &p)
Definition multipoly.h:338
MultiPoly(poly_type p)
Definition multipoly.h:71
static const coeff_type one_coeff
Definition multipoly.h:400
mvpoly< N, CoeffT >::type poly_type
Definition multipoly.h:62
MultiPoly & operator<<=(multi_index_type const &I)
Definition multipoly.h:284
coeff_type const & operator()(multi_index_type const &I) const
Definition multipoly.h:141
mvpoly< M, CoeffT >::type const & select(multi_index_type const &I=multi_index_zero(N-M), typename std::enable_if_t<(M > 0) &&(M< N)> *=0) const
Definition multipoly.h:240
coeff_type & trailing_coefficient()
Definition multipoly.h:135
MultiPoly & operator+=(poly_type const &p)
Definition multipoly.h:332
MultiPoly(coeff_type c, multi_index_type const &I=multi_index_zero(N))
Definition multipoly.h:77
void coefficient(size_t const &i, typename poly_type::coeff_type const &c)
Definition multipoly.h:183
MultiPoly & operator-=(MultiPoly const &p)
Definition multipoly.h:272
MultiPoly & operator=(poly_type const &p)
Definition multipoly.h:95
MultiPoly & operator-=(CoeffT const &c)
Definition multipoly.h:309
bool operator!=(MultiPoly const &q) const
Definition multipoly.h:295
MultiPoly & operator*=(MultiPoly const &p)
Definition multipoly.h:278
multi_index_type degree() const
Definition multipoly.h:110
static const coeff_type zero_coeff
Definition multipoly.h:399
void coefficient(multi_index_type const &I, coeff_type const &c)
Definition multipoly.h:158
MultiPoly & operator+=(CoeffT const &c)
Definition multipoly.h:303
friend class MultiPoly
Definition multipoly.h:390
MultiPoly(MultiPoly< M, CoeffT > const &p, multi_index_type const &I=multi_index_zero(N-M), typename std::enable_if_t<(M > 0) &&(M< N)> *=0)
Definition multipoly.h:85
static const MultiPoly one
Definition multipoly.h:398
bool is_zero() const
Definition multipoly.h:251
coeff_type const & coefficient(size_t i) const
Definition polynomial.h:191
double c[8][4]
@ X
Definition coord.h:48
std::enable_if_t<(M > 0) &&(M<=N), MultiPoly< N, CoeffT > > operator-(MultiPoly< N, CoeffT > const &p, MultiPoly< M, CoeffT > const &q)
Definition multipoly.h:508
std::enable_if_t<(M > 0) &&(M<=N), MultiPoly< N, CoeffT > > operator+(MultiPoly< N, CoeffT > const &p, MultiPoly< M, CoeffT > const &q)
Definition multipoly.h:486
std::valarray< size_t > multi_index_type
Definition multi-index.h:85
MultiPoly< N, CoeffT > operator/(MultiPoly< N, CoeffT > const &p, CoeffT const &c)
Definition multipoly.h:611
multi_index_type multi_index_zero(size_t N)
Definition multi-index.h:90
std::enable_if_t<(M > 0) &&(M<=N), MultiPoly< N, CoeffT > > operator*(MultiPoly< N, CoeffT > const &p, MultiPoly< M, CoeffT > const &q)
Definition multipoly.h:531
Various utility functions.
Definition affine.h:22
std::ostream & operator<<(std::ostream &os, const Bezier &b)
Definition bezier.h:372
STL namespace.
size_t N
static void normalize(type &p)
static T evaluate(type const &p, std::array< T, N > const &X)
static void shift(type &p, multi_index_type const &I)