DGtal 1.3.0
Loading...
Searching...
No Matches
MPolynomial.h
1
17#pragma once
18
36#if defined(MPolynomial_RECURSES)
37#error Recursive header files inclusion detected in MPolynomial.h
38#else // defined(MPolynomial_RECURSES)
40#define MPolynomial_RECURSES
41
42#if !defined MPolynomial_h
44#define MPolynomial_h
45
47// Inclusions
48#include <iostream>
49#include <vector>
50#include "DGtal/base/Common.h"
52
53namespace DGtal
54{
55
56 template < int n, typename TRing,
57 typename TAlloc = std::allocator<TRing> >
58 class MPolynomial;
59 template < int N, int n, typename TRing,
60 typename TAlloc = std::allocator<TRing> >
61 class MPolynomialDerivativeComputer;
62 template < int n, typename TRing,
63 typename TAlloc = std::allocator<TRing>,
64 typename TX = TRing >
65 class MPolynomialEvaluator;
66
67 template < int n, typename TRing, typename TOwner,
68 typename TAlloc, typename TX >
69 class MPolynomialEvaluatorImpl;
70
74 template < typename TRing, typename TAlloc >
79
88 template < typename TRing, typename TOwner,
89 typename TAlloc, typename TX >
90 class MPolynomialEvaluatorImpl< 1, TRing, TOwner, TAlloc, TX >
91 {
92 public:
93 typedef TRing Ring;
94 typedef TOwner Owner;
95 typedef TAlloc Alloc;
96 typedef TX X;
97
98 template <int nn, class TT, class AA, class SS>
100
101 template <int nn, class TT, class HLHL, class AA, class SS>
103
104private:
105 const Owner & myOwner;
106 const X & myEvalPoint;
107
108 inline MPolynomialEvaluatorImpl( const Owner & owner, const X & evalpoint)
109 : myOwner(owner), myEvalPoint(evalpoint)
110 {}
111
115 class EvalFun
116 {
118
119 public:
120 inline
122 owner )
123 : myOwner(owner)
124 {}
125
131 inline
133 {
134 X res = (X) 0;
135 X xx = (X) 1;
136 for ( int i = 0; i < (int) p.myValue.size(); ++i )
137 {
138 res += (X)(Ring) p.myValue[i] * xx;
139 xx = xx * myOwner.myEvalPoint;
140 }
141 return res;
142 }
143 };
144
145public:
149 inline operator X() const
150 {
151 X res = (X) 0;
152 myOwner.evaluate( res, EvalFun( *this ) );
153 return res;
154 }
155
159 inline X operator() () const
160 {
161 return (X)(*this);
162 }
163
164 };
165
180 template < int n, typename TRing, typename TOwner,
181 typename TAlloc, typename TX >
183 {
184 public:
185 typedef TRing Ring;
186 typedef TOwner Owner;
187 typedef TAlloc Alloc;
188 typedef TX X;
191
198 typedef MPolynomial< n - 1, X,
199 typename Alloc::template rebind<X>::other > MPolyNM1;
200
201 template<int nn, class TT, class AA, class SS>
203
204 template<int nn, class TT, class HLHL, class AA, class SS>
206
207 private:
208 const Owner & myOwner; // The "owner"
209 const X & myEvalPoint; // The evaluation point on this level
210
211 inline
212 MPolynomialEvaluatorImpl(const Owner & owner, const X & evalpoint)
213 : myOwner(owner), myEvalPoint(evalpoint)
214 {}
215
221 template < typename XX, typename Fun >
223 {
225 const Fun & myEvalFun;
226
227 public:
228 inline
230 const Fun & evalfun)
231 : myOwner(owner), myEvalFun(evalfun)
232 {}
233
240 inline XX operator() ( const MPolynomial<n, Ring, Alloc> & p ) const
241 {
242 XX res = (XX) 0;
243 X xx = (X) 1;
244 for ( int i = 0; i < (int) p.myValue.size(); ++i )
245 {
246 res += myEvalFun(p.myValue[i]) * (XX) xx;
247 xx = xx * myOwner.myEvalPoint;
248 }
249 return res;
250 }
251 };
252
259 template < typename XX, typename Fun >
260 inline
261 void evaluate( XX & res, const Fun & evalfun ) const
262 {
263 // We have to pass evaluation on to our owner, but give a new
264 // functor which now evaluates polynomials of type poly<n, T>.
265 myOwner.evaluate( res, EvalFun< XX, Fun >( *this, evalfun ) );
266 }
267
275 {
277
278 public:
279 inline
281 : myOwner(owner)
282 {
283 }
284
291 inline MPolyNM1 operator() (const MPolyN & p) const
292 {
293 MPolyNM1 res;
294 X xx = (X) 1;
295 for ( int i = 0; i < (int) p.myValue.size(); ++i )
296 {
297 res += ( (MPolyNM1) p.myValue[i] ) * xx;
298 xx = xx * myOwner.myEvalPoint;
299 }
300 return res;
301 }
302 };
303
304 public:
308 inline
309 operator MPolyNM1() const
310 // operator poly<n - 1, S, typename Alloc::template rebind<S>::other>() const
311 {
312 MPolyNM1 res; // missing: determine allocator object
313 // We need to pass evaluation on to our owner
314 myOwner.evaluate( res, EvalFun2( *this ) );
315 return res;
316 }
317
323 template < typename XX >
324 inline
326 < n - 1, Ring,
328 Alloc, XX > operator() ( const XX & x ) const
329 {
332 Alloc, XX >( *this, x );
333 }
334 };
335
344 template < typename TRing, typename TAlloc, typename TX >
345 class MPolynomialEvaluator< 1, TRing, TAlloc, TX>
346 {
347 friend class MPolynomial< 1, TRing, TAlloc >;
348 public:
349 typedef TRing Ring;
350 typedef TAlloc Alloc;
351 typedef TX X;
353
354 private:
355 const MPoly1 & myPoly;
356 const X & myEvalPoint;
357
358 inline
359 MPolynomialEvaluator( const MPoly1 & poly, const X & evalpoint)
360 : myPoly( poly ), myEvalPoint( evalpoint )
361 {}
362
363 public:
367 inline
368 operator X() const
369 {
370 X res = (X) 0;
371 X xx = (X) 1;
372 for ( int i = 0; i < (int) myPoly.myValue.size(); ++i )
373 {
374 res += ( (X) (Ring) myPoly.myValue[i] ) * xx;
375 xx = xx * myEvalPoint;
376 }
377 return res;
378 }
379
383 inline
385 {
386 return (X) (*this);
387 }
388 };
389
390
399 template < int n, typename TRing, typename TAlloc, typename TX >
401 {
402 friend class MPolynomial< n, TRing, TAlloc>;
403
404 template<int nn, class TT, class HLHL, class AA, class SS>
406
407 public:
408 typedef TRing Ring;
409 typedef TAlloc Alloc;
410 typedef TX X;
412 typedef MPolynomial< n - 1, X,
413 typename Alloc::template rebind<X>::other > MPolyNM1;
414 private:
415 const MPolyN & myPoly;
416 const X & myEvalPoint;
417
418 inline
419 MPolynomialEvaluator( const MPolyN & poly, const X & evalpoint)
420 : myPoly( poly ), myEvalPoint( evalpoint )
421 {}
422
429 template < typename XX, typename Fun >
430 inline
431 void evaluate( XX & res, const Fun & evalfun ) const
432 {
433 X xx = (X) 1;
434 for ( int i = 0; i < (int) myPoly.myValue.size(); ++i )
435 {
436 res += evalfun( myPoly.myValue[i] ) * xx;
437 xx = xx * myEvalPoint;
438 }
439 }
440
441public:
445 inline
446 operator MPolyNM1() const
447 {
449 X xx = (X) 1;
450 for ( int i = 0; i < (int) myPoly.myValue.size(); ++i )
451 {
452 res += MPolyNM1( myPoly.myValue[i] ) * xx;
453 xx = xx * myEvalPoint;
454 }
455 return res;
456 }
457
461 template <typename XX>
462 inline
465 operator() (const XX & x) const
466 {
469 ( *this, x );
470 }
471 };
472
494 template < typename TRing, typename TAlloc >
495 class MPolynomial< 0, TRing, TAlloc >
496 {
497 public:
498 typedef TRing Ring;
499 typedef TAlloc Alloc;
500
501 private:
504
505 public:
513 inline
514 MPolynomial( const Ring & v = 0, const Alloc & allocator = Alloc() )
515 : myAllocator(allocator), myValue(v)
516 {}
517
524 inline
525 MPolynomial( const Alloc & allocator )
526 : myAllocator(allocator), myValue( Ring() )
527 {}
528
532 inline bool isZero() const
533 {
534 return myValue == 0;
535 }
536
541 inline operator const Ring & () const
542 {
543 return myValue;
544 }
545
551 inline MPolynomial & operator = (const Ring & v)
552 {
553 myValue = v;
554 return *this;
555 }
556
561 inline Ring operator() () const
562 {
563 return myValue;
564 }
565
571 inline MPolynomial operator * (const Ring & v) const
572 {
573 return MPolynomial(myValue * v);
574 }
575
581 inline MPolynomial operator / (const Ring & v) const
582 {
583 return MPolynomial(myValue / v);
584 }
585
591 inline MPolynomial operator + (const Ring & v) const
592 {
593 return MPolynomial(myValue + v);
594 }
595
601 inline MPolynomial operator - (const Ring & v) const
602 {
603 return MPolynomial(myValue - v);
604 }
605
611 {
612 return MPolynomial(-myValue);
613 }
614
620 inline MPolynomial & operator *= (const Ring & v)
621 {
622 myValue *= v;
623 return *this;
624 }
625
631 inline MPolynomial & operator /= (const Ring & v)
632 {
633 myValue /= v;
634 return *this;
635 }
636
642 inline MPolynomial & operator += (const Ring & v)
643 {
644 myValue += v;
645 return *this;
646 }
647
653 inline MPolynomial & operator -= (const Ring & v)
654 {
655 myValue -= v;
656 return *this;
657 }
658
664 inline bool operator == (const Ring & v) const
665 {
666 return myValue == v;
667 }
668
674 inline bool operator != (const Ring & v) const
675 {
676 return myValue != v;
677 }
678
683 void selfDisplay( std::ostream & s, int /*N = 0*/ ) const
684 {
685 s << myValue;
686 }
687
692 inline void swap( MPolynomial & p )
693 {
694 std::swap(myValue, p.myValue);
695 }
696
701 {
702 return myAllocator;
703 }
704 };
705
706
719 template < typename T, typename TAlloc = std::allocator<T>,
720 bool usePointers = false>
722 {
723 public:
724 typedef TAlloc Alloc;
725 typedef typename std::vector<T, Alloc>::size_type Size;
726 private:
727 std::vector<T, Alloc> myVec;
728
729 public:
730 IVector( const Alloc & allocator = Alloc() )
731 : myVec(allocator)
732 {}
733
734 IVector( Size aSize, const Alloc & allocator = Alloc() )
735 : myVec( aSize, T(), allocator )
736 {}
737
738 IVector( Size aSize, const T & entry, const Alloc & allocator = Alloc() )
739 : myVec(aSize, entry, allocator)
740 {}
741
742 Size size() const
743 {
744 return myVec.size();
745 }
746
747 void resize( Size aSize, const T & entry = T() )
748 {
749 myVec.resize(aSize, entry);
750 }
751
752 const T & operator[] ( Size i ) const
753 {
754 return myVec[i];
755 }
756
758 {
759 return myVec[i];
760 }
761
762 const T & back() const
763 {
764 return myVec.back();
765 }
766
767 T & back()
768 {
769 return myVec.back();
770 }
771
772 void swap(IVector & v)
773 {
774 myVec.swap( v.myVec );
775 }
776
778 {
779 return myVec.get_allocator();
780 }
781
783 {
784 return myVec.get_allocator();
785 }
786 };
787
792 template < typename T, typename TAlloc>
793 class IVector< T, TAlloc, true >
794 {
795 public:
796 typedef TAlloc Alloc;
797 typedef typename std::vector<typename Alloc::pointer, typename Alloc::template rebind<typename Alloc::pointer>::other>::size_type Size;
798
799 private:
801 std::vector<typename Alloc::pointer, typename Alloc::template rebind<typename Alloc::pointer>::other> myVec;
802
803 void create( Size begin, Size end, typename Alloc::const_reference entry)
804 {
805 for (Size i = begin; i < end; ++i)
806 {
807 myVec[i] = myAllocator.allocate(sizeof(T));
808 myAllocator.construct(myVec[i], entry);
809 }
810 }
811
812 void free(Size begin, Size end)
813 {
814 for (Size i = begin; i < end; ++i)
815 {
816 myAllocator.destroy(myVec[i]);
817 myAllocator.deallocate(myVec[i], sizeof(T));
818 }
819 }
820
821 template<class A>
822 void copy_from(const std::vector<typename Alloc::pointer, A> & source)
823 {
824 for (Size i = 0; i < myVec.size(); ++i)
825 {
826 myVec[i] = myAllocator.allocate(sizeof(T));
827 myAllocator.construct(myVec[i], *source[i]);
828 }
829 }
830
831 public:
832 IVector(const Alloc & allocator = Alloc())
833 : myAllocator(allocator), myVec(allocator)
834 {}
835
836 IVector(Size aSize, const Alloc & allocator = Alloc())
837 : myAllocator(allocator), myVec(aSize, 0, allocator)
838 {
839 create(0, aSize, T());
840 }
841
842 IVector(Size aSize, const T & entry, const Alloc & allocator = Alloc())
843 : myAllocator(allocator), myVec(aSize, 0, allocator)
844 {
845 create(0, aSize, entry);
846 }
847
848 IVector(const IVector & v)
849 : myVec(v.size())
850 {
851 copy_from(v.myVec);
852 }
853
855 {
856 free(0, (Size)myVec.size());
857 }
858
859 IVector & operator = (const IVector & v)
860 {
861 if (&v != this)
862 {
863 free(0, (Size)myVec.size());
864 myVec.resize(v.size());
865 copy_from(v.myVec);
866 }
867 return *this;
868 }
869
870 Size size() const
871 {
872 return (Size)myVec.size();
873 }
874
875 void resize(Size aSize, const T & entry = T())
876 {
877 Size oldsize = (Size)myVec.size();
878 if (oldsize > aSize)
879 free(aSize, oldsize);
880 myVec.resize(aSize);
881 if (oldsize < aSize)
882 create(oldsize, aSize, entry);
883 }
884
885 const T & operator[] (Size i) const
886 {
887 return *myVec[i];
888 }
889
891 {
892 return *myVec[i];
893 }
894
895 const T & back() const
896 {
897 return *myVec.back();
898 }
899
900 T & back()
901 {
902 return *myVec.back();
903 }
904
905 void swap(IVector & v)
906 {
907 myVec.swap(v.myVec);
908 }
909
911 {
912 return myVec.get_allocator();
913 }
914
916 {
917 return myVec.get_allocator();
918 }
919 };
920
921
923 // template class MPolynomial
953 template < int n, typename TRing, class TAlloc >
955 {
956 // ----------------------- friends ---------------------------------------
957
958 template<int NN, int nn, typename TT, typename AA>
960
961 friend void euclidDiv<TRing, TAlloc>
966
967 template<int nn, typename TT, typename AA, typename SS>
969
970 template<int nn, typename TT, typename HLHL, typename AA, typename SS>
972
973 public:
974 typedef TRing Ring;
975 typedef TAlloc Alloc;
976 typedef MPolynomial< n - 1, Ring, Alloc > MPolyNM1;
983 typedef IVector< MPolyNM1,
984 typename Alloc::template rebind<MPolyNM1 >::other, (n>1) >
986 typedef typename Storage::Size Size;
987
988 // ----------------------- Datas ----------------------------
989private:
999
1003 inline
1004 MPolynomial( bool, Size s, const Alloc & /*allocator*/)
1005 : myValue(s)
1006 {}
1007
1008public:
1015 inline void normalize()
1016 {
1017 Size dp1 = myValue.size();
1018 while ( dp1 )
1019 {
1020 if (myValue[dp1 - 1].isZero())
1021 --dp1;
1022 else
1023 break;
1024 }
1025 if (dp1 < myValue.size())
1026 myValue.resize(dp1);
1027 }
1028
1029 // ----------------------- Standard services ----------------------------
1030 public:
1031
1035 inline MPolynomial( const Alloc & allocator = Alloc() )
1036 : myValue( allocator )
1037 {}
1038
1042 inline MPolynomial( const Ring & v, const Alloc & allocator = Alloc() )
1043 : myValue( 1, MPolyNM1( v ), allocator )
1044 {}
1045
1050 inline MPolynomial( const MPolyNM1 & pdm1,
1051 const Alloc & /*allocator = Alloc()*/ )
1052 : myValue( 1, pdm1 )
1053 {}
1054
1059 template < typename Ring2, typename Alloc2 >
1061 const Alloc & allocator = Alloc() )
1062 : myValue( p.degree() + 1, MPolyNM1(), allocator )
1063 {
1064 for ( Size i = 0; i < myValue.size(); ++i )
1065 myValue[i] = p[i];
1066 normalize();
1067 }
1068
1073 template < typename Ring2, typename Alloc2 >
1074 inline
1075 MPolynomial & operator=
1077 {
1078 myValue.resize(p.degree() + 1);
1079 for ( Size i = 0; i < myValue.size(); ++i )
1080 myValue[i] = p[i];
1081 normalize();
1082 return *this;
1083 }
1084
1089 inline void swap( MPolynomial & p )
1090 {
1091 myValue.swap(p.myValue);
1092 }
1093
1098 {
1099 return myValue.getAllocator();
1100 }
1101
1102 // ----------------------- MPolynomial services ----------------------------
1103 public:
1104
1109 inline int degree() const
1110 {
1111 return (int)(myValue.size() - 1);
1112 }
1113
1119 inline const MPolyNM1 & leading() const
1120 {
1121 return myValue.size() ? myValue.back() : myZeroPolynomial;
1122 }
1123
1127 inline bool isZero() const
1128 {
1129 return myValue.size() == 0;
1130 }
1131
1138 {
1139 if (i >= myValue.size())
1140 myValue.resize(i + 1);
1141 return myValue[i];
1142 }
1143
1147 inline const MPolyNM1 & operator[] (Size i) const
1148 {
1149 return i < myValue.size() ? myValue[i] : myZeroPolynomial;
1150 }
1151
1158 inline
1160 {
1162 }
1163
1171 template <typename Ring2>
1172 inline
1174 {
1176 }
1177
1178 // ----------------------- Operators --------------------------------------
1179 public:
1180
1186 inline MPolynomial operator * (const Ring & v) const
1187 {
1188 MPolynomial r(*this);
1189 for ( Size i = 0; i < myValue.size(); ++i )
1190 r[i] *= v;
1191 return r;
1192 }
1193
1199 inline MPolynomial operator / (const Ring & v) const
1200 {
1201 MPolynomial r(*this);
1202 for ( Size i = 0; i < myValue.size(); ++i )
1203 r[i] /= v;
1204 return r;
1205 }
1206
1213 {
1214 return *this = *this * p;
1215 }
1216
1222 inline MPolynomial & operator *= (const Ring & v)
1223 {
1224 MPolynomial r( *this );
1225 for ( Size i = 0; i < myValue.size(); ++i )
1226 myValue[i] *= v;
1227 return *this;
1228 }
1229
1235 inline MPolynomial & operator /= (const Ring & v)
1236 {
1237 for ( Size i = 0; i < myValue.size(); ++i )
1238 myValue[i] /= v;
1239 return *this;
1240 }
1241
1248 friend
1249 inline MPolynomial operator * (const Ring & v, const MPolynomial & p)
1250 {
1251 MPolynomial r(p);
1252 for ( Size i = 0; i < p.myValue.size(); ++i )
1253 r[i] *= v;
1254 return r;
1255 }
1256
1261 {
1262 MPolynomial r( true, myValue.size(), getAllocator() );
1263 for ( Size i = 0; i < myValue.size(); ++i )
1264 r[i] = -myValue[i];
1265 return r;
1266 }
1267
1273 inline MPolynomial operator + (const MPolynomial & q) const
1274 {
1275 MPolynomial r(*this);
1276 if (r.myValue.size() < q.myValue.size())
1277 r.myValue.resize(q.myValue.size());
1278 for ( Size i = 0; i < q.myValue.size(); ++i )
1279 r[i] += q[i];
1280 r.normalize();
1281 return r;
1282 }
1283
1289 inline MPolynomial operator - (const MPolynomial & q) const
1290 {
1291 MPolynomial r(*this);
1292 if (r.myValue.size() < q.myValue.size())
1293 r.myValue.resize(q.myValue.size());
1294 for ( Size i = 0; i < q.myValue.size(); ++i )
1295 r[i] -= q[i];
1296 r.normalize();
1297 return r;
1298 }
1299
1306 {
1307 if (myValue.size() < q.myValue.size())
1308 myValue.resize(q.myValue.size());
1309 for ( Size i = 0; i < q.myValue.size(); ++i )
1310 myValue[i] += q[i];
1311 normalize();
1312 return *this;
1313 }
1314
1321 {
1322 if (myValue.size() < q.myValue.size())
1323 myValue.resize(q.myValue.size());
1324 for ( Size i = 0; i < q.myValue.size(); ++i )
1325 myValue[i] -= q[i];
1326 normalize();
1327 return *this;
1328 }
1329
1336 inline MPolynomial operator + (const MPolyNM1 & q) const
1337 {
1338 MPolynomial r(*this);
1339 if (r.myValue.size() < 1)
1340 r.myValue.resize(1);
1341 r[0] += q;
1342 r.normalize();
1343 return r;
1344 }
1345
1352 inline MPolynomial operator - (const MPolyNM1 & q) const
1353 {
1354 MPolynomial r(*this);
1355 if (r.myValue.size() < 1)
1356 r.myValue.resize(1);
1357 r[0] -= q;
1358 r.normalize();
1359 return r;
1360 }
1361
1367 inline MPolynomial operator + (const Ring & v) const
1368 {
1369 MPolynomial r(*this);
1370 if (r.myValue.size() < 1)
1371 r.myValue.resize(1);
1372 r[0] += v;
1373 r.normalize();
1374 return r;
1375 }
1376
1382 inline MPolynomial operator - (const Ring & v) const
1383 {
1384 MPolynomial r(*this);
1385 if (r.myValue.size() < 1)
1386 r.myValue.resize(1);
1387 r[0] -= v;
1388 r.normalize();
1389 return r;
1390 }
1391
1399 {
1400 if (myValue.size() < 1)
1401 myValue.resize(1);
1402 myValue[0] += q;
1403 normalize();
1404 return *this;
1405 }
1406
1414 {
1415 if (myValue.size() < 1)
1416 myValue.resize(1);
1417 myValue[0] -= q;
1418 normalize();
1419 return *this;
1420 }
1421
1427 inline MPolynomial & operator += (const Ring & v)
1428 {
1429 if (myValue.size() < 1)
1430 myValue.resize(1);
1431 myValue[0] += v;
1432 normalize();
1433 return *this;
1434 }
1435
1441 inline MPolynomial & operator -= (const Ring & v)
1442 {
1443 if (myValue.size() < 1)
1444 myValue.resize(1);
1445 myValue[0] -= v;
1446 normalize();
1447 return *this;
1448 }
1449
1457 inline MPolynomial operator * (const MPolynomial & p) const
1458 {
1459 int d = p.degree() + degree();
1460 if (d < -1)
1461 d = -1;
1462 MPolynomial r( true, d + 1, getAllocator() );
1463 if (!isZero() && !p.isZero())
1464 for ( Size i = 0; i < r.myValue.size(); ++i )
1465 for ( Size j = 0; j < myValue.size(); ++j )
1466 if (i < j + p.myValue.size())
1467 r[i] += myValue[j] * p[i - j];
1468 r.normalize();
1469 return r;
1470 }
1471
1472 // ----------------------- Comparison operators ---------------------------
1473 public:
1474
1480 inline bool operator == (const MPolynomial & q) const
1481 {
1482 if (myValue.size() != q.myValue.size())
1483 return false;
1484 for (Size i = 0; i < myValue.size(); ++i)
1485 if (myValue[i] != q[i])
1486 return false;
1487 return true;
1488 }
1489
1495 inline bool operator != (const MPolynomial & q) const
1496 {
1497 return !(*this == q);
1498 }
1499
1505 inline bool operator == (const Ring & v) const
1506 {
1507 if ((v == 0) && (myValue.size() == 0))
1508 return true;
1509 if (myValue.size() != 1)
1510 return false;
1511 return myValue[0] == v;
1512 }
1513
1519 inline bool operator != (const Ring & v) const
1520 {
1521 return !(*this == v);
1522 }
1523
1524
1525
1526 // ----------------------- Interface --------------------------------------
1527 public:
1528
1536 void selfDisplay ( std::ostream & s, int N = n ) const
1537 {
1538 if (isZero())
1539 s << (Ring) 0;
1540 else
1541 {
1542 Size nonzero = 0;
1543 for (Size i = 0; i < myValue.size(); ++i)
1544 if (!myValue[i].isZero())
1545 ++nonzero;
1546 if (nonzero > 1) s << "(";
1547 bool first = true;
1548 for (Size i = 0; i < myValue.size(); ++i)
1549 if (!myValue[i].isZero())
1550 {
1551 if (first) first = false;
1552 else s << " + ";
1553 myValue[i].selfDisplay(s, N);
1554 if (i > 0)
1555 {
1556 s << " ";
1557 s << "X_" << N - n;
1558 if (i > 1) s << "^" << i;
1559 }
1560 }
1561 if (nonzero > 1)
1562 s << ")";
1563 }
1564 }
1565
1570 bool isValid() const;
1571
1572
1573 // ------------------------- Datas --------------------------------------
1574 private:
1575 // ------------------------- Hidden services ----------------------------
1576 protected:
1577
1578
1579 }; // end of class MPolynomial
1580
1581
1588 template <int N, typename TRing, class TAlloc>
1589 std::ostream&
1590 operator<< ( std::ostream & out,
1591 const MPolynomial<N, TRing, TAlloc> & object );
1592
1593
1594 // ------------------------- monomial services ----------------------------
1595
1602 template <int n, typename Ring, typename Alloc>
1604 {
1605 public:
1607
1614 get( unsigned int k, unsigned int e )
1615 {
1617 if ( k == 0 )
1618 p[e] = Xe_kComputer<n-1,Ring,Alloc>().get( k-1, e );
1619 else
1620 p[0] = Xe_kComputer<n-1,Ring,Alloc>().get( k-1, e );
1621 p.normalize();
1622 //std::cerr << "Xe_k(" << k << "," << e << ")=" << p << std::endl;
1623 return p;
1624 }
1625
1626 };
1627
1628 template <typename Ring, typename Alloc>
1629 class Xe_kComputer<0,Ring,Alloc>
1630 {
1631 public:
1633
1635 get( unsigned int /*k*/, unsigned int /*e*/ )
1636 {
1638 return p;
1639 }
1640 };
1641
1651 template <int n, typename Ring, typename Alloc>
1652 inline
1653 MPolynomial<n, Ring, Alloc>
1654 Xe_k( unsigned int k, unsigned int e )
1655 {
1656 return Xe_kComputer<n, Ring, Alloc>().get( k, e );
1657 }
1658
1667 template <int n, typename Ring>
1668 inline
1669 MPolynomial<n, Ring, std::allocator<Ring> >
1670 Xe_k( unsigned int k, unsigned int e )
1671 {
1672 return Xe_kComputer<n, Ring, std::allocator<Ring> >().get( k, e );
1673 }
1674
1675
1683 template <typename Ring, typename Alloc>
1684 inline
1685 MPolynomial<1, Ring, Alloc>
1686 mmonomial(unsigned int e)
1687 {
1689 p[e] = 1;
1690 return p;
1691 }
1692
1701 template <typename Ring, typename Alloc>
1702 inline
1703 MPolynomial<2, Ring, Alloc>
1704 mmonomial(unsigned int e, unsigned int f)
1705 {
1707 p[e][f] = 1;
1708 return p;
1709 }
1710
1720 template <typename Ring, typename Alloc>
1721 inline MPolynomial<3, Ring, Alloc>
1722 mmonomial(unsigned int e, unsigned int f, unsigned int g)
1723 {
1725 p[e][f][g] = 1;
1726 return p;
1727 }
1728
1739 template <typename Ring, typename Alloc>
1740 inline
1741 MPolynomial<4, Ring, Alloc>
1742 mmonomial(unsigned int e, unsigned int f, unsigned int g, unsigned int h)
1743 {
1745 p[e][f][g][h] = 1;
1746 return p;
1747 }
1748
1755 template <typename Ring>
1756 inline
1757 MPolynomial<1, Ring, std::allocator<Ring> >
1758 mmonomial(unsigned int e)
1759 {
1761 p[e] = 1;
1762 return p;
1763 }
1764
1772 template <typename Ring>
1773 inline
1774 MPolynomial<2, Ring, std::allocator<Ring> >
1775 mmonomial(unsigned int e, unsigned int f)
1776 {
1778 p[e][f] = 1;
1779 return p;
1780 }
1781
1790 template <typename Ring>
1791 inline
1792 MPolynomial<3, Ring, std::allocator<Ring> >
1793 mmonomial(unsigned int e, unsigned int f, unsigned int g)
1794 {
1796 p[e][f][g] = 1;
1797 return p;
1798 }
1799
1809 template <typename Ring>
1810 inline
1811 MPolynomial<4, Ring, std::allocator<Ring> >
1813 (unsigned int e, unsigned int f, unsigned int g, unsigned int h)
1814 {
1816 p[e][f][g][h] = 1;
1817 return p;
1818 }
1819
1820
1841 template <int n, typename Ring, class Alloc>
1842 class MPolynomialDerivativeComputer<0, n, Ring, Alloc>
1843 {
1844 public:
1847
1855 static inline
1856 void computeDerivative( const MPolyN & src, MPolyN & dest)
1857 {
1858 dest.myValue.resize(src.degree() >= 0 ? src.degree() : 0);
1859 for ( int i = 1; i <= src.degree(); ++i )
1860 dest[i - 1] = src[i] * (Ring)i;
1861 dest.normalize();
1862 }
1863 };
1864
1886 template <int N, int n, typename Ring, typename Alloc>
1888 {
1889 public:
1892
1900 static inline
1901 void computeDerivative(const MPolyN & src, MPolyN & dest)
1902 {
1903 dest.myValue.resize(src.degree() + 1);
1904 for ( int i = 0; i <= src.degree(); ++i )
1906 ::computeDerivative( src[i], dest[i] );
1907 dest.normalize();
1908 }
1909 };
1910
1914 template<typename Ring, class Alloc>
1915 class MPolynomialDerivativeComputer<0, 0, Ring, Alloc>
1916 {
1917 public:
1918 class ERROR_N_must_be_strictly_less_than_n_in_derivative_template;
1920
1921 static inline
1923 {
1924 ERROR_N_must_be_strictly_less_than_n_in_derivative_template();
1925 }
1926 };
1927
1931 template<int N, typename Ring, class Alloc>
1932 class MPolynomialDerivativeComputer<N, 0, Ring, Alloc>
1933 {
1934 public:
1935 class ERROR_N_must_be_strictly_less_than_n_in_derivative_template;
1937
1938 static inline
1940 {
1941 ERROR_N_must_be_strictly_less_than_n_in_derivative_template();
1942 }
1943 };
1944
1963 template <int N, int n, typename Ring, typename Alloc>
1964 inline
1965 MPolynomial<n, Ring, Alloc>
1967 {
1968 MPolynomial<n, Ring, Alloc> res( p.getAllocator() );
1970 return res;
1971 }
1972
1986 template<int N, int n, typename Ring>
1987 inline
1988 MPolynomial<n, Ring, std::allocator<Ring> >
1990 (const MPolynomial<n,Ring,std::allocator<Ring> > & p)
1991 {
1992 MPolynomial<n, Ring, std::allocator<Ring> > res( p.getAllocator() );
1994 ::computeDerivative( p, res );
1995 return res;
1996 }
1997
2001 template<typename Ring, typename Alloc>
2002 void
2007 {
2008 if (f.degree() < g.degree())
2009 {
2010 // Ignore the trivial case
2011 q = MPolynomial<1, Ring, Alloc>(f.getAllocator());
2012 r = f;
2013 return;
2014 }
2015 q = MPolynomial<1, Ring, Alloc>( true, f.degree() - g.degree() + 1,
2016 f.getAllocator() );
2017 r = f;
2018 for (int i = q.degree(); i >= 0; --i)
2019 {
2020 q[i] = r[i + g.degree()] / g.leading();
2021 for (int j = g.degree(); j >= 0; --j)
2022 r[i + j] -= q[i] * g[j];
2023 }
2024 r.normalize();
2025 // Note that the degree of q is already correct.
2026 }
2027
2031 template <typename Ring>
2032 void
2033 euclidDiv( const MPolynomial<1, Ring, std::allocator<Ring> > & f,
2034 const MPolynomial<1, Ring, std::allocator<Ring> > & g,
2035 MPolynomial<1, Ring, std::allocator<Ring> > & q,
2036 MPolynomial<1, Ring, std::allocator<Ring> > & r )
2037 {
2038 euclidDiv<Ring, std::allocator<Ring> >(f, g, q, r);
2039 }
2040
2045 template<typename Ring, typename Alloc>
2046 MPolynomial<1, Ring, Alloc>
2048 const MPolynomial<1, Ring, Alloc> & g )
2049 {
2050 if (f.isZero())
2051 {
2052 if (g.isZero()) return f; // both are zero
2053 else return g / g.leading(); // make g monic
2054 }
2056 d1(f / f.leading()),
2057 d2(g / g.leading()),
2058 q(f.getAllocator()),
2059 r(f.getAllocator());
2060 while (!d2.isZero())
2061 {
2062 euclidDiv(d1, d2, q, r);
2063 d1.swap(d2);
2064 d2 = r;
2065 d2 /= r.leading(); // make r monic
2066 }
2067 return d1;
2068 }
2069
2074 template<typename Ring>
2075 MPolynomial<1, Ring, std::allocator<Ring> >
2076 gcd( const MPolynomial<1, Ring, std::allocator<Ring> > & f,
2077 const MPolynomial<1, Ring, std::allocator<Ring> > & g )
2078 {
2079 return gcd<Ring, std::allocator<Ring> >(f, g);
2080 }
2081
2082} // namespace DGtal
2083
2084
2086// Includes inline functions.
2087#include "DGtal/math/MPolynomial.ih"
2088
2089// //
2091
2092#endif // !defined MPolynomial_h
2093
2094#undef MPolynomial_RECURSES
2095#endif // else defined(MPolynomial_RECURSES)
IVector(Size aSize, const Alloc &allocator=Alloc())
Definition: MPolynomial.h:836
IVector(Size aSize, const T &entry, const Alloc &allocator=Alloc())
Definition: MPolynomial.h:842
void copy_from(const std::vector< typename Alloc::pointer, A > &source)
Definition: MPolynomial.h:822
IVector(const Alloc &allocator=Alloc())
Definition: MPolynomial.h:832
void create(Size begin, Size end, typename Alloc::const_reference entry)
Definition: MPolynomial.h:803
void resize(Size aSize, const T &entry=T())
Definition: MPolynomial.h:875
std::vector< typenameAlloc::pointer, typenameAlloc::templaterebind< typenameAlloc::pointer >::other >::size_type Size
Definition: MPolynomial.h:797
std::vector< typename Alloc::pointer, typename Alloc::template rebind< typename Alloc::pointer >::other > myVec
Definition: MPolynomial.h:801
void free(Size begin, Size end)
Definition: MPolynomial.h:812
Size size() const
Definition: MPolynomial.h:742
std::vector< T, Alloc >::size_type Size
Definition: MPolynomial.h:725
IVector(const Alloc &allocator=Alloc())
Definition: MPolynomial.h:730
IVector(Size aSize, const Alloc &allocator=Alloc())
Definition: MPolynomial.h:734
const T & back() const
Definition: MPolynomial.h:762
void swap(IVector &v)
Definition: MPolynomial.h:772
Alloc get_allocator() const
Definition: MPolynomial.h:777
std::vector< T, Alloc > myVec
Definition: MPolynomial.h:727
const T & operator[](Size i) const
Definition: MPolynomial.h:752
IVector(Size aSize, const T &entry, const Alloc &allocator=Alloc())
Definition: MPolynomial.h:738
Alloc getAllocator() const
Definition: MPolynomial.h:782
void resize(Size aSize, const T &entry=T())
Definition: MPolynomial.h:747
static void computeDerivative(const MPoly0 &, MPoly0 &)
Definition: MPolynomial.h:1922
static void computeDerivative(const MPolyN &src, MPolyN &dest)
Definition: MPolynomial.h:1856
MPolynomial< n, Ring, Alloc > MPolyN
Type for polynomial with n variable in the ring Ring.
Definition: MPolynomial.h:1846
static void computeDerivative(const MPoly0 &, MPoly0 &)
Definition: MPolynomial.h:1939
MPolynomial< n, Ring, Alloc > MPolyN
Type for polynomial with n variable in the ring Ring.
Definition: MPolynomial.h:1891
static void computeDerivative(const MPolyN &src, MPolyN &dest)
Definition: MPolynomial.h:1901
const MPolynomialEvaluatorImpl< n, Ring, Owner, Alloc, X > & myOwner
Definition: MPolynomial.h:276
MPolyNM1 operator()(const MPolyN &p) const
Definition: MPolynomial.h:291
EvalFun2(const MPolynomialEvaluatorImpl< n, Ring, Owner, Alloc, X > &owner)
Definition: MPolynomial.h:280
const MPolynomialEvaluatorImpl< n, Ring, Owner, Alloc, X > & myOwner
Definition: MPolynomial.h:224
XX operator()(const MPolynomial< n, Ring, Alloc > &p) const
Definition: MPolynomial.h:240
EvalFun(const MPolynomialEvaluatorImpl< n, Ring, Owner, Alloc, X > &owner, const Fun &evalfun)
Definition: MPolynomial.h:229
const MPolynomialEvaluatorImpl< 1, Ring, Owner, Alloc, X > & myOwner
Definition: MPolynomial.h:117
EvalFun(const MPolynomialEvaluatorImpl< 1, Ring, Owner, Alloc, X > &owner)
Definition: MPolynomial.h:121
MPolynomialEvaluatorImpl(const Owner &owner, const X &evalpoint)
Definition: MPolynomial.h:108
const X & myEvalPoint
The evaluation point on this level.
Definition: MPolynomial.h:106
void evaluate(XX &res, const Fun &evalfun) const
Definition: MPolynomial.h:261
MPolynomial< n - 1, X, typename Alloc::template rebind< X >::other > MPolyNM1
Definition: MPolynomial.h:199
MPolynomialEvaluatorImpl< n - 1, Ring, MPolynomialEvaluatorImpl< n, Ring, Owner, Alloc, X >, Alloc, XX > operator()(const XX &x) const
Definition: MPolynomial.h:328
MPolynomial< n, Ring, Alloc > MPolyN
Type for the multivariate polynomial.
Definition: MPolynomial.h:190
MPolynomialEvaluatorImpl(const Owner &owner, const X &evalpoint)
Definition: MPolynomial.h:212
const X & myEvalPoint
The evaluation point.
Definition: MPolynomial.h:356
const MPoly1 & myPoly
The polynomial in question.
Definition: MPolynomial.h:355
MPolynomialEvaluator(const MPoly1 &poly, const X &evalpoint)
Definition: MPolynomial.h:359
MPolynomial< n, Ring, Alloc > MPolyN
Definition: MPolynomial.h:411
const X & myEvalPoint
the evaluation point
Definition: MPolynomial.h:416
MPolynomial< n - 1, X, typename Alloc::template rebind< X >::other > MPolyNM1
Definition: MPolynomial.h:413
MPolynomialEvaluator(const MPolyN &poly, const X &evalpoint)
Definition: MPolynomial.h:419
MPolynomialEvaluatorImpl< n - 1, Ring, MPolynomialEvaluator< n, Ring, Alloc, X >, Alloc, XX > operator()(const XX &x) const
Definition: MPolynomial.h:465
void evaluate(XX &res, const Fun &evalfun) const
Definition: MPolynomial.h:431
const MPolyN & myPoly
The polynomial in question.
Definition: MPolynomial.h:415
MPolynomial(const Alloc &allocator)
Definition: MPolynomial.h:525
MPolynomial(const Ring &v=0, const Alloc &allocator=Alloc())
Definition: MPolynomial.h:514
void selfDisplay(std::ostream &s, int) const
Definition: MPolynomial.h:683
Aim: Represents a multivariate polynomial, i.e. an element of , where K is some ring or field.
Definition: MPolynomial.h:955
MPolynomial(const Ring &v, const Alloc &allocator=Alloc())
Definition: MPolynomial.h:1042
bool operator==(const MPolynomial &q) const
Definition: MPolynomial.h:1480
Storage::Size Size
Definition: MPolynomial.h:986
static MPolyNM1 myZeroPolynomial
The zero polynomial of n-1 variables for a n-multivariate polynomial.
Definition: MPolynomial.h:991
MPolynomialEvaluator< n, Ring, Alloc, Ring > operator()(const Ring &x) const
Definition: MPolynomial.h:1159
void selfDisplay(std::ostream &s, int N=n) const
Definition: MPolynomial.h:1536
MPolynomial(const Alloc &allocator=Alloc())
Definition: MPolynomial.h:1035
friend MPolynomial operator*(const Ring &v, const MPolynomial &p)
Definition: MPolynomial.h:1249
MPolynomial & operator-=(const MPolynomial &q)
Definition: MPolynomial.h:1320
MPolynomial operator/(const Ring &v) const
Definition: MPolynomial.h:1199
MPolynomial & operator/=(const Ring &v)
Definition: MPolynomial.h:1235
MPolynomial< n - 1, Ring, Alloc > MPolyNM1
Definition: MPolynomial.h:976
MPolynomial operator-() const
Definition: MPolynomial.h:1260
MPolynomial & operator+=(const MPolynomial &q)
Definition: MPolynomial.h:1305
bool isValid() const
MPolynomial(const MPolyNM1 &pdm1, const Alloc &)
Definition: MPolynomial.h:1050
MPolyNM1 & operator[](Size i)
Definition: MPolynomial.h:1137
MPolynomial & operator*=(const MPolynomial &p)
Definition: MPolynomial.h:1212
Alloc getAllocator() const
Definition: MPolynomial.h:1097
bool operator!=(const MPolynomial &q) const
Definition: MPolynomial.h:1495
void swap(MPolynomial &p)
Definition: MPolynomial.h:1089
int degree() const
Definition: MPolynomial.h:1109
const MPolyNM1 & leading() const
Definition: MPolynomial.h:1119
bool isZero() const
Definition: MPolynomial.h:1127
MPolynomial(bool, Size s, const Alloc &)
Definition: MPolynomial.h:1004
MPolynomial(const MPolynomial< n, Ring2, Alloc2 > &p, const Alloc &allocator=Alloc())
Definition: MPolynomial.h:1060
MPolynomial & operator=(const MPolynomial< n, Ring2, Alloc2 > &p)
Definition: MPolynomial.h:1076
MPolynomial operator+(const MPolynomial &q) const
Definition: MPolynomial.h:1273
MPolynomial< 0, Ring, Alloc > get(unsigned int, unsigned int)
Definition: MPolynomial.h:1635
MPolynomial< n, Ring, Alloc > get(unsigned int k, unsigned int e)
Definition: MPolynomial.h:1614
DGtal is the top-level namespace which contains all DGtal functions and types.
void euclidDiv(const MPolynomial< 1, TRing, TAlloc > &f, const MPolynomial< 1, TRing, TAlloc > &g, MPolynomial< 1, TRing, TAlloc > &q, MPolynomial< 1, TRing, TAlloc > &r)
MPolynomial< 1, Ring, Alloc > mmonomial(unsigned int e)
Definition: MPolynomial.h:1686
MPolynomial< n, Ring, Alloc > Xe_k(unsigned int k, unsigned int e)
Definition: MPolynomial.h:1654
std::ostream & operator<<(std::ostream &out, const ClosedIntegerHalfPlane< TSpace > &object)
MPolynomial< 1, Ring, Alloc > gcd(const MPolynomial< 1, Ring, Alloc > &f, const MPolynomial< 1, Ring, Alloc > &g)
Definition: MPolynomial.h:2047
MPolynomial< n, Ring, Alloc > derivative(const MPolynomial< n, Ring, Alloc > &p)
Definition: MPolynomial.h:1966