algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/polynomial.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : polynomial.hpp
00004 * DESCRIPTION: Dense univariate polynomials
00005 * COPYRIGHT  : (C) 2004  Joris van der Hoeven and Gregoire Lecerf
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #ifndef __MMX_POLYNOMIAL_HPP
00014 #define __MMX_POLYNOMIAL_HPP
00015 #include <algebramix/polynomial_naive.hpp>
00016 
00017 namespace mmx {
00018 #define Polynomial_variant(C) polynomial_variant_helper<C>::PV
00019 #define Polynomial_multiply(C) polynomial_variant_helper<C>::PV
00020 #define TMPL_DEF \
00021   template<typename C, typename V=typename Polynomial_variant(C) >
00022 #define TMPL template<typename C, typename V>
00023 #define TMPLK template<typename C, typename V, typename K>
00024 #define Format format<C>
00025 #define Vector vector<C>
00026 #define Polynomial polynomial<C,V>
00027 #define Polynomial_rep polynomial_rep<C,V>
00028 #define Abs_polynomial polynomial<Abs_type(C),V>
00029 #define Real_polynomial polynomial<Real_type(C),V>
00030 #define Center_polynomial polynomial<Center_type(C),V>
00031 #define Radius_polynomial polynomial<Radius_type(C),V>
00032 TMPL class polynomial_rep;
00033 TMPL class polynomial;
00034 TMPL inline int deg (const Polynomial& P);
00035 TMPL inline int degree (const Polynomial& P);
00036 TMPL inline nat N (const Polynomial& P);
00037 TMPL inline C* seg (Polynomial& P);
00038 TMPL inline const C* seg (const Polynomial& P);
00039 
00040 /******************************************************************************
00041 * Dense polynomials
00042 ******************************************************************************/
00043 
00044 TMPL_DEF
00045 class polynomial_rep REP_STRUCT_1(C) {
00046 public:
00047   typedef implementation<vector_linear,V> Vec;
00048   typedef implementation<polynomial_linear,V> Pol;
00049 private:
00050   C*  a;
00051   nat n;
00052   nat l;  // allocated number of coefficients
00053 public:
00054   inline void normalize () {
00055     while ((n != 0) && is_exact_zero (a[n-1])) n--; }
00056   inline polynomial_rep (C* a2, nat n2, const Format& fm):
00057     Format (fm), a(a2), n(n2), l(n2) { normalize (); }
00058   inline polynomial_rep (C* a2, nat n2, nat l2, const Format& fm):
00059     Format (fm), a(a2), n(n2), l(l2) { normalize (); }
00060   inline ~polynomial_rep () {
00061     mmx_delete<C> (a, l); }
00062   void extend (nat n2) {
00063     nat l2= aligned_size<C,V> (n2);
00064     C* b= mmx_formatted_new<C> (l2, this->tfm ());
00065     Pol::copy (b, a, n);
00066     Pol::clear (b+n, l2-n);
00067     mmx_delete<C> (a, l);
00068     a= b;
00069     n= n2;
00070     l= l2;
00071   }
00072   void resize (nat n2) {
00073     if (n < n2) extend (n2);
00074     n= n2;
00075   }
00076 
00077   friend class Polynomial;
00078   friend int deg LESSGTR (const Polynomial& P);
00079   friend int degree LESSGTR (const Polynomial& P);
00080   friend nat N LESSGTR (const Polynomial& P);
00081   friend C* seg LESSGTR (Polynomial& P);
00082   friend const C* seg LESSGTR (const Polynomial& P);
00083 };
00084   
00085 TMPL_DEF
00086 class polynomial {
00087 INDIRECT_PROTO_2 (polynomial, polynomial_rep, C, V)
00088 public:
00089   typedef implementation<vector_linear,V> Vec;
00090   typedef implementation<polynomial_linear,V> Pol;
00091   typedef typename Pol::template global_variables<Polynomial> S;
00092 public:
00093   static inline generic get_variable_name () {
00094     return S::get_variable_name (); }
00095   static inline void set_variable_name (const generic& x) {
00096     S::set_variable_name (x); }
00097 
00098   //#ifdef EMPTY_FORMATS
00099   inline polynomial () {
00100     nat l= aligned_size<C,V> (0);
00101     rep= new Polynomial_rep (mmx_new<C> (l), 0, l, Format (no_format ()));
00102   }
00103   //#endif
00104   inline polynomial (const Format& fm) {
00105     nat l= aligned_size<C,V> (0);
00106     rep= new Polynomial_rep (mmx_new<C> (l), 0, l, fm);
00107   }
00108   template<typename T> inline polynomial (const T& x) {
00109     nat l= aligned_size<C,V> (1);
00110     C c= as<C> (x);
00111     C* a= mmx_formatted_new<C> (l, get_format (c));
00112     a[0]= c;
00113     rep= new Polynomial_rep (a, 1, l, get_format (c));
00114     rep->normalize ();
00115   }
00116   //#ifdef EMPTY_FORMATS
00117   template<typename T> inline
00118   polynomial (const polynomial<T,V>& P) {
00119     Format fm= as<Format > (CF(P));
00120     nat l= aligned_size<C,V> (N(P));
00121     C* a= mmx_formatted_new<C> (l, fm);
00122     Pol::cast (a, seg (P), N(P));
00123     rep= new Polynomial_rep (a, N(P), l, fm);
00124     rep->normalize ();
00125   }
00126   //#endif
00127   template<typename T> inline
00128   polynomial (const polynomial<T,V>& P, const Format& fm) {
00129     nat l= aligned_size<C,V> (N(P));
00130     C* a= mmx_formatted_new<C> (l, fm);
00131     Pol::cast (a, seg (P), N(P));
00132     rep= new Polynomial_rep (a, N(P), l, fm);
00133     rep->normalize ();
00134   }
00135   polynomial (const C& x, nat n) {
00136     nat l= aligned_size<C,V> (n+1);
00137     C* a= mmx_formatted_new<C> (l, get_format (x));
00138     Pol::clear (a, n);
00139     a[n]= x;
00140     rep= new Polynomial_rep (a, n+1, l, get_format (x));
00141     rep->normalize ();
00142   }
00143   inline polynomial (C* a, nat n, const Format& fm) {
00144     rep= new Polynomial_rep (a, n, fm);
00145   }
00146   inline polynomial (C* a, nat n, nat l, const Format& fm) {
00147     rep= new Polynomial_rep (a, n, l, fm);
00148   }
00149   polynomial (const vector<C>& v) {
00150     nat l= aligned_size<C,V> (N(v));
00151     C* a= mmx_formatted_new<C> (l, CF(v));
00152     Pol::copy (a, seg (v), N(v));
00153     rep= new Polynomial_rep (a, N(v), l, CF(v));
00154     rep->normalize ();
00155   }
00156   polynomial (const iterator<C>& it) {
00157     nat i, l=0;
00158     nat s= aligned_size<C,V> (0);
00159     C* a= mmx_formatted_new<C> (s, CF(it));
00160     rep= new Polynomial_rep (a, 0, s, CF(it));
00161     for (i=0; busy (it); i++, ++it) {
00162       if (i >= l) {
00163         l= max ((nat) 1, l<<1);
00164         rep->extend (l);
00165       }
00166       rep->a[i]= *it;
00167     }
00168     rep->normalize ();
00169   }
00170   inline friend Polynomial copy (const Polynomial& P) {
00171     nat n= N(P), l= aligned_size<C,V> (n);
00172     C* r= mmx_formatted_new<C> (l, CF(P));
00173     Pol::copy (r, seg (P), n);
00174     return Polynomial (r, n, l, CF(P));
00175   }
00176   inline C operator[] (nat i) const {
00177     return i<rep->n? rep->a[i]: promote (0, CF(*this)); }
00178   Polynomial& operator += (const Polynomial& P);
00179   Polynomial& operator -= (const Polynomial& P);
00180   Polynomial& operator *= (const C& c);
00181   Polynomial& operator /= (const C& c);
00182 };
00183 INDIRECT_IMPL_2 (polynomial, polynomial_rep, typename C, C, typename V, V)
00184 DEFINE_UNARY_FORMAT_2 (polynomial)
00185 
00186 TMPL inline nat N (const Polynomial& P) { return P->n; }
00187 TMPL inline int deg (const Polynomial& P) { return ((int) P->n) - 1; }
00188 TMPL inline int degree (const Polynomial& P) { return ((int) P->n) - 1; }
00189 TMPL inline C* seg (Polynomial& P) { return P->a; }
00190 TMPL inline const C* seg (const Polynomial& P) { return P->a; }
00191 TMPL inline Format CF (const Polynomial& P) { return P->tfm (); }
00192 
00193 TMPL inline vector<C>
00194 coefficients (const Polynomial& P) {
00195   vector<C> v (get_sample (CF(P)), N(P));
00196   for (nat i= 0; i < N(P); i++) v[i]= P[i];
00197   return v;
00198 }
00199 
00200 TMPL inline vector<C>
00201 coefficients (const Polynomial& P, nat b, nat e) {
00202   if (b >= e) return vector<C> ();
00203   vector<C> v (get_sample (CF(P)), e - b);
00204   for (nat i= 0; i < e - b; i++) v[i]= P[b+i];
00205   return v;
00206 }
00207 
00208 STYPE_TO_TYPE(TMPL,scalar_type,Polynomial,C);
00209 STYPE_TO_TYPE(TMPL,monomial_type,Polynomial,nat);
00210 UNARY_RETURN_TYPE(TMPL,Re_op,Polynomial,Real_polynomial);
00211 UNARY_RETURN_TYPE(TMPL,abs_op,Polynomial,Abs_polynomial);
00212 UNARY_RETURN_TYPE(TMPL,center_op,Polynomial,Center_polynomial);
00213 UNARY_RETURN_TYPE(TMPL,radius_op,Polynomial,Radius_polynomial);
00214 
00215 TMPL
00216 struct fast_helper<Polynomial > {
00217   typedef Fast_type(C) FC;
00218   typedef polynomial<FC> fast_type;
00219   typedef typename Polynomial_variant(FC) FV;
00220   static inline fast_type dd (const Polynomial& p) {
00221     format<FC> fm= fast (CF(p));
00222     nat l= aligned_size<FC,FV> (N(p));
00223     FC* r= mmx_formatted_new<FC> (l, fm);
00224     for (nat i=0; i<N(p); i++) r[i]= fast (p[i]);
00225     return fast_type (r, N(p), l, fm); }
00226   static inline Polynomial uu (const fast_type& p) {
00227     Format fm= slow<C> (CF(p));
00228     nat l= aligned_size<C,V> (N(p));
00229     C* r= mmx_formatted_new<C> (l, fm);
00230     for (nat i=0; i<N(p); i++) r[i]= slow<C> (p[i]);
00231     return Polynomial (r, N(p), l, fm); }
00232 };
00233 
00234 template<typename T, typename F, typename TV, typename FV>
00235 struct as_helper<polynomial<T,TV>,polynomial<F,FV> > {
00236   static inline polynomial<T,TV>
00237   cv (const polynomial<F,FV>& p) {
00238     format<T> fm= as<format<T> > (CF(p));
00239     nat l= aligned_size<T,TV> (N(p));
00240     T* c= mmx_formatted_new<T> (l, fm);
00241     for (nat i=0; i<N(p); i++) c[i]= as<T> (p[i]);
00242     //return polynomial<T,TV> (c, N(p), l, get_format (c[0]));
00243     // FIXME: a direct return does not seem to work; a compiler bug?
00244     polynomial<T,TV> r= polynomial<T,TV> (c, N(p), l, fm);
00245     return r;
00246   }
00247 };
00248 
00249 template<typename T, typename F, typename TV, typename FV> inline void
00250 set_as (polynomial<T,TV>& r, const polynomial<F,FV>& p) {
00251   r.secure ();
00252   inside (r) -> resize (N(p));
00253   T* c= seg (r);
00254   for (nat i=0; i<N(p); i++) set_as (c[i], p[i]);
00255   inside (r) -> normalize ();
00256 }
00257 
00258 template<typename C, typename V, typename T> inline void
00259 set_as (Polynomial& r, const T& x) {
00260   r.secure ();
00261   inside (r) -> resize (1);
00262   set_as (seg(r)[0], x);
00263   inside (r) -> normalize ();
00264 }
00265 
00266 template<typename Op, typename C, typename V> nat
00267 unary_hash (const Polynomial& p) {
00268   register nat i, h= 642531, n= N(p);
00269   for (i=0; i<n; i++)
00270     h= (h<<1) ^ (h<<5) ^ (h>>27) ^ Op::op (p[i]);
00271   return h;
00272 }
00273 
00274 /******************************************************************************
00275 * Polynomial iteration
00276 ******************************************************************************/
00277 
00278 TMPL_DEF
00279 class polynomial_iterator_rep: public iterator_rep<C> {
00280   Polynomial P;  // the polynomial to traverse
00281   nat i;         // current position
00282 protected:
00283   bool is_busy () { return ((int) i) <= deg (P); }
00284   void advance () { i++; }
00285   C current () { return P[i]; }
00286 public:
00287   polynomial_iterator_rep (const Polynomial& P2):
00288     iterator_rep<C> (CF(P2)), P(P2), i(0) {}
00289 };
00290 
00291 TMPL iterator<C>
00292 iterate (const Polynomial& P) {
00293   return iterator<C> (new polynomial_iterator_rep<C,V> (P));
00294 }
00295 
00296 /******************************************************************************
00297 * Output routines for dense polynomials
00298 ******************************************************************************/
00299 
00300 TMPL inline generic var (const Polynomial& P) {
00301   (void) P; return Polynomial::get_variable_name (); }
00302 
00303 TMPL inline void set_variable_name (const Polynomial& P, const generic& x) {
00304   (void) P; return Polynomial::set_variable_name (x); }
00305 
00306 TMPL syntactic
00307 flatten (const Polynomial& P, const syntactic& v) {
00308   int i, len= deg(P);
00309   syntactic s= 0;
00310   for (i=len; i>=0; i--)
00311     s= s + flatten (P[i]) * pow (v, i);
00312   return s;
00313 }
00314 
00315 TMPL syntactic
00316 flatten (const Polynomial& P) {
00317   return flatten (P, as_syntactic (var (P)));
00318 }
00319 
00320 TMPL
00321 struct binary_polynomial_helper: public void_binary_helper<Polynomial > {
00322   static inline string short_type_name () {
00323     return "P" * Short_type_name (C); }
00324   static inline generic full_type_name () {
00325     return gen ("Polynomial", Full_type_name (C)); }
00326 };
00327 
00328 TMPL
00329 struct binary_helper<Polynomial >: public binary_polynomial_helper<C,V> {
00330   static inline generic disassemble (const Polynomial& p) {
00331     return binary_disassemble<vector<C> > (coefficients (p)); }
00332   static inline Polynomial assemble (const generic& v) {
00333     return Polynomial (binary_assemble<vector<C> > (v)); }
00334   static inline void write (const port& out, const Polynomial& p) {
00335     binary_write<Format > (out, CF(p));
00336     binary_write<nat> (out, N(p));
00337     for (nat i=0; i<N(p); i++)
00338       binary_write<C> (out, p[i]); }
00339   static inline Polynomial read (const port& in) {
00340     Format fm= binary_read<Format > (in);
00341     nat n= binary_read<nat> (in);
00342     nat l= aligned_size<C,V> (n);
00343     C* r= mmx_formatted_new<C> (l, fm);
00344     for (nat i=0; i<n; i++)
00345       r[i]= binary_read<C> (in);
00346     return Polynomial (r, n, l, fm); }
00347 };
00348 
00349 /******************************************************************************
00350 * Valuation and comparisons
00351 ******************************************************************************/
00352 
00353 TMPL int
00354 val (const Polynomial& P) {
00355   for (nat i=0; i<N(P); i++)
00356     if (P[i] != 0) return (int) i;
00357   return (int) (((nat) (-1)) >> 1);
00358 }
00359 
00360 TMPL int
00361 sign (const Polynomial& P) {
00362   for (nat i=0; i<N(P); i++) {
00363     int s= sign (P[i]);
00364     if (s != 0) return s;
00365   }
00366   return 0;
00367 }
00368 
00369 TMPL int
00370 compare (const Polynomial& P1, const Polynomial& P2) {
00371   nat n1= N(P1), n2= N(P2), n= max (n1, n2);
00372   for (nat i=0; i<n; i++) {
00373     int s= sign (P1[i] - P2[i]);
00374     if (s != 0) return s;
00375   }
00376   return 0;
00377 }
00378 
00379 template<typename Op,typename C,typename V> inline bool
00380 binary_test (const Polynomial& P1, const Polynomial& P2) {
00381   nat n1= N(P1), n2= N(P2), n= max (n1, n2);
00382   for (nat i=0; i<n; i++)
00383     if (Op::not_op (P1[i], P2[i])) return false;
00384   return true;
00385 }
00386 
00387 TRUE_IDENTITY_OP_SUGAR(TMPL,Polynomial)
00388 EXACT_IDENTITY_OP_SUGAR(TMPL,Polynomial)
00389 COMPARE_SUGAR(TMPL,Polynomial)
00390 EQUAL_SCALAR_SUGAR(TMPL,Polynomial,C)
00391 COMPARE_SCALAR_SUGAR(TMPL,Polynomial,C)
00392 EQUAL_INT_SUGAR(TMPL,Polynomial)
00393 COMPARE_INT_SUGAR(TMPL,Polynomial)
00394 
00395 /******************************************************************************
00396 * In place arithmetic
00397 ******************************************************************************/
00398 
00399 TMPL Polynomial&
00400 Polynomial::operator += (const Polynomial& P) {
00401   typedef implementation<polynomial_linear,V> Pol;
00402   secure ();
00403   nat n1= rep->n, n2= N(P);
00404   if (n1 < n2) rep -> extend (n2);
00405   Pol::add (rep->a, seg (P), n2);
00406   if (n1 == n2) rep -> normalize ();
00407   return *this;
00408 }
00409 
00410 TMPL Polynomial&
00411 Polynomial::operator -= (const Polynomial& P) {
00412   typedef implementation<polynomial_linear,V> Pol;
00413   secure ();
00414   nat n1= rep->n, n2= N(P);
00415   if (n1 < n2) rep->extend (n2);
00416   Pol::sub (rep->a, seg (P), n2);
00417   if (n1 == n2) rep->normalize ();
00418   return *this;
00419 }
00420 
00421 TMPL Polynomial&
00422 Polynomial::operator *= (const C& c) {
00423   typedef implementation<polynomial_linear,V> Pol;
00424   secure ();
00425   Pol::mul_sc (rep->a, c, rep->n);
00426   rep->normalize ();
00427   return *this;
00428 }
00429 
00430 TMPL Polynomial&
00431 Polynomial::operator /= (const C& c) {
00432   typedef implementation<polynomial_linear,V> Pol;
00433   secure ();
00434   Pol::div_sc (rep->a, c, rep->n);
00435   rep->normalize ();
00436   return *this;
00437 }
00438 
00439 /******************************************************************************
00440 * Basic arithmetic operations
00441 ******************************************************************************/
00442 
00443 TMPL Polynomial
00444 operator - (const Polynomial& P) {
00445   typedef implementation<polynomial_linear,V> Pol;
00446   nat n= N(P);
00447   nat l= aligned_size<C,V> (n);
00448   C* r= mmx_formatted_new<C> (l, CF(P));
00449   Pol::neg (r, seg (P), n);
00450   return Polynomial (r, n, l, CF(P));
00451 }
00452 
00453 TMPL Polynomial
00454 operator + (const Polynomial& P1, const Polynomial& P2) {
00455   typedef implementation<polynomial_linear,V> Pol;
00456   nat m= min (N(P1), N(P2));
00457   nat n= max (N(P1), N(P2));
00458   nat l= aligned_size<C,V> (n);
00459   C* r= mmx_formatted_new<C> (l, CF(P1));
00460   Pol::add (r, seg (P1), seg (P2), m);
00461   if (N(P1) > m) Pol::copy (r+m, seg(P1)+m, n-m);
00462   if (N(P2) > m) Pol::copy (r+m, seg(P2)+m, n-m);
00463   return Polynomial (r, n, l, CF(P1));
00464 }
00465 
00466 TMPL Polynomial operator + (const Polynomial& P, const C& c) {
00467   return P + Polynomial (c); }
00468 TMPL Polynomial operator + (const C& c, const Polynomial& P) {
00469   return Polynomial (c) + P; }
00470 
00471 TMPL Polynomial
00472 big_add (const vector<Polynomial >& a) {
00473   typedef implementation<polynomial_linear,V> Pol;
00474   nat i, k= N(a), n=0;
00475   nat l= aligned_size<C,V> (n);
00476   for (i=0; i<k; i++) n= max (N(a[i]), n);
00477   C* r= mmx_formatted_new<C> (l, CF (get_sample (CF (a))));
00478   Pol::set (r, 0, n);
00479   for (i=0; i<k; i++) Pol::add (r, seg (a[i]), N(a[i]));
00480   return Polynomial (r, n, l, Format (CF(a)));
00481 }
00482 
00483 TMPL Polynomial
00484 operator - (const Polynomial& P1, const Polynomial& P2) {
00485   typedef implementation<polynomial_linear,V> Pol;
00486   nat m= min (N(P1), N(P2));
00487   nat n= max (N(P1), N(P2));
00488   nat l= aligned_size<C,V> (n);
00489   C* r= mmx_formatted_new<C> (l, CF(P1));
00490   Pol::sub (r, seg (P1), seg (P2), m);
00491   if (N(P1) > m) Pol::copy (r+m, seg(P1)+m, n-m);
00492   if (N(P2) > m) Pol::neg  (r+m, seg(P2)+m, n-m);
00493   return Polynomial (r, n, l, CF(P1));
00494 }
00495 
00496 TMPL Polynomial operator - (const Polynomial& P, const C& c) {
00497   return P - Polynomial (c); }
00498 TMPL Polynomial operator - (const C& c, const Polynomial& P) {
00499   return Polynomial (c) - P; }
00500 
00501 TMPL Polynomial
00502 operator * (const Polynomial& P1, const Polynomial& P2) {
00503   typedef implementation<polynomial_multiply,V> Pol;
00504   nat n1= N(P1), n2= N(P2);
00505   if (n1 == 0 || n2 == 0) return Polynomial (CF(P1));
00506   nat l= aligned_size<C,V> (n1+n2-1);
00507   C* r= mmx_formatted_new<C> (l, CF(P1));
00508   Pol::mul (r, seg (P1), seg (P2), n1, n2);
00509   return Polynomial (r, n1+n2-1, l, CF(P1));
00510 }
00511 
00514 TMPL Polynomial
00515 tmul (int d2, const Polynomial& P1, const Polynomial& P2) {
00516   typedef implementation<polynomial_multiply,V> Pol;
00517   nat n2 = max (0, d2 + 1), n1= N(P1), n= N(P2);
00518   if (n1 == 0 || n2 == 0) return Polynomial (CF(P1));
00519   ASSERT (n < n1 + n2, "bad dimension in tmul");
00520   nat l2= aligned_size<C,V> (n2);
00521   C* r= mmx_formatted_new<C> (l2, CF(P1));
00522   if (n != n1 + n2 - 1) {
00523     nat l= aligned_size<C,V> (n1+n2-1);
00524     C* s2= mmx_formatted_new<C> (l, CF(P1));
00525     Pol::copy (s2, seg (P2), n);
00526     Pol::clear (s2 + n, n1+n2-n-1);
00527     Pol::tmul (r, seg (P1), s2, n1, n2);
00528     mmx_delete<C> (s2, l);
00529   }
00530   else
00531     Pol::tmul (r, seg (P1), seg (P2), n1, n2);
00532   return Polynomial (r, n2, l2, CF(P1));
00533 }
00534 
00535 TMPL Polynomial
00536 square (const Polynomial& P) {
00537   typedef implementation<polynomial_multiply,V> Pol;
00538   nat n= N(P);
00539   if (n == 0) return P;
00540   nat l= aligned_size<C,V> (2*n-1);
00541   C* r= mmx_formatted_new<C> (l, CF(P));
00542   Pol::square (r, seg (P), n);
00543   return Polynomial (r, 2*n-1, l, CF(P));
00544 }
00545 
00546 TMPL Polynomial
00547 operator * (const Polynomial& P, const C& c) {
00548   typedef implementation<polynomial_linear,V> Pol;
00549   nat n= N(P);
00550   nat l= aligned_size<C,V> (n);
00551   C* r= mmx_formatted_new<C> (l, CF(P));
00552   Pol::mul_sc (r, seg (P), c, n);
00553   return Polynomial (r, n, l, CF(P));
00554 }
00555 
00556 TMPL Polynomial
00557 operator * (const C& c, const Polynomial& P) {
00558   typedef implementation<polynomial_linear,V> Pol;
00559   nat n= N(P);
00560   nat l= aligned_size<C,V> (n);
00561   C* r= mmx_formatted_new<C> (l, CF(P));
00562   Pol::mul_sc (r, seg (P), c, n);
00563   return Polynomial (r, n, l, CF(P));
00564 }
00565 
00566 TMPL Polynomial
00567 big_mul (const vector<Polynomial >& a) {
00568   typedef implementation<vector_linear,V> Vec;
00569   return Vec::template vec_unary_big_dicho<mul_op> (seg (a), N(a));
00570 }
00571 
00572 TMPL Polynomial
00573 operator / (const Polynomial& P, const C& c) {
00574   typedef implementation<polynomial_linear,V> Pol;
00575   nat n= N(P);
00576   nat l= aligned_size<C,V> (n);
00577   C* r= mmx_formatted_new<C> (l, CF(P));
00578   Pol::div_sc (r, seg (P), c, n);
00579   return Polynomial (r, n, l, CF(P));
00580 }
00581 
00582 TMPL Polynomial
00583 operator / (const Polynomial& P1, const Polynomial& P2) {
00584   typedef implementation<polynomial_exact_divide,V> Pol;
00585   nat n1= N(P1), n2= N(P2);
00586   ASSERT (n2 != 0, "division by zero");
00587   if (n1 < n2) return Polynomial (CF(P1));
00588   nat lq= aligned_size<C,V> (n1-n2+1);
00589   C* q= mmx_formatted_new<C> (lq, CF(P1));
00590   Pol::div (q, seg (P1), seg (P2), n1, n2);
00591   return Polynomial (q, n1-n2+1, lq, CF(P1));
00592 }
00593 
00594 TMPL Polynomial
00595 skew_div (const Polynomial& P, const C& c, bool left) {
00596   typedef implementation<polynomial_linear,V> Pol;
00597   if (left) {
00598     nat n= N(P);
00599     nat l= aligned_size<C,V> (n);
00600     C* r= mmx_formatted_new<C> (n, CF(P));
00601     Pol::div_sc (r, seg (P), c, n);
00602     return Polynomial (r, n, l, CF(P));
00603   }
00604   else return P / c;
00605 }
00606 
00607 TMPL Polynomial
00608 quo (const Polynomial& P, const C& c) {
00609   typedef implementation<polynomial_linear,V> Pol;
00610   nat n= N(P);
00611   nat l= aligned_size<C,V> (n);
00612   C* r= mmx_formatted_new<C> (l, CF(P));
00613   Pol::quo_sc (r, seg (P), c, n);
00614   return Polynomial (r, n, l, CF(P));
00615 }
00616 
00617 TMPL Polynomial
00618 rem (const Polynomial& P, const C& c) {
00619   typedef implementation<polynomial_linear,V> Pol;
00620   nat n= N(P);
00621   nat l= aligned_size<C,V> (n);
00622   C* r= mmx_formatted_new<C> (l, CF(P));
00623   Pol::rem_sc (r, seg (P), c, n);
00624   return Polynomial (r, n, l, CF(P));
00625 }
00626 
00627 TMPL Polynomial
00628 quo (const Polynomial& P1, const Polynomial& P2) {
00629   typedef implementation<polynomial_divide,V> Pol;
00630   nat n1= N(P1), n2= N(P2);
00631   if (n1 < n2 || n2 == 0) return Polynomial (CF(P1));
00632   nat lq= aligned_size<C,V> (n1-n2+1);
00633   nat lr= aligned_size<C,V> (n1);
00634   C* q= mmx_formatted_new<C> (lq, CF(P1));
00635   C* r= mmx_formatted_new<C> (lr, CF(P1));
00636   Pol::copy (r, seg (P1), n1);
00637   Pol::quo_rem (q, r, seg (P2), n1, n2);
00638   mmx_delete<C> (r, lr);
00639   return Polynomial (q, n1-n2+1, lq, CF(P1));
00640 }
00641 
00643 TMPL Polynomial
00644 tquo (int d1, const Polynomial& P1, const Polynomial& P2) {
00645   typedef implementation<polynomial_divide,V> Pol;
00646   nat n1= max (0, d1+1), n= N(P1), n2= N(P2);
00647   ASSERT (n <= n1-n2+1, "bad dimension in tquo");
00648   if (n1 < n2 || n2 == 0) return Polynomial (CF(P1));
00649   nat l= aligned_size<C,V> (n1);
00650   C* q= mmx_formatted_new<C> (l, CF(P1));
00651   C* r= mmx_formatted_new<C> (l, CF(P1));
00652   Pol::clear (r, n1);
00653   Pol::copy  (r+n2-1, seg (P1), n);
00654   Pol::tquo_rem (q, r, seg (P2), n1, n2);
00655   mmx_delete<C> (r, l);
00656   return Polynomial (q, n1, l, CF(P1));
00657 }
00658 
00659 TMPL Polynomial
00660 rem (const Polynomial& P1, const Polynomial& P2) {
00661   typedef implementation<polynomial_divide,V> Pol;
00662   nat n1= N(P1), n2= N(P2);
00663   if (n1 < n2 || n2 == 0) return P1;
00664   nat lq= aligned_size<C,V> (n1-n2+1);
00665   nat lr= aligned_size<C,V> (n1);
00666   C* q= mmx_formatted_new<C> (lq, CF(P1));
00667   C* r= mmx_formatted_new<C> (lr, CF(P1));
00668   Pol::copy (r, seg (P1), n1);
00669   Pol::quo_rem (q, r, seg (P2), n1, n2);
00670   mmx_delete<C> (q, lq);
00671   return Polynomial (r, n2 - 1, lr, CF(P1));
00672 }
00673 
00674 TMPL bool
00675 divides (const Polynomial& P1, const Polynomial& P2) {
00676   return rem (P2, P1) == 0;
00677 }
00678 
00680 TMPL Polynomial
00681 rem (const Polynomial& P1, const Polynomial& P2, Polynomial& Q) {
00682   typedef implementation<polynomial_divide,V> Pol;
00683   nat n1= N(P1), n2= N(P2);
00684   if (n1 < n2 || n2 == 0) return Polynomial (CF(P1));
00685   nat lq= aligned_size<C,V> (n1-n2+1);
00686   nat lr= aligned_size<C,V> (n1);
00687   C* q= mmx_formatted_new<C> (lq, CF(P1));
00688   C* r= mmx_formatted_new<C> (lr, CF(P1));
00689   Pol::copy (r, seg (P1), n1);
00690   Pol::quo_rem (q, r, seg (P2), n1, n2);
00691   Q= Polynomial (q, n1-n2+1, lq, CF(P1));
00692   return Polynomial (r, n2 - 1, lr, CF(P1));
00693 }
00694 
00696 TMPL Polynomial
00697 trem (int d1, const Polynomial& P1, const Polynomial& P2) {
00698   typedef implementation<polynomial_divide,V> Pol;
00699   nat n1= max (0, d1+1), n= N(P1), n2= N(P2);
00700   ASSERT (n <= n2-1, "bad dimension in trem");
00701   if (n1 < n2 || n2 == 0) return P1;
00702   nat l= aligned_size<C,V> (n1);
00703   C* q= mmx_formatted_new<C> (l, CF(P1));
00704   C* r= mmx_formatted_new<C> (l, CF(P1));
00705   Pol::copy  (r, seg (P1), n);
00706   Pol::clear (r+n, n1-n);
00707   Pol::tquo_rem (q, r, seg (P2), n1, n2);
00708   mmx_delete<C> (r, l);
00709   return Polynomial (q, n1, l, CF(P1));
00710 }
00711 
00714 TMPL inline int
00715 pexponent (const Polynomial& P1, const Polynomial& P2) {
00716   return max (0, deg (P1) - deg (P2) + 1);
00717 }
00718 
00719 TMPL Polynomial
00720 pquo (const Polynomial& P1, const Polynomial& P2) {
00721   typedef implementation<polynomial_divide,V> Pol;
00722   nat n1= N(P1), n2= N(P2);
00723   if (n1 < n2 || n2 == 0) return Polynomial (CF(P1));
00724   nat lq= aligned_size<C,V> (n1-n2+1);
00725   nat lr= aligned_size<C,V> (n1);
00726   C* q= mmx_formatted_new<C> (lq, CF(P1));
00727   C* r= mmx_formatted_new<C> (lr, CF(P1));
00728   Pol::copy (r, seg (P1), n1);
00729   Pol::pquo_rem (q, r, seg (P2), n1, n2);
00730   mmx_delete<C> (r, lr);
00731   return Polynomial (q, n1-n2+1, lq, CF(P1));
00732 }
00733 
00734 TMPL Polynomial
00735 prem (const Polynomial& P1, const Polynomial& P2) {
00736   typedef implementation<polynomial_divide,V> Pol;
00737   nat n1= N(P1), n2= N(P2);
00738   if (n1 < n2 || n2 == 0) return P1;
00739   nat lq= aligned_size<C,V> (n1-n2+1);
00740   nat lr= aligned_size<C,V> (n1);
00741   C* q= mmx_formatted_new<C> (lq, CF(P1));
00742   C* r= mmx_formatted_new<C> (lr, CF(P1));
00743   Pol::copy (r, seg (P1), n1);
00744   Pol::pquo_rem (q, r, seg (P2), n1, n2);
00745   mmx_delete<C> (q, lq);
00746   return Polynomial (r, n2 - 1, lr, CF(P1));
00747 }
00748 
00750 TMPL Polynomial
00751 prem (const Polynomial& P1, const Polynomial& P2, Polynomial& Q) {
00752   typedef implementation<polynomial_divide,V> Pol;
00753   nat n1= N(P1), n2= N(P2);
00754   if (n1 < n2 || n2 == 0) return Polynomial (CF(P1));
00755   nat lq= aligned_size<C,V> (n1-n2+1);
00756   nat lr= aligned_size<C,V> (n1);
00757   C* q= mmx_formatted_new<C> (lq, CF(P1));
00758   C* r= mmx_formatted_new<C> (lr, CF(P1));
00759   Pol::copy (r, seg (P1), n1);
00760   Pol::pquo_rem (q, r, seg (P2), n1, n2);
00761   Q= Polynomial (q, n1-n2+1, lq, CF(P1));
00762   return Polynomial (r, n2 - 1, lr, CF(P1));
00763 }
00764 
00765 TMPL inline Polynomial operator / (const C& c, const Polynomial& P) {
00766   return Polynomial (c) / P; }
00767 
00768 ARITH_SCALAR_INT_SUGAR(TMPL,Polynomial)
00769 
00770 /******************************************************************************
00771 * Gcd computations
00772 ******************************************************************************/
00773 
00774 // gcd (P1, P2) = U1 P1 + U2 P2, with
00775 // deg U1 < deg P2 and deg U2 < deg P1 (for non-degenerated cases)
00776 
00777 TMPL inline C
00778 contents (const Polynomial& P) {
00779   typedef implementation<polynomial_linear,V> Pol;
00780   return Pol::big_gcd (seg (P), N(P));
00781 }
00782 
00783 TMPL inline Polynomial
00784 primitive_part (const Polynomial& P, C& c) {
00785   typedef implementation<polynomial_linear,V> Pol;
00786   c= contents (P);
00787   nat n= N(P);
00788   nat l= aligned_size<C,V> (n);
00789   C* r= mmx_formatted_new<C> (l, CF(P));
00790   Pol::div_sc (r, seg (P), c, n);
00791   return Polynomial (r, n, l, CF(P));
00792 }
00793 
00794 TMPL inline Polynomial
00795 primitive_part (const Polynomial& P) {
00796   C c;
00797   return primitive_part (P, c);
00798 }
00799 
00800 TMPL inline Polynomial
00801 gcd (const Polynomial& P1, const Polynomial& P2,
00802      Polynomial& U1, Polynomial& U2) {
00803   typedef implementation<polynomial_gcd,V> Pol;
00804   C one= promote (1, CF(P1));
00805   U1= one; U2= one;
00806   return Pol::gcd (P1, P2, U1, U2);
00807 }
00808 
00809 TMPL inline Polynomial
00810 gcd (const Polynomial& P1, const Polynomial& P2, Polynomial& U1) {
00811   Polynomial U2(0); U1= promote (1, CF(P1));
00812   return gcd (P1, P2, U1, U2);
00813 }
00814 
00815 TMPL inline Polynomial
00816 gcd (const Polynomial& P1, const Polynomial& P2) {
00817   typedef implementation<polynomial_gcd,V> Pol;
00818   return Pol::gcd (P1, P2);
00819 }
00820 
00821 TMPL static vector<Polynomial>
00822 gcd (const Polynomial& p, const vector<Polynomial>& q) {
00823   typedef implementation<polynomial_evaluate,V> Pol;
00824   return Pol::multi_gcd (p, q);
00825 }
00826 
00827 TMPL inline Polynomial
00828 lcm (const Polynomial& P1, const Polynomial& P2) {
00829   typedef implementation<polynomial_gcd,V> Pol;
00830   return Pol::lcm (P1, P2);
00831 }
00832 
00833 TMPL inline Polynomial
00834 invert_modulo (const Polynomial& P, const Polynomial& Q) {
00835   typedef implementation<polynomial_gcd,V> Pol;
00836   return Pol::invert_mod (P, Q);
00837 }
00838 
00839 TMPL inline void
00840 pade (const Polynomial& P, nat n, nat k, Polynomial& Num, Polynomial &Den) {
00841   typedef implementation<polynomial_gcd,V> Pol;
00842   Pol::pade (P, n, k, Num, Den);
00843 }
00844 
00845 template<typename C,typename V,typename W> inline void
00846 minimal_polynomial_bis (Polynomial& p, const vector<C,W>& v) {
00847   // p is the minimal polynomial of the sequence of the elements in v
00848   // Algorithm 12.19 of "Modern Computer Algebra"
00849   nat n= N(v); nat k= n >> 1;
00850   ASSERT ((n & 1) == 0, "even size expected");
00851   Polynomial h (v), s, t;
00852   pade (h, n, k, s, t);
00853   t= reverse (t);
00854   p= (deg(t) < 1 + deg(s)) ? lshiftz (t, 1 + deg (s) - deg (t)) : t;
00855 }
00856 
00857 template<typename C,typename W> inline
00858 polynomial<C,typename Polynomial_variant(C) >
00859 minimal_polynomial (const vector<C,W>& v) {
00860   polynomial<C,typename Polynomial_variant(C) > P;
00861   minimal_polynomial_bis (P, v);
00862   return P;
00863 }
00864 
00865 /******************************************************************************
00866 * Subresultants
00867 ******************************************************************************/
00868 
00869 // Recall that subresultants are only well-defined until
00870 // degree min (deg (P), deg (Q)) - 1.
00871 
00872 TMPL inline vector<Polynomial>
00873 subresultants (const Polynomial& P, const Polynomial& Q,
00874                vector<Polynomial>& co_P, vector<Polynomial>& co_Q) {
00875   typedef implementation<polynomial_subresultant,V> Pol;
00876   int n= deg (P), m= deg (Q); nat l= max (min (n, m), 0);
00877   C one= promote (1, CF(P));
00878   Polynomial d; vector<Polynomial> res (Polynomial (one), l);
00879   co_P= vector<Polynomial> (Polynomial (one), l);
00880   co_Q= vector<Polynomial> (Polynomial (one), l); 
00881   Pol::subresultant_sequence (P, Q, res, co_P, co_Q,
00882                               d, d, d, d, d, d, 0);
00883   return res;
00884 }
00885 
00886 TMPL inline vector<Polynomial>
00887 subresultants (const Polynomial& P, const Polynomial& Q,
00888                vector<Polynomial>& co_P) {
00889   typedef implementation<polynomial_subresultant,V> Pol;
00890   int n= deg (P), m= deg (Q); nat l= max (min (n, m), 0);
00891   Polynomial d;
00892   C zero= promote (0, CF(P)), one= promote (1, CF(P));
00893   vector<Polynomial> res (Polynomial (one), l), co_Q (Polynomial (zero), 0); 
00894   co_P= vector<Polynomial> (Polynomial (one), l);
00895   Pol::subresultant_sequence (P, Q, res, co_P, co_Q,
00896                               d, d, d, d, d, d, 0);
00897   return res;
00898 }
00899 
00900 TMPL inline vector<Polynomial>
00901 subresultants (const Polynomial& P, const Polynomial& Q) {
00902   typedef implementation<polynomial_subresultant,V> Pol;
00903   int n= deg (P), m= deg (Q); nat l= max (min (n, m), 0);
00904   Polynomial d;
00905   C zero= promote (0, CF(P)), one= promote (1, CF(P));
00906   vector<Polynomial>
00907     res (Polynomial(one), l),
00908     co_P (Polynomial (zero), 0),
00909     co_Q (Polynomial (zero), 0); 
00910   Pol::subresultant_sequence (P, Q, res, co_P, co_Q,
00911                               d, d, d, d, d, d, 0);
00912   return res;
00913 }
00914 
00915 TMPL inline Polynomial
00916 subresultant (const Polynomial& P, const Polynomial& Q, int k,
00917               Polynomial& coP, Polynomial& coQ) {
00918   typedef implementation<polynomial_subresultant,V> Pol;
00919   int n= deg (P), m= deg (Q);
00920   nat l= max (min (n, m), 0);
00921   ASSERT (k < l, "index out of range");
00922   C zero= promote (0, CF(P)), one= promote (1, CF(P));
00923   Polynomial d; 
00924   vector<Polynomial>
00925     res (Polynomial (zero), l),
00926     co_P (Polynomial (zero), l),
00927     co_Q (Polynomial (zero), l); 
00928   res [k]= Polynomial (one);
00929   co_P[k]= Polynomial (one);
00930   co_Q[k]= Polynomial (one);
00931   Pol::subresultant_sequence (P, Q, res, co_P, co_Q,
00932                               d, d, d, d, d, d, 0);
00933   coP= co_P[k]; coQ= co_Q[k];
00934   return res[k];
00935 }
00936 
00937 TMPL inline Polynomial
00938 subresultant (const Polynomial& P, const Polynomial& Q, int k,
00939               Polynomial& coP) {
00940   typedef implementation<polynomial_subresultant,V> Pol;
00941   int n= deg (P), m= deg (Q);
00942   nat l= max (min (n, m), 0);
00943   ASSERT (k < l, "index out of range");
00944   Polynomial d;
00945   C zero= promote (0, CF(P)), one= promote (1, CF(P));
00946   vector<Polynomial>
00947     res (Polynomial (zero), l),
00948     co_P (Polynomial (zero), l),
00949     co_Q (Polynomial (zero), 0); 
00950   res [k]= Polynomial (one);
00951   co_P[k]= Polynomial (one);
00952   Pol::subresultant_sequence (P, Q, res, co_P, co_Q,
00953                               d, d, d, d, d, d, 0);
00954   coP= co_P[k];
00955   return res[k];
00956 }
00957 
00958 TMPL inline Polynomial
00959 subresultant (const Polynomial& P, const Polynomial& Q, int k) {
00960   typedef implementation<polynomial_subresultant,V> Pol;
00961   if (k < 0) return promote (0, P);
00962   int n= deg (P), m= deg (Q);
00963   nat l= max (min (n, m), 0);
00964   ASSERT ((nat) k < l, "index out of range");
00965   Polynomial d;
00966   C zero= promote (0, CF(P)), one= promote (1, CF(P));
00967   vector<Polynomial>
00968     res (Polynomial (zero), l),
00969     co_P (Polynomial (zero), 0),
00970     co_Q (Polynomial (zero), 0);
00971   res [k]= Polynomial (one);
00972   Pol::subresultant_sequence (P, Q, res, co_P, co_Q,
00973                               d, d, d, d, d, d, 0);
00974   return res[k];
00975 }
00976 
00977 TMPL inline C
00978 resultant (const Polynomial& P, const Polynomial& Q) {
00979   typedef implementation<polynomial_subresultant,V> Pol;
00980   int n= degree (P), m= degree (Q);
00981   if (n < 0 || m < 0) return promote (0, CF(P));
00982   if (m == 0) return binpow (Q[0], n);
00983   if (n == 0) {
00984     C r= binpow (P[0], m); 
00985     return (n & 1) ? -r : r;
00986   }
00987   Polynomial d;
00988   C zero= promote (0, CF(P)), one= promote (1, CF(P));
00989   vector<Polynomial>
00990     res (Polynomial (one), 1),
00991     co_P (Polynomial (zero), 0),
00992     co_Q (Polynomial (zero), 0);
00993   Pol::subresultant_sequence (P, Q, res, co_P, co_Q,
00994                               d, d, d, d, d, d, 0);
00995   return res[0][0];
00996 }
00997 
00998 TMPL inline C
00999 discriminant (const Polynomial& P) {
01000   typedef implementation<polynomial_subresultant,V> Pol;
01001   return resultant (derive (P), P);
01002 }
01003 
01004 /******************************************************************************
01005 * Differentiation, integration and composition
01006 ******************************************************************************/
01007 
01008 TMPL Polynomial
01009 derive (const Polynomial& P) {
01010   typedef implementation<polynomial_linear,V> Pol;
01011   nat n= N(P);
01012   if (n <= 1) return promote (0, P);
01013   nat l= aligned_size<C,V> (n-1);
01014   C* r= mmx_formatted_new<C> (l, CF(P));
01015   Pol::derive (r, seg (P), n);
01016   return Polynomial (r, n-1, l, CF(P));
01017 }
01018 
01019 TMPL Polynomial
01020 derive (const Polynomial& P, const nat& order) {
01021   typedef implementation<polynomial_linear,V> Pol;
01022   nat n= N(P);
01023   if (n <= order) return promote (0, P);
01024   nat l= aligned_size<C,V> (n-order);
01025   C* r= mmx_formatted_new<C> (l, CF(P));
01026   Pol::derive (r, seg (P), n, order);
01027   return Polynomial (r, n-order, l, CF(P));
01028 }
01029 
01030 TMPL Polynomial
01031 xderive (const Polynomial& P) {
01032   typedef implementation<polynomial_linear,V> Pol;
01033   nat n= N(P);
01034   nat l= aligned_size<C,V> (n);
01035   C* r= mmx_formatted_new<C> (l, CF(P));
01036   Pol::xderive (r, seg (P), n);
01037   return Polynomial (r, n, l, CF(P));
01038 }
01039 
01040 TMPL Polynomial
01041 integrate (const Polynomial& P) {
01042   typedef implementation<polynomial_linear,V> Pol;
01043   nat n= N(P);
01044   nat l= aligned_size<C,V> (n+1);
01045   C* r= mmx_formatted_new<C> (l, CF(P));
01046   Pol::integrate (r, seg (P), n);
01047   return Polynomial (r, n+1, l, CF(P));
01048 }
01049 
01050 template<typename C,typename V,typename K> Polynomial
01051 compose (const Polynomial& P1, const polynomial<K,V>& P2) {
01052   typedef implementation<polynomial_compose,V> Pol;
01053   nat n1= N(P1), n2= N(P2);
01054   if (n1 <= 1) return P1;
01055   if (n2 == 0) return P1[0];
01056   nat n= (n1-1) * (n2-1) + 1;
01057   nat l= aligned_size<C,V> (n);
01058   C* r= mmx_formatted_new<C> (l, CF(P1));
01059   Pol::compose (r, seg (P1), seg (P2), n1, n2);
01060   return Polynomial (r, n, l, CF(P1));
01061 }
01062 
01063 TMPL Polynomial
01064 shift (const Polynomial& P, const C& sh) {
01065   typedef implementation<polynomial_compose,V> Pol;
01066   nat n= N(P);
01067   if (n <= 1 || sh == 0) return P;
01068   nat l= aligned_size<C,V> (n);
01069   C* r= mmx_formatted_new<C> (l, CF(P));
01070   Pol::shift (r, seg (P), sh, n);
01071   return Polynomial (r, n, l, CF(P));
01072 }
01073 
01074 TMPL Polynomial
01075 shift (const Polynomial& P, int i) {
01076   return shift (P, promote (i, CF(P)));
01077 }
01078 
01079 template<typename C,typename V,typename K> Polynomial
01080 q_difference (const Polynomial& P, const K& q) {
01081   typedef implementation<polynomial_linear,V> Pol;
01082   nat n= N(P);
01083   if (n <= 1) return P;
01084   nat l= aligned_size<C,V> (n);
01085   C* r= mmx_formatted_new<C> (l, CF(P));
01086   Pol::q_difference (r, seg (P), q, n);
01087   return Polynomial (r, n, l, CF(P));
01088 }
01089 
01090 TMPL Polynomial
01091 dilate (const Polynomial& P, nat p) {
01092   typedef implementation<polynomial_linear,V> Pol;
01093   if (p == 1) return P;
01094   nat n= N(P);
01095   if (n <= 1) return P;
01096   nat k= (n-1)*p + 1;
01097   nat l= aligned_size<C,V> (k);
01098   C* r= mmx_formatted_new<C> (l, CF(P));
01099   Pol::dilate (r, seg (P), p, n);
01100   return Polynomial (r, k, l, CF(P));
01101 }
01102 
01103 /******************************************************************************
01104 * Evaluation
01105 ******************************************************************************/
01106 
01107 TMPL inline vector<Polynomial>
01108 rem (const Polynomial& p, const vector<Polynomial>& q) {
01109   typedef implementation<polynomial_evaluate,V> Pol;
01110   return Pol::multi_rem (p, q);
01111 }
01112 
01113 TMPL inline vector<Polynomial>
01114 prem (const Polynomial& p, const vector<Polynomial>& q) {
01115   typedef implementation<polynomial_evaluate,V> Pol;
01116   return Pol::multi_prem (p, q);
01117 }
01118 
01119 TMPL inline Polynomial
01120 annulator_bis (const Vector& x) {
01121   typedef implementation<polynomial_evaluate,V> Pol;
01122   return Pol::template annulator<Polynomial> (x);
01123 }
01124 
01125 template<typename C> inline polynomial<C,typename Polynomial_variant(C) >
01126 annulator (const Vector& x) {
01127   return annulator_bis<C,typename Polynomial_variant(C) > (x);
01128 }
01129 
01130 TMPL inline C
01131 evaluate (const Polynomial& p, const C& x) {
01132   typedef implementation<polynomial_evaluate,V> Pol;
01133   return Pol::evaluate (seg (p), x, N(p));
01134 }
01135 
01136 TMPL inline C
01137 eval (const Polynomial& p, const C& x) {
01138   return evaluate (p, x);
01139 }
01140 
01141 TMPL inline Polynomial
01142 tevaluate_bis (const C& v, const C& x, nat n) {
01143   typedef implementation<polynomial_evaluate,V> Pol;
01144   nat l= aligned_size<C,V> (n);
01145   C* buf= mmx_formatted_new<C> (l, get_format (v));
01146   Pol::tevaluate (v, buf, x, n);
01147   return Polynomial (buf, n, l, get_format (v));
01148 }
01149 
01150 template<typename C> inline polynomial<C,typename Polynomial_variant(C) >
01151 tevaluate (const C& v, const C& x, nat n) {
01152   return tevaluate_bis<C,typename Polynomial_variant(C) > (v, x, n);
01153 }
01154 
01155 TMPL inline Vector
01156 evaluate (const Polynomial& p, const Vector& x) {
01157   typedef implementation<polynomial_evaluate,V> Pol;
01158   return Pol::evaluate (p, x);
01159 }
01160 
01161 TMPL inline Vector
01162 eval (const Polynomial& p, const Vector& x) {
01163   return evaluate (p, x);
01164 }
01165 
01166 TMPL inline Polynomial
01167 tevaluate_bis (const Vector& v, const Vector& x, nat l) {
01168   typedef implementation<polynomial_evaluate,V> Pol;
01169   return Pol::template tevaluate<Polynomial> (v, x, l);
01170 }
01171 
01172 template<typename C> inline polynomial<C,typename Polynomial_variant(C) >
01173 tevaluate (const Vector& v, const Vector& x, nat l) {
01174   return tevaluate_bis<C,typename Polynomial_variant(C) > (v, x, l);
01175 }
01176 
01177 TMPL inline Polynomial
01178 interpolate_bis (const Vector& v, const Vector& x) {
01179   typedef implementation<polynomial_evaluate,V> Pol;
01180   return Pol::template interpolate<Polynomial> (v, x);
01181 }
01182 
01183 template<typename C> inline polynomial<C,typename Polynomial_variant(C) >
01184 interpolate (const Vector& v, const Vector& x) {
01185   return interpolate_bis<C,typename Polynomial_variant(C) > (v, x);
01186 }
01187 
01188 TMPL Vector
01189 tinterpolate (const Polynomial& p, const Vector& x) {
01190   typedef implementation<polynomial_evaluate,V> Pol;
01191   return Pol::tinterpolate (p, x);
01192 }
01193 
01194 TMPL vector<Polynomial >
01195 expand (const Polynomial& p, const Vector& v, const vector<nat>& mu) {
01196   typedef implementation<polynomial_evaluate,V> Pol;
01197   nat k= N(v);
01198   ASSERT (N(mu) == k, "dimensions don't match");
01199   C** r= mmx_new<C*> (k);
01200   for (nat i=0; i<k; i++)
01201     r[i]= mmx_formatted_new<C> (aligned_size<C,V> (mu[i]), CF(p));
01202   Pol::expand (r, seg (p), seg (v), seg (mu), N (p), k);
01203   nat l= default_aligned_size<Polynomial > (k);
01204   Polynomial* ret= mmx_formatted_new<Polynomial > (l, get_format (p));
01205   for (nat i=0; i<k; i++)
01206     ret[i]= Polynomial (r[i], mu[i], aligned_size<C,V> (mu[i]), CF(p));
01207   mmx_delete<C*> (r, k);
01208   return vector<Polynomial > (ret, k, l);
01209 }
01210 
01211 /******************************************************************************
01212 * Miscellaneous
01213 ******************************************************************************/
01214 
01215 TMPL Polynomial
01216 range (const Polynomial& P, nat start, nat end) {
01217   typedef implementation<polynomial_linear,V> Pol;
01218   nat l= aligned_size<C,V> (end-start);
01219   C* r= mmx_formatted_new<C> (l, CF(P));
01220   for (nat i=start; i<end; i++) r[i-start]= P[i];
01221   return Polynomial (r, end-start, l, CF(P));
01222 }
01223 
01224 TMPL Polynomial
01225 extract_mod (const Polynomial& P, nat k, nat p) {
01226   typedef implementation<polynomial_linear,V> Pol;
01227   nat n= (N(P) - k + p - 1) / p;
01228   nat l= aligned_size<C,V> (n);
01229   C* r= mmx_formatted_new<C> (l, CF(P));
01230   for (nat i=0; i<n; i++) r[i]= P[i*p+k];
01231   return Polynomial (r, n, l, CF(P));
01232 }
01233 
01234 TMPL Polynomial
01235 lshiftz (const Polynomial& P, const int& shift) {
01236   typedef implementation<polynomial_linear,V> Pol;
01237   if (shift == 0) return P;
01238   else if (shift <= -((int) N(P))) return promote (0, P);
01239   else if (shift < 0) return range (P, (nat) (-shift), N(P));
01240   else {
01241     nat n= N(P) + shift;
01242     nat l= aligned_size<C,V> (n);
01243     C* r= mmx_formatted_new<C> (l, CF(P));
01244     Pol::copy (r+shift, seg (P), N(P));
01245     return Polynomial (r, n, l, CF(P));
01246   }
01247 }
01248 
01249 TMPL Polynomial
01250 reverse (const Polynomial& P) {
01251   typedef implementation<polynomial_linear,V> Pol;
01252   typedef implementation<vector_linear,V> Vec;
01253   nat n= N(P);
01254   nat l= aligned_size<C,V> (n);
01255   C* r= mmx_formatted_new<C> (l, CF(P));
01256   Vec::vec_reverse (r, seg (P), n);
01257   return Polynomial (r, n, l, CF(P));
01258 }
01259 
01260 TMPL Polynomial
01261 graeffe (const Polynomial& P) {
01262   typedef implementation<polynomial_graeffe,V> Pol;
01263   nat n= N(P);
01264   nat l= aligned_size<C,V> (n);
01265   C* r= mmx_formatted_new<C> (l, CF(P));
01266   Pol::graeffe (r, seg (P), n);
01267   return Polynomial (r, n, l, CF(P));
01268 }
01269 
01270 TMPL Polynomial
01271 invert_lo (const Polynomial& P, nat m) {
01272   typedef implementation<polynomial_divide,V> Pol;
01273   nat n= N(P);
01274   nat l= aligned_size<C,V> (m);
01275   C* r= mmx_formatted_new<C> (l, CF(P));
01276   if (n >= m)
01277     Pol::invert_lo (r, seg (P), m);
01278   else {
01279     C* t= mmx_formatted_new<C> (l, CF(P));
01280     Pol::copy (t, seg (P), n);
01281     Pol::clear (t + n, m - n);
01282     Pol::invert_lo (r, t, m);
01283   }
01284   return Polynomial (r, m, l, CF(P));
01285 }
01286 
01287 TMPL inline Polynomial
01288 invert_lo (const Polynomial& P) {
01289   return invert_lo (P, N(P));
01290 }
01291 
01292 TMPL Polynomial
01293 invert_hi (const Polynomial& P) {
01294   typedef implementation<polynomial_divide,V> Pol;
01295   nat n= N(P);
01296   nat l= aligned_size<C,V> (n);
01297   C* r= mmx_formatted_new<C> (l, CF(P));
01298   Pol::invert_hi (r, seg (P), n);
01299   return Polynomial (r, n, l, CF(P));
01300 }
01301 
01302 /******************************************************************************
01303 * Mapping operations
01304 ******************************************************************************/
01305 
01306 template<typename Op, typename C, typename V>
01307 polynomial<Unary_return_type(Op,C),V>
01308 unary_map (const polynomial<C,V>& p) {
01309   typedef implementation<vector_linear,V> Vec;
01310   typedef Unary_return_type(Op,C) T;
01311   nat n= N(p);
01312   nat l= aligned_size<T,V> (n);
01313   format<T> fm= unary_map<Op> (CF(p));
01314   T* r= mmx_formatted_new<T> (l, fm);
01315   Vec::template vec_unary<Op> (r, seg (p), n);
01316   return polynomial<T,V> (r, n, l, fm);
01317 }
01318 
01319 template<typename Op, typename C, typename V, typename X>
01320 polynomial<Binary_return_type(Op,C,X),V>
01321 binary_map_scalar (const polynomial<C,V>& p, const X& x) {
01322   typedef implementation<vector_linear,V> Vec;
01323   typedef Binary_return_type(Op,C,X) T;
01324   nat n= N(p);
01325   nat l= aligned_size<T,V> (n);
01326   format<T> fm= binary_map_scalar<Op> (CF(p), x);
01327   T* r= mmx_formatted_new<T> (l, fm);
01328   Vec::template vec_binary_scalar<Op> (r, seg (p), x, n);
01329   return polynomial<T,V> (r, n, l, fm);
01330 }
01331 
01332 template<typename Op, typename C, typename V> Unary_return_type(Op,C)
01333 big (const polynomial<C,V>& v) {
01334   typedef implementation<vector_linear,V> Vec;
01335   return Vec::template vec_unary_big<Op> (seg (v), N(v));
01336 }
01337 
01338 TMPL Polynomial copy (const Polynomial& P) {
01339   return unary_map<id_op> (P); }
01340 TMPL Polynomial duplicate (const Polynomial& P) {
01341   return unary_map<duplicate_op> (P); }
01342 
01343 /******************************************************************************
01344 * Dynamic mappers
01345 ******************************************************************************/
01346 
01347 template<typename S1, typename D> polynomial<D>
01348 map (const function_1<D,Argument(S1) >& fun,
01349      const polynomial<S1>& p1, const format<D>& fm)
01350 {
01351   nat n= N(p1);
01352   nat l= default_aligned_size<D> (n);
01353   D* r= mmx_formatted_new<D> (l, fm);
01354   for (nat i=0; i<n; i++) r[i]= fun (p1[i]);
01355   return polynomial<D> (r, n, l, fm);
01356 }
01357 
01358 template<typename S1, typename D> inline polynomial<D>
01359 map (D (*fun) (const S1&),
01360      const polynomial<S1>& p1, const format<D>& fm) {
01361   return map (function_1<D,Argument(S1) > (fun), p1, fm);
01362 }
01363 
01364 /******************************************************************************
01365 * Floating point related functions
01366 ******************************************************************************/
01367 
01368 TMPL inline bool is_finite (const Polynomial& p) {
01369   return big<and_is_finite_op> (p); }
01370 TMPL inline bool is_nan (const Polynomial& p) {
01371   return big<or_is_nan_op> (p); }
01372 TMPL inline bool is_infinite (const Polynomial& p) {
01373   return !is_nan (p) && big<or_is_infinite_op> (p); }
01374 TMPL inline bool is_fuzz (const Polynomial& p) {
01375   return !is_nan (p) && big<or_is_fuzz_op> (p); }
01376 TMPL inline bool is_reliable (const Polynomial& p) {
01377   return is_reliable (promote (0, CF(p))); }
01378 
01379 TMPL inline Polynomial change_precision (const Polynomial& P, xnat p) {
01380   return binary_map_scalar<change_precision_op> (P, p); }
01381 TMPL inline xnat precision (const Polynomial& p) {
01382   return big<min_precision_op> (p); }
01383 
01384 TMPL inline xint exponent (const Polynomial& p) {
01385   return big<max_exponent_op> (p); }
01386 TMPL inline double magnitude (const Polynomial& p) {
01387   return big<max_magnitude_op> (p); }
01388 
01389 /******************************************************************************
01390 * Complex and ball polynomials
01391 ******************************************************************************/
01392 
01393 TMPL Abs_polynomial abs (const Polynomial& p) { return unary_map<abs_op> (p); }
01394 TMPL Real_polynomial Re (const Polynomial& p) { return unary_map<Re_op> (p); }
01395 TMPL Real_polynomial Im (const Polynomial& p) { return unary_map<Im_op> (p); }
01396 TMPL Polynomial conj (const Polynomial& p) { return unary_map<conj_op> (p); }
01397 
01398 TMPL Center_polynomial center (const Polynomial& p) {
01399   return unary_map<center_op> (p); }
01400 TMPL Radius_polynomial radius (const Polynomial& p) {
01401   return unary_map<radius_op> (p); }
01402 TMPL Center_polynomial lower (const Polynomial& p) {
01403   return unary_map<lower_op> (p); }
01404 TMPL Center_polynomial upper (const Polynomial& p) {
01405   return unary_map<upper_op> (p); }
01406 TMPL inline Polynomial sharpen (const Polynomial& p) {
01407   return unary_map<sharpen_op> (p); }
01408 TMPLK inline Polynomial blur (const Polynomial& p, const K& x) {
01409   return binary_map_scalar<blur_op> (p, x); }
01410 
01411 #undef TMPL_DEF
01412 #undef TMPL
01413 #undef TMPLK
01414 #undef Format
01415 #undef Vector
01416 #undef Polynomial
01417 #undef Polynomial_rep
01418 #undef Abs_polynomial
01419 #undef Real_polynomial
01420 #undef Center_polynomial
01421 #undef Radius_polynomial
01422 } // namespace mmx
01423 #endif // __MMX_POLYNOMIAL_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines