algebramix_doc 0.3
|
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