DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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)
39 
40 #define MPolynomial_RECURSES
41 
42 #if !defined MPolynomial_h
43 
44 #define MPolynomial_h
45 
47 // Inclusions
48 #include <iostream>
49 #include <vector>
50 #include "DGtal/base/Common.h"
52 
53 namespace 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> >
62  template < int n, typename TRing,
63  typename TAlloc = std::allocator<TRing>,
64  typename TX = TRing >
66 
67  template < int n, typename TRing, typename TOwner,
68  typename TAlloc, typename TX >
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>
99  friend class MPolynomialEvaluator;
100 
101  template <int nn, class TT, class HLHL, class AA, class SS>
103 
104 private:
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 
145 public:
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>
202  friend class MPolynomialEvaluator;
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 >
222  class EvalFun
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 
274  class EvalFun2
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 
318  /*
319  Continues evaluation with the next indeterminant. Functor
320  returning a "child" evaluator implementation.
321  */
322  template < typename XX >
323  inline
325  < n - 1, Ring,
327  Alloc, XX > operator() ( const XX & x ) const
328  {
331  Alloc, XX >( *this, x );
332  }
333  };
334 
343  template < typename TRing, typename TAlloc, typename TX >
344  class MPolynomialEvaluator< 1, TRing, TAlloc, TX>
345  {
346  friend class MPolynomial< 1, TRing, TAlloc >;
347  public:
348  typedef TRing Ring;
349  typedef TAlloc Alloc;
350  typedef TX X;
352 
353  private:
354  const MPoly1 & myPoly;
355  const X & myEvalPoint;
356 
357  inline
358  MPolynomialEvaluator( const MPoly1 & poly, const X & evalpoint)
359  : myPoly( poly ), myEvalPoint( evalpoint )
360  {}
361 
362  public:
366  inline
367  operator X() const
368  {
369  X res = (X) 0;
370  X xx = (X) 1;
371  for ( int i = 0; i < (int) myPoly.myValue.size(); ++i )
372  {
373  res += ( (X) (Ring) myPoly.myValue[i] ) * xx;
374  xx = xx * myEvalPoint;
375  }
376  return res;
377  }
378 
382  inline
383  X operator() () const
384  {
385  return (X) (*this);
386  }
387  };
388 
389 
398  template < int n, typename TRing, typename TAlloc, typename TX >
400  {
401  friend class MPolynomial< n, TRing, TAlloc>;
402 
403  template<int nn, class TT, class HLHL, class AA, class SS>
405 
406  public:
407  typedef TRing Ring;
408  typedef TAlloc Alloc;
409  typedef TX X;
411  typedef MPolynomial< n - 1, X,
412  typename Alloc::template rebind<X>::other > MPolyNM1;
413  private:
414  const MPolyN & myPoly;
415  const X & myEvalPoint;
416 
417  inline
418  MPolynomialEvaluator( const MPolyN & poly, const X & evalpoint)
419  : myPoly( poly ), myEvalPoint( evalpoint )
420  {}
421 
428  template < typename XX, typename Fun >
429  inline
430  void evaluate( XX & res, const Fun & evalfun ) const
431  {
432  X xx = (X) 1;
433  for ( int i = 0; i < (int) myPoly.myValue.size(); ++i )
434  {
435  res += evalfun( myPoly.myValue[i] ) * xx;
436  xx = xx * myEvalPoint;
437  }
438  }
439 
440 public:
444  inline
445  operator MPolyNM1() const
446  {
447  MPolyNM1 res( myPoly.getAllocator() );
448  X xx = (X) 1;
449  for ( int i = 0; i < (int) myPoly.myValue.size(); ++i )
450  {
451  res += MPolyNM1( myPoly.myValue[i] ) * xx;
452  xx = xx * myEvalPoint;
453  }
454  return res;
455  }
456 
460  template <typename XX>
461  inline
464  operator() (const XX & x) const
465  {
468  ( *this, x );
469  }
470  };
471 
493  template < typename TRing, typename TAlloc >
494  class MPolynomial< 0, TRing, TAlloc >
495  {
496  public:
497  typedef TRing Ring;
498  typedef TAlloc Alloc;
499 
500  private:
503 
504  public:
512  inline
513  MPolynomial( const Ring & v = 0, const Alloc & allocator = Alloc() )
514  : myAllocator(allocator), myValue(v)
515  {}
516 
523  inline
524  MPolynomial( const Alloc & allocator )
525  : myAllocator(allocator), myValue( Ring() )
526  {}
527 
531  inline bool isZero() const
532  {
533  return myValue == 0;
534  }
535 
540  inline operator const Ring & () const
541  {
542  return myValue;
543  }
544 
550  inline MPolynomial & operator = (const Ring & v)
551  {
552  myValue = v;
553  return *this;
554  }
555 
560  inline Ring operator() () const
561  {
562  return myValue;
563  }
564 
570  inline MPolynomial operator * (const Ring & v) const
571  {
572  return MPolynomial(myValue * v);
573  }
574 
580  inline MPolynomial operator / (const Ring & v) const
581  {
582  return MPolynomial(myValue / v);
583  }
584 
590  inline MPolynomial operator + (const Ring & v) const
591  {
592  return MPolynomial(myValue + v);
593  }
594 
600  inline MPolynomial operator - (const Ring & v) const
601  {
602  return MPolynomial(myValue - v);
603  }
604 
609  inline MPolynomial operator - () const
610  {
611  return MPolynomial(-myValue);
612  }
613 
619  inline MPolynomial & operator *= (const Ring & v)
620  {
621  myValue *= v;
622  return *this;
623  }
624 
630  inline MPolynomial & operator /= (const Ring & v)
631  {
632  myValue /= v;
633  return *this;
634  }
635 
641  inline MPolynomial & operator += (const Ring & v)
642  {
643  myValue += v;
644  return *this;
645  }
646 
652  inline MPolynomial & operator -= (const Ring & v)
653  {
654  myValue -= v;
655  return *this;
656  }
657 
663  inline bool operator == (const Ring & v) const
664  {
665  return myValue == v;
666  }
667 
673  inline bool operator != (const Ring & v) const
674  {
675  return myValue != v;
676  }
677 
683  void selfDisplay( std::ostream & s, int /*N = 0*/ ) const
684  {
685  s << myValue;
686  }
687 
692  inline void swap( MPolynomial & p )
693  {
695  }
696 
701  {
702  return myAllocator;
703  }
704  };
705 
706 
719  template < typename T, typename TAlloc = std::allocator<T>,
720  bool usePointers = false>
721  class IVector
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 
757  T & operator[] ( Size i )
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  typedef unsigned long int Size;
799 
800  private:
802  std::vector<typename Alloc::pointer, typename Alloc::template rebind<typename Alloc::pointer>::other> myVec;
803 
804  void create( Size begin, Size end, typename Alloc::const_reference entry)
805  {
806  for (Size i = begin; i < end; ++i)
807  {
808  myVec[i] = myAllocator.allocate(sizeof(T));
809  myAllocator.construct(myVec[i], entry);
810  }
811  }
812 
813  void free(Size begin, Size end)
814  {
815  for (Size i = begin; i < end; ++i)
816  {
817  myAllocator.destroy(myVec[i]);
818  myAllocator.deallocate(myVec[i], sizeof(T));
819  }
820  }
821 
822  template<class A>
823  void copy_from(const std::vector<typename Alloc::pointer, A> & source)
824  {
825  for (Size i = 0; i < myVec.size(); ++i)
826  {
827  myVec[i] = myAllocator.allocate(sizeof(T));
828  myAllocator.construct(myVec[i], *source[i]);
829  }
830  }
831 
832  public:
833  IVector(const Alloc & allocator = Alloc())
834  : myAllocator(allocator), myVec(allocator)
835  {}
836 
837  IVector(Size aSize, const Alloc & allocator = Alloc())
838  : myAllocator(allocator), myVec(aSize, 0, allocator)
839  {
840  create(0, aSize, T());
841  }
842 
843  IVector(Size aSize, const T & entry, const Alloc & allocator = Alloc())
844  : myAllocator(allocator), myVec(aSize, 0, allocator)
845  {
846  create(0, aSize, entry);
847  }
848 
849  IVector(const IVector & v)
850  : myVec(v.size())
851  {
852  copy_from(v.myVec);
853  }
854 
856  {
857  free(0, (Size)myVec.size());
858  }
859 
860  IVector & operator = (const IVector & v)
861  {
862  if (&v != this)
863  {
864  free(0, (Size)myVec.size());
865  myVec.resize(v.size());
866  copy_from(v.myVec);
867  }
868  return *this;
869  }
870 
871  Size size() const
872  {
873  return (Size)myVec.size();
874  }
875 
876  void resize(Size aSize, const T & entry = T())
877  {
878  Size oldsize = (Size)myVec.size();
879  if (oldsize > aSize)
880  free(aSize, oldsize);
881  myVec.resize(aSize);
882  if (oldsize < aSize)
883  create(oldsize, aSize, entry);
884  }
885 
886  const T & operator[] (Size i) const
887  {
888  return *myVec[i];
889  }
890 
892  {
893  return *myVec[i];
894  }
895 
896  const T & back() const
897  {
898  return *myVec.back();
899  }
900 
901  T & back()
902  {
903  return *myVec.back();
904  }
905 
906  void swap(IVector & v)
907  {
908  myVec.swap(v.myVec);
909  }
910 
912  {
913  return myVec.get_allocator();
914  }
915 
917  {
918  return myVec.get_allocator();
919  }
920  };
921 
922 
924  // template class MPolynomial
954  template < int n, typename TRing, class TAlloc >
956  {
957  // ----------------------- friends ---------------------------------------
958 
959  template<int NN, int nn, typename TT, typename AA>
961 
962  friend void euclidDiv<TRing, TAlloc>
967 
968  template<int nn, typename TT, typename AA, typename SS>
969  friend class MPolynomialEvaluator;
970 
971  template<int nn, typename TT, typename HLHL, typename AA, typename SS>
973 
974  public:
975  typedef TRing Ring;
976  typedef TAlloc Alloc;
977  typedef MPolynomial< n - 1, Ring, Alloc > MPolyNM1;
984  typedef IVector< MPolyNM1,
985  typename Alloc::template rebind<MPolyNM1 >::other, (n>1) >
987  typedef typename Storage::Size Size;
988 
989  // ----------------------- Datas ----------------------------
990 private:
1000 
1004  inline
1005  MPolynomial( bool, Size s, const Alloc & /*allocator*/)
1006  : myValue(s)
1007  {}
1008 
1009 public:
1016  inline void normalize()
1017  {
1018  Size dp1 = myValue.size();
1019  while ( dp1 )
1020  {
1021  if (myValue[dp1 - 1].isZero())
1022  --dp1;
1023  else
1024  break;
1025  }
1026  if (dp1 < myValue.size())
1027  myValue.resize(dp1);
1028  }
1029 
1030  // ----------------------- Standard services ----------------------------
1031  public:
1032 
1036  inline MPolynomial( const Alloc & allocator = Alloc() )
1037  : myValue( allocator )
1038  {}
1039 
1043  inline MPolynomial( const Ring & v, const Alloc & allocator = Alloc() )
1044  : myValue( 1, MPolyNM1( v ), allocator )
1045  {}
1046 
1051  inline MPolynomial( const MPolyNM1 & pdm1,
1052  const Alloc & allocator = Alloc() )
1053  : myValue( 1, pdm1 )
1054  {}
1055 
1060  template < typename Ring2, typename Alloc2 >
1062  const Alloc & allocator = Alloc() )
1063  : myValue( p.degree() + 1, MPolyNM1(), allocator )
1064  {
1065  for ( Size i = 0; i < myValue.size(); ++i )
1066  myValue[i] = p[i];
1067  normalize();
1068  }
1069 
1074  template < typename Ring2, typename Alloc2 >
1075  inline
1076  MPolynomial & operator=
1078  {
1079  myValue.resize(p.degree() + 1);
1080  for ( Size i = 0; i < myValue.size(); ++i )
1081  myValue[i] = p[i];
1082  normalize();
1083  return *this;
1084  }
1085 
1090  inline void swap( MPolynomial & p )
1091  {
1092  myValue.swap(p.myValue);
1093  }
1094 
1099  {
1100  return myValue.getAllocator();
1101  }
1102 
1103  // ----------------------- MPolynomial services ----------------------------
1104  public:
1105 
1110  inline int degree() const
1111  {
1112  return (int)(myValue.size() - 1);
1113  }
1114 
1120  inline const MPolyNM1 & leading() const
1121  {
1122  return myValue.size() ? myValue.back() : myZeroPolynomial;
1123  }
1124 
1128  inline bool isZero() const
1129  {
1130  return myValue.size() == 0;
1131  }
1132 
1138  inline MPolyNM1 & operator[] ( Size i )
1139  {
1140  if (i >= myValue.size())
1141  myValue.resize(i + 1);
1142  return myValue[i];
1143  }
1144 
1148  inline const MPolyNM1 & operator[] (Size i) const
1149  {
1150  return i < myValue.size() ? myValue[i] : myZeroPolynomial;
1151  }
1152 
1159  inline
1161  {
1162  return MPolynomialEvaluator<n, Ring, Alloc, Ring>( *this, x );
1163  }
1164 
1172  template <typename Ring2>
1173  inline
1175  {
1177  }
1178 
1179  // ----------------------- Operators --------------------------------------
1180  public:
1181 
1187  inline MPolynomial operator * (const Ring & v) const
1188  {
1189  MPolynomial r(*this);
1190  for ( Size i = 0; i < myValue.size(); ++i )
1191  r[i] *= v;
1192  return r;
1193  }
1194 
1200  inline MPolynomial operator / (const Ring & v) const
1201  {
1202  MPolynomial r(*this);
1203  for ( Size i = 0; i < myValue.size(); ++i )
1204  r[i] /= v;
1205  return r;
1206  }
1207 
1214  {
1215  return *this = *this * p;
1216  }
1217 
1223  inline MPolynomial & operator *= (const Ring & v)
1224  {
1225  MPolynomial r( *this );
1226  for ( Size i = 0; i < myValue.size(); ++i )
1227  myValue[i] *= v;
1228  return *this;
1229  }
1230 
1236  inline MPolynomial & operator /= (const Ring & v)
1237  {
1238  for ( Size i = 0; i < myValue.size(); ++i )
1239  myValue[i] /= v;
1240  return *this;
1241  }
1242 
1249  friend
1250  inline MPolynomial operator * (const Ring & v, const MPolynomial & p)
1251  {
1252  MPolynomial r(p);
1253  for ( Size i = 0; i < p.myValue.size(); ++i )
1254  r[i] *= v;
1255  return r;
1256  }
1257 
1261  inline MPolynomial operator - () const
1262  {
1263  MPolynomial r( true, myValue.size(), getAllocator() );
1264  for ( Size i = 0; i < myValue.size(); ++i )
1265  r[i] = -myValue[i];
1266  return r;
1267  }
1268 
1274  inline MPolynomial operator + (const MPolynomial & q) const
1275  {
1276  MPolynomial r(*this);
1277  if (r.myValue.size() < q.myValue.size())
1278  r.myValue.resize(q.myValue.size());
1279  for ( Size i = 0; i < q.myValue.size(); ++i )
1280  r[i] += q[i];
1281  r.normalize();
1282  return r;
1283  }
1284 
1290  inline MPolynomial operator - (const MPolynomial & q) const
1291  {
1292  MPolynomial r(*this);
1293  if (r.myValue.size() < q.myValue.size())
1294  r.myValue.resize(q.myValue.size());
1295  for ( Size i = 0; i < q.myValue.size(); ++i )
1296  r[i] -= q[i];
1297  r.normalize();
1298  return r;
1299  }
1300 
1307  {
1308  if (myValue.size() < q.myValue.size())
1309  myValue.resize(q.myValue.size());
1310  for ( Size i = 0; i < q.myValue.size(); ++i )
1311  myValue[i] += q[i];
1312  normalize();
1313  return *this;
1314  }
1315 
1322  {
1323  if (myValue.size() < q.myValue.size())
1324  myValue.resize(q.myValue.size());
1325  for ( Size i = 0; i < q.myValue.size(); ++i )
1326  myValue[i] -= q[i];
1327  normalize();
1328  return *this;
1329  }
1330 
1337  inline MPolynomial operator + (const MPolyNM1 & q) const
1338  {
1339  MPolynomial r(*this);
1340  if (r.myValue.size() < 1)
1341  r.myValue.resize(1);
1342  r[0] += q;
1343  r.normalize();
1344  return r;
1345  }
1346 
1353  inline MPolynomial operator - (const MPolyNM1 & q) const
1354  {
1355  MPolynomial r(*this);
1356  if (r.myValue.size() < 1)
1357  r.myValue.resize(1);
1358  r[0] -= q;
1359  r.normalize();
1360  return r;
1361  }
1362 
1368  inline MPolynomial operator + (const Ring & v) const
1369  {
1370  MPolynomial r(*this);
1371  if (r.myValue.size() < 1)
1372  r.myValue.resize(1);
1373  r[0] += v;
1374  r.normalize();
1375  return r;
1376  }
1377 
1383  inline MPolynomial operator - (const Ring & v) const
1384  {
1385  MPolynomial r(*this);
1386  if (r.myValue.size() < 1)
1387  r.myValue.resize(1);
1388  r[0] -= v;
1389  r.normalize();
1390  return r;
1391  }
1392 
1399  inline MPolynomial & operator += (const MPolyNM1 & q)
1400  {
1401  if (myValue.size() < 1)
1402  myValue.resize(1);
1403  myValue[0] += q;
1404  normalize();
1405  return *this;
1406  }
1407 
1414  inline MPolynomial & operator -= (const MPolyNM1 & q)
1415  {
1416  if (myValue.size() < 1)
1417  myValue.resize(1);
1418  myValue[0] -= q;
1419  normalize();
1420  return *this;
1421  }
1422 
1428  inline MPolynomial & operator += (const Ring & v)
1429  {
1430  if (myValue.size() < 1)
1431  myValue.resize(1);
1432  myValue[0] += v;
1433  normalize();
1434  return *this;
1435  }
1436 
1442  inline MPolynomial & operator -= (const Ring & v)
1443  {
1444  if (myValue.size() < 1)
1445  myValue.resize(1);
1446  myValue[0] -= v;
1447  normalize();
1448  return *this;
1449  }
1450 
1458  inline MPolynomial operator * (const MPolynomial & p) const
1459  {
1460  int d = p.degree() + degree();
1461  if (d < -1)
1462  d = -1;
1463  MPolynomial r( true, d + 1, getAllocator() );
1464  if (!isZero() && !p.isZero())
1465  for ( Size i = 0; i < r.myValue.size(); ++i )
1466  for ( Size j = 0; j < myValue.size(); ++j )
1467  if (i < j + p.myValue.size())
1468  r[i] += myValue[j] * p[i - j];
1469  r.normalize();
1470  return r;
1471  }
1472 
1473  // ----------------------- Comparison operators ---------------------------
1474  public:
1475 
1481  inline bool operator == (const MPolynomial & q) const
1482  {
1483  if (myValue.size() != q.myValue.size())
1484  return false;
1485  for (Size i = 0; i < myValue.size(); ++i)
1486  if (myValue[i] != q[i])
1487  return false;
1488  return true;
1489  }
1490 
1496  inline bool operator != (const MPolynomial & q) const
1497  {
1498  return !(*this == q);
1499  }
1500 
1506  inline bool operator == (const Ring & v) const
1507  {
1508  if ((v == 0) && (myValue.size() == 0))
1509  return true;
1510  if (myValue.size() != 1)
1511  return false;
1512  return myValue[0] == v;
1513  }
1514 
1520  inline bool operator != (const Ring & v) const
1521  {
1522  return !(*this == v);
1523  }
1524 
1525 
1526 
1527  // ----------------------- Interface --------------------------------------
1528  public:
1529 
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 
1605  template <int n, typename Ring, typename Alloc>
1607  {
1608  public:
1610 
1612  get( unsigned int k, unsigned int e )
1613  {
1615  if ( k == 0 )
1616  p[e] = Xe_kComputer<n-1,Ring,Alloc>().get( k-1, e );
1617  else
1618  p[0] = Xe_kComputer<n-1,Ring,Alloc>().get( k-1, e );
1619  p.normalize();
1620  //std::cerr << "Xe_k(" << k << "," << e << ")=" << p << std::endl;
1621  return p;
1622  }
1623 
1624  };
1625 
1626  template <typename Ring, typename Alloc>
1627  class Xe_kComputer<0,Ring,Alloc>
1628  {
1629  public:
1631 
1633  get( unsigned int /*k*/, unsigned int /*e*/ )
1634  {
1636  return p;
1637  }
1638  };
1639 
1649  template <int n, typename Ring, typename Alloc>
1650  inline
1652  Xe_k( unsigned int k, unsigned int e )
1653  {
1654  return Xe_kComputer<n, Ring, Alloc>().get( k, e );
1655  }
1656 
1665  template <int n, typename Ring>
1666  inline
1668  Xe_k( unsigned int k, unsigned int e )
1669  {
1670  return Xe_kComputer<n, Ring, std::allocator<Ring> >().get( k, e );
1671  }
1672 
1673 
1681  template <typename Ring, typename Alloc>
1682  inline
1684  mmonomial(unsigned int e)
1685  {
1687  p[e] = 1;
1688  return p;
1689  }
1690 
1699  template <typename Ring, typename Alloc>
1700  inline
1702  mmonomial(unsigned int e, unsigned int f)
1703  {
1705  p[e][f] = 1;
1706  return p;
1707  }
1708 
1718  template <typename Ring, typename Alloc>
1720  mmonomial(unsigned int e, unsigned int f, unsigned int g)
1721  {
1723  p[e][f][g] = 1;
1724  return p;
1725  }
1726 
1737  template <typename Ring, typename Alloc>
1738  inline
1740  mmonomial(unsigned int e, unsigned int f, unsigned int g, unsigned int h)
1741  {
1743  p[e][f][g][h] = 1;
1744  return p;
1745  }
1746 
1753  template <typename Ring>
1754  inline
1756  mmonomial(unsigned int e)
1757  {
1759  p[e] = 1;
1760  return p;
1761  }
1762 
1770  template <typename Ring>
1771  inline
1773  mmonomial(unsigned int e, unsigned int f)
1774  {
1776  p[e][f] = 1;
1777  return p;
1778  }
1779 
1788  template <typename Ring>
1789  inline
1791  mmonomial(unsigned int e, unsigned int f, unsigned int g)
1792  {
1794  p[e][f][g] = 1;
1795  return p;
1796  }
1797 
1807  template <typename Ring>
1808  inline
1810  mmonomial
1811  (unsigned int e, unsigned int f, unsigned int g, unsigned int h)
1812  {
1814  p[e][f][g][h] = 1;
1815  return p;
1816  }
1817 
1818 
1839  template <int n, typename Ring, class Alloc>
1840  class MPolynomialDerivativeComputer<0, n, Ring, Alloc>
1841  {
1842  public:
1845 
1853  static inline
1854  void computeDerivative( const MPolyN & src, MPolyN & dest)
1855  {
1856  dest.myValue.resize(src.degree() >= 0 ? src.degree() : 0);
1857  for ( int i = 1; i <= src.degree(); ++i )
1858  dest[i - 1] = src[i] * (Ring)i;
1859  dest.normalize();
1860  }
1861  };
1862 
1884  template <int N, int n, typename Ring, typename Alloc>
1886  {
1887  public:
1890 
1898  static inline
1899  void computeDerivative(const MPolyN & src, MPolyN & dest)
1900  {
1901  dest.myValue.resize(src.degree() + 1);
1902  for ( int i = 0; i <= src.degree(); ++i )
1904  ::computeDerivative( src[i], dest[i] );
1905  dest.normalize();
1906  }
1907  };
1908 
1912  template<typename Ring, class Alloc>
1913  class MPolynomialDerivativeComputer<0, 0, Ring, Alloc>
1914  {
1915  public:
1916  class ERROR_N_must_be_strictly_less_than_n_in_derivative_template;
1918 
1919  static inline
1921  {
1922  ERROR_N_must_be_strictly_less_than_n_in_derivative_template();
1923  }
1924  };
1925 
1929  template<int N, typename Ring, class Alloc>
1930  class MPolynomialDerivativeComputer<N, 0, Ring, Alloc>
1931  {
1932  public:
1933  class ERROR_N_must_be_strictly_less_than_n_in_derivative_template;
1935 
1936  static inline
1938  {
1939  ERROR_N_must_be_strictly_less_than_n_in_derivative_template();
1940  }
1941  };
1942 
1961  template <int N, int n, typename Ring, typename Alloc>
1962  inline
1965  {
1968  return res;
1969  }
1970 
1984  template<int N, int n, typename Ring>
1985  inline
1987  derivative
1988  (const MPolynomial<n,Ring,std::allocator<Ring> > & p)
1989  {
1990  MPolynomial<n, Ring, std::allocator<Ring> > res( p.getAllocator() );
1992  ::computeDerivative( p, res );
1993  return res;
1994  }
1995 
1999  template<typename Ring, typename Alloc>
2000  void
2002  const MPolynomial<1, Ring, Alloc> & g,
2005  {
2006  if (f.degree() < g.degree())
2007  {
2008  // Ignore the trivial case
2010  r = f;
2011  return;
2012  }
2013  q = MPolynomial<1, Ring, Alloc>( true, f.degree() - g.degree() + 1,
2014  f.getAllocator() );
2015  r = f;
2016  for (int i = q.degree(); i >= 0; --i)
2017  {
2018  q[i] = r[i + g.degree()] / g.leading();
2019  for (int j = g.degree(); j >= 0; --j)
2020  r[i + j] -= q[i] * g[j];
2021  }
2022  r.normalize();
2023  // Note that the degree of q is already correct.
2024  }
2025 
2029  template <typename Ring>
2030  void
2031  euclidDiv( const MPolynomial<1, Ring, std::allocator<Ring> > & f,
2032  const MPolynomial<1, Ring, std::allocator<Ring> > & g,
2033  MPolynomial<1, Ring, std::allocator<Ring> > & q,
2034  MPolynomial<1, Ring, std::allocator<Ring> > & r )
2035  {
2036  euclidDiv<Ring, std::allocator<Ring> >(f, g, q, r);
2037  }
2038 
2043  template<typename Ring, typename Alloc>
2046  const MPolynomial<1, Ring, Alloc> & g )
2047  {
2048  if (f.isZero())
2049  {
2050  if (g.isZero()) return f; // both are zero
2051  else return g / g.leading(); // make g monic
2052  }
2054  d1(f / f.leading()),
2055  d2(g / g.leading()),
2056  q(f.getAllocator()),
2057  r(f.getAllocator());
2058  while (!d2.isZero())
2059  {
2060  euclidDiv(d1, d2, q, r);
2061  d1.swap(d2);
2062  d2 = r;
2063  d2 /= r.leading(); // make r monic
2064  }
2065  return d1;
2066  }
2067 
2072  template<typename Ring>
2074  gcd( const MPolynomial<1, Ring, std::allocator<Ring> > & f,
2075  const MPolynomial<1, Ring, std::allocator<Ring> > & g )
2076  {
2077  return gcd<Ring, std::allocator<Ring> >(f, g);
2078  }
2079 
2080 } // namespace DGtal
2081 
2082 
2084 // Includes inline functions.
2085 #include "DGtal/math/MPolynomial.ih"
2086 
2087 // //
2089 
2090 #endif // !defined MPolynomial_h
2091 
2092 #undef MPolynomial_RECURSES
2093 #endif // else defined(MPolynomial_RECURSES)