00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX__POLYNOMIAL_NAIVE__HPP
00014 #define __MMX__POLYNOMIAL_NAIVE__HPP
00015 #include <basix/port.hpp>
00016 #include <basix/vector.hpp>
00017
00018 namespace mmx {
00019 #define TMPL template <typename C>
00020 #define TMPLK template <typename C, typename K>
00021 #define TMPLX template <typename C, typename X>
00022 #define TMPLP template <typename Polynomial>
00023 #define Vector vector<C>
00024 template <typename C, typename V> struct polynomial;
00025
00026
00027
00028
00029
00030 struct polynomial_naive {
00031 typedef vector_naive Vec;
00032 typedef polynomial_naive Naive;
00033 typedef polynomial_naive Positive;
00034 typedef polynomial_naive No_simd;
00035 typedef polynomial_naive No_thread;
00036 typedef polynomial_naive No_scaled;
00037 };
00038
00039 template<typename C>
00040 struct polynomial_variant_helper {
00041 typedef polynomial_naive PV;
00042 };
00043
00044
00045
00046
00047
00048 struct polynomial_defaults {};
00049
00050 template<typename V>
00051 struct implementation<polynomial_defaults,V,polynomial_naive> {
00052 template<typename P>
00053 class global_variables {
00054 static inline generic& dyn_name () {
00055 static generic name = "x";
00056 return name; }
00057 public:
00058 static inline void set_variable_name (const generic& x) { dyn_name () = x; }
00059 static inline generic get_variable_name () { return dyn_name (); }
00060 };
00061
00062 };
00063
00064
00065
00066
00067
00068 template<typename V>
00069 struct implementation<vector_defaults,V,polynomial_naive>:
00070 public implementation<vector_defaults,V,typename V::Vec> {};
00071
00072 template<typename V>
00073 struct implementation<vector_allocate,V,polynomial_naive>:
00074 public implementation<vector_allocate,V,typename V::Vec> {};
00075
00076 template<typename V>
00077 struct implementation<vector_abstractions,V,polynomial_naive>:
00078 public implementation<vector_abstractions,V,typename V::Vec> {};
00079
00080 template<typename V>
00081 struct implementation<vector_abstractions_stride,V,polynomial_naive>:
00082 public implementation<vector_abstractions_stride,V,typename V::Vec> {};
00083
00084 template<typename V>
00085 struct implementation<vector_linear,V,polynomial_naive>:
00086 public implementation<vector_linear,V,typename V::Vec> {};
00087
00088
00089
00090
00091
00092 struct polynomial_vectorial {};
00093
00094 template<typename V>
00095 struct implementation<polynomial_vectorial,V,polynomial_naive>:
00096 public implementation<polynomial_defaults,V>
00097 {
00098 typedef implementation<vector_linear,V> Vec;
00099
00100 TMPLX static inline void set (C* dest, const X& c, nat n) {
00101 Vec::set (dest, c, n); }
00102 TMPL static inline void clear (C* dest, nat n) {
00103 Vec::clear (dest, n); }
00104 TMPL static inline void copy (C* dest, const C* s, nat n) {
00105 Vec::copy (dest, s, n); }
00106 TMPLX static inline void cast (C* dest, const X* s, nat n) {
00107 Vec::cast (dest, s, n); }
00108 TMPL static inline void reverse (C* dest, const C* s, nat n) {
00109 Vec::vec_reverse (dest, s, n); }
00110 TMPL static inline void neg (C* dest, const C* s, nat n) {
00111 Vec::neg (dest, s, n); }
00112 TMPL static inline void neg (C* dest, nat n) {
00113 Vec::neg (dest, n); }
00114 TMPL static inline void add (C* dest, const C* s1, const C* s2, nat n) {
00115 Vec::add (dest, s1, s2, n); }
00116 TMPL static inline void add (C* dest, const C* s, nat n) {
00117 Vec::add (dest, s, n); }
00118 TMPL static inline void sub (C* dest, const C* s1, const C* s2, nat n) {
00119 Vec::sub (dest, s1, s2, n); }
00120 TMPL static inline void sub (C* dest, const C* s, nat n) {
00121 Vec::sub (dest, s, n); }
00122 TMPL static inline void mul_add (C* dest, const C* s1, const C* s2, nat n) {
00123 Vec::mul_add (dest, s1, s2, n); }
00124 TMPLX static inline void mul_add (C* dest, const C* s, const X& c, nat n) {
00125 Vec::mul_add (dest, s, c, n); }
00126 TMPLX static inline void mul_add (C* dest, const X& c, const C* s, nat n) {
00127 Vec::mul_add (dest, c, s, n); }
00128 TMPL static inline void mul_sc (C* dest, const C* s, const C& c, nat n) {
00129 Vec::mul (dest, s, c, n); }
00130 TMPL static inline void mul_sc (C* dest, const C& c, nat n) {
00131 Vec::mul (dest, c, n); }
00132 TMPL static inline void div_sc (C* dest, const C* s, const C& c, nat n) {
00133 Vec::div (dest, s, c, n); }
00134 TMPL static inline void div_sc (C* dest, const C& c, nat n) {
00135 Vec::div (dest, c, n); }
00136 TMPL static inline void quo_sc (C* dest, const C* s, const C& c, nat n) {
00137 Vec::quo (dest, s, c, n); }
00138 TMPL static inline void quo_sc (C* dest, const C& c, nat n) {
00139 Vec::quo (dest, c, n); }
00140 TMPL static inline void rem_sc (C* dest, const C* s, const C& c, nat n) {
00141 Vec::rem (dest, s, c, n); }
00142 TMPL static inline void rem_sc (C* dest, const C& c, nat n) {
00143 Vec::rem (dest, c, n); }
00144 TMPL static inline bool equal (const C* s1, const C* s2, nat n) {
00145 return Vec::equal (s1, s2, n); }
00146 TMPL static inline bool equal (const C* s, const C& c, nat n) {
00147 return Vec::equal (s, c, n); }
00148 TMPL static inline bool exact_eq (const C* s1, const C* s2, nat n) {
00149 return Vec::exact_eq (s1, s2, n); }
00150 TMPL static inline bool exact_eq (const C* s, const C& c, nat n) {
00151 return Vec::exact_eq (s, c, n); }
00152 TMPL static inline void trim (const C* s, nat& n) {
00153 while (n > 0 && s[n-1] == 0) n--; }
00154
00155 };
00156
00157
00158
00159
00160
00161 struct polynomial_linear {};
00162
00163 template<typename V>
00164 struct implementation<polynomial_linear,V,polynomial_naive>:
00165 public implementation<polynomial_vectorial,V>
00166 {
00167 typedef implementation<vector_linear,V> Vec;
00168 typedef implementation<polynomial_vectorial,V> Pol;
00169
00170 TMPL static inline int
00171 sign (C* s, nat n) {
00172 while (n != 0) {
00173 int sgn= sign (*s);
00174 if (sgn != 0) return sgn;
00175 s++; n--;
00176 }
00177 return 0;
00178 }
00179
00180 TMPL static inline int
00181 cmp (const C* s1, const C* s2, nat n) {
00182 while (n != 0) {
00183 int sgn= compare (*s1, *s2);
00184 if (sgn != 0) return sgn;
00185 s1++; s2++; n--;
00186 }
00187 return 0;
00188 }
00189
00190 TMPL static inline void
00191 derive (C* dest, nat n) {
00192 for (nat i=1; i<n; i++)
00193 dest[i-1]= promote ((int) i, dest[i]) * dest[i];
00194 }
00195
00196 TMPL static inline void
00197 derive (C* dest, nat n, nat order) {
00198 if (order == 0) return;
00199 for (nat i=order; i<n; i++) {
00200 dest[i-order]= promote (i, dest[i]) * dest[i];
00201 for (nat j=1; j<order; j++)
00202 dest[i-order] *= promote ((int) (i-j), dest[i]);
00203 }
00204 }
00205
00206 TMPL static inline void
00207 derive (C* dest, const C* s, nat n) {
00208 for (nat i=1; i<n; i++)
00209 dest[i-1]= promote ((int) i, s[i]) * s[i];
00210 }
00211
00212 TMPL static inline void
00213 derive (C* dest, const C* s, nat n, nat order) {
00214 for (nat i=order; i<n; i++) {
00215 dest[i-order]= s[i];
00216 for (nat j=0; j<order; j++)
00217 dest[i-order] *= promote ((int) (i-j), s[i]);
00218 }
00219 }
00220
00221 TMPL static inline void
00222 xderive (C* dest, nat n) {
00223 for (nat i=0; i<n; i++)
00224 dest[i]= promote ((int) i, dest[i]) * dest[i];
00225 }
00226
00227 TMPL static inline void
00228 xderive (C* dest, const C* s, nat n) {
00229 for (nat i=0; i<n; i++)
00230 dest[i]= promote ((int) i, s[i]) * s[i];
00231 }
00232
00233 TMPL static inline void
00234 integrate (C* dest, const C* s, nat n) {
00235 dest[0]= promote (0, dest[0]);
00236 for (nat i=0; i<n; i++)
00237 dest[i+1]= s[i] / promote ((int) (i+1), s[i]);
00238 }
00239
00240 TMPLK static inline void
00241 q_difference (C* dest, const C* s, const K& q, nat n) {
00242 K p= promote (1, q);
00243 while (n != 0) {
00244 *dest= p * (*s);
00245 dest++; s++; n--; p *= q;
00246 }
00247 }
00248
00249 TMPL static inline void
00250 dilate (C* dest, const C* s, nat p, nat n) {
00251 Vec::clear (dest, (n-1)*p + 1);
00252 while (n != 0) {
00253 *dest= *s;
00254 dest += p; s++; n--;
00255 }
00256 }
00257
00258 TMPL inline static C
00259 big_gcd (const C* s, nat n) {
00260 return Vec::template vec_unary_big<gcd_op, C> (s, n);
00261 }
00262
00263 };
00264
00265
00266
00267
00268
00269 struct polynomial_multiply {};
00270
00271 template<typename V>
00272 struct implementation<polynomial_multiply,V,polynomial_naive>:
00273 public implementation<polynomial_linear,V>
00274 {
00275 typedef implementation<polynomial_linear,V> Pol;
00276 typedef implementation<vector_linear,V> Vec;
00277
00278 TMPLK static void
00279 mul (C* dest, const C* s1, const K* s2, nat n1, nat n2) {
00280 if (n1+n2>0)
00281 Pol::clear (dest, n1+n2-1);
00282 while (n2 != 0) {
00283 Pol::mul_add (dest, s1, *s2, n1);
00284 dest++; s2++; n2--;
00285 }
00286 }
00287
00288 TMPL static void
00289 square (C* dest, const C* s, nat n) {
00290 if (n>0)
00291 Pol::clear (dest, n+n-1);
00292 else return;
00293 for (nat i=0; i<n-1; i++)
00294 Pol::mul_add (dest+i+i+1, s+i+1, s[i], n-i-1);
00295 for (nat i=1; i<n+n-2; i++)
00296 dest[i] = dest[i] + dest[i];
00297 for (nat i=0; i<n; i++)
00298 dest[i+i] += s[i] * s[i];
00299 }
00300
00301 TMPL static void
00302 tmul (C* dest, const C* s1, const C* s2, nat n1, nat n2) {
00303
00304
00305 Pol::clear (dest, n2);
00306 while (n1 != 0) {
00307 Pol::mul_add (dest, *s1, s2, n2);
00308 s1++; s2++; n1--;
00309 }
00310 }
00311
00312 };
00313
00314
00315
00316
00317
00318 struct polynomial_graeffe {};
00319
00320 template<typename V>
00321 struct implementation<polynomial_graeffe,V,polynomial_naive>:
00322 public implementation<polynomial_multiply,V>
00323 {
00324 typedef implementation<polynomial_multiply,V> Pol;
00325 typedef implementation<vector_linear,V> Vec;
00326
00327 TMPL static void
00328 graeffe (C* dest, const C* s, nat n) {
00329 if (n <= 1) return;
00330 nat l1= (n+1) >> 1, l2= n >> 1;
00331 nat l= aligned_size<C,V> (n << 1);
00332 C* c1 = mmx_new<C> (l);
00333 C* c2 = c1 + l1;
00334 C* aux= c2 + l2;
00335 if (n>0) dest[n-1]= C(0);
00336 Vec::half_copy (c1, s, l1);
00337 Vec::half_copy (c2, s+1, l2);
00338 Pol::square (dest, c1, l1);
00339 Pol::square (aux , c2, l2);
00340 Pol::sub (dest+1, aux, (l2<<1) - 1);
00341 mmx_delete<C> (c1, l);
00342 }
00343
00344 };
00345
00346
00347
00348
00349
00350 struct polynomial_divide {};
00351
00352 template<typename V>
00353 struct implementation<polynomial_divide,V,polynomial_naive>:
00354 public implementation<polynomial_multiply,V>
00355 {
00356 typedef implementation<polynomial_multiply,V> Pol;
00357 typedef implementation<vector_linear,V> Vec;
00358
00359 TMPL static void
00360 quo_rem (C* dest, C* s1, const C* s2, nat n1, nat n2) {
00361
00362
00363
00364 while (n1 >= n2 && n1 != 0) {
00365 int d= n1-n2;
00366 C q= quo (s1[n1-1], s2[n2-1]);
00367 dest[d]= q;
00368 for (nat i=0; i<n2; i++)
00369 s1[i+d] -= q * s2[i];
00370 n1--;
00371 }
00372 }
00373
00374 TMPL static void
00375 tquo_rem (C* dest, const C* s1, const C* s2, nat n1, nat n2) {
00376
00377
00378
00379
00380 C c = s2[n2-1];
00381 Pol::copy (dest, s1, n2-1);
00382 s1 += n2-1;
00383 for (nat i = n2-1; i < n1; i++, dest++, s1++)
00384 dest[n2-1] = quo (*s1 - Vec::inn_prod (dest, s2, n2-1), c);
00385 }
00386
00387 TMPL static void
00388 pquo_rem (C* dest, C* s1, const C* s2, nat n1, nat n2) {
00389
00390
00391
00392
00393
00394 nat l= n1 - n2 + 1;
00395 while (n1 >= n2 && n1 != 0) {
00396 int d= n1-n2;
00397 dest[d]= s1[n1-1];
00398 for (nat i=0; i<n1-1; i++)
00399 s1[i]*= s2[n2-1];
00400 for (nat i=0; i<n2-1; i++)
00401 s1[i+d]-= s1[n1-1] * s2[i];
00402 s1[n1-1]=0;
00403 n1--;
00404 }
00405 C c= s2[n2-1];
00406 for (nat i = 1; i < l; i++) {
00407 dest[i] *= c;
00408 c *= s2[n2-1];
00409 }
00410 }
00411
00412 TMPL static void
00413 invert_hi (C* dest, const C* src, nat n) {
00414 if (n == 1) *dest= C(1) / *src;
00415 else {
00416 nat h= (n+1) >> 1;
00417 nat l= n - h;
00418 invert_hi (dest + l, src + l, h);
00419 nat buf_size= aligned_size<C,V> (n << 1);
00420 C* buf= mmx_new<C> (buf_size);
00421 C* aux= buf + l;
00422 Pol::mul (aux, src, dest + l, n, h);
00423
00424 Pol::mul (buf, dest + h, aux + h - 1, l, l);
00425
00426 Pol::neg (dest, buf + l - 1, l);
00427 mmx_delete<C> (buf, buf_size);
00428 }
00429 }
00430
00431 };
00432
00433
00434
00435
00436
00437 struct polynomial_exact_divide {};
00438
00439 template<typename V>
00440 struct polynomial_exact_divide_threshold {};
00441
00442 template<typename V>
00443 struct implementation<polynomial_exact_divide,V,polynomial_naive>:
00444 public implementation<polynomial_divide,V>
00445 {
00446 typedef implementation<polynomial_divide,V> Pol;
00447 typedef implementation<vector_linear,V> Vec;
00448
00449 TMPL static void
00450 div (C* dest, const C* s1, const C* s2, nat n1, nat n2) {
00451
00452
00453
00454 nat l1= aligned_size<C,V> (n1);
00455 C* r= mmx_new<C> (l1);
00456 Vec::copy (r, s1, n1);
00457 Pol::quo_rem (dest, r, s2, n1, n2);
00458 if (! Pol::equal (r, C(0), n1)) {
00459 mmx_delete<C> (r, l1);
00460 ERROR ("division must be exact");
00461 }
00462 mmx_delete<C> (r, l1);
00463 }
00464
00465 };
00466
00467
00468
00469
00470
00471 struct polynomial_compose {};
00472
00473 template<typename V>
00474 struct implementation<polynomial_compose,V,polynomial_naive>:
00475
00476 public implementation<polynomial_multiply,V>
00477 {
00478 typedef implementation<polynomial_multiply,V> Pol;
00479
00480 TMPLK static void
00481 compose (C* dest, K* p, const C* s1, const K* s2, nat n1, nat n2) {
00482
00483 if (n1 == 1) {
00484 *dest= *s1;
00485 Pol::copy (p, s2, n2);
00486 }
00487 else {
00488 nat d2= n2 - 1;
00489 nat h1= n1 >> 1, h2= n1 - h1;
00490 nat l1= (h1-1) * d2 + 1, l2= (h2-1) * d2 + 1;
00491 nat k1= l1 + d2, k2= l2 + d2;
00492 nat alloc_c1= aligned_size<C,V> (l1 + l2);
00493 C* c1= mmx_new<C> (alloc_c1);
00494 C* c2= c1 + l1;
00495 nat alloc_p1= aligned_size<K,V> (k1 + k2);
00496 C* p1= mmx_new<K> (alloc_p1);
00497 K* p2= p1 + k1;
00498 compose (c1, p1, s1, s2, h1, n2);
00499 compose (c2, p2, s1+h1, s2, h2, n2);
00500 Pol::mul (dest, c2, p1, l2, k1);
00501 Pol::add (dest, c1, l1);
00502 Pol::mul (p, p1, p2, k1, k2);
00503 mmx_delete<K> (p1, alloc_p1);
00504 mmx_delete<C> (c1, alloc_c1);
00505 }
00506 }
00507
00508 TMPLK static void
00509 compose (C* dest, const C* s1, const K* s2, nat n1, nat n2) {
00510 ASSERT (n1 > 0 && n2 > 0, "composition of empty segments");
00511 if (n1 == 1) *dest= *s1;
00512 else {
00513 nat d2= n2 - 1;
00514 nat h1= n1 >> 1, h2= n1 - h1;
00515 nat l1= (h1-1) * d2 + 1, l2= (h2-1) * d2 + 1;
00516 nat k1= l1 + d2;
00517 nat alloc_c1= aligned_size<C,V> (l1 + l2);
00518 C* c1= mmx_new<C> (alloc_c1);
00519 C* c2= c1 + l1;
00520 nat alloc_p1= aligned_size<K,V> (k1);
00521 K* p1= mmx_new<K> (alloc_p1);
00522 compose (c1, p1, s1, s2, h1, n2);
00523 compose (c2, s1+h1, s2, h2, n2);
00524 Pol::mul (dest, c2, p1, l2, k1);
00525 Pol::add (dest, c1, l1);
00526 mmx_delete<K> (p1, alloc_p1);
00527 mmx_delete<C> (c1, alloc_c1);
00528 }
00529 }
00530
00531 TMPLK static void
00532 shift (C* dest, const C* s, const K& sh, nat n) {
00533 if (n <= 1 || sh == 0) Pol::copy (dest, s, n);
00534 else {
00535 K q[2]; q[0]= sh; q[1]= promote (1, sh);
00536 compose (dest, s, q, n, 2);
00537 }
00538 }
00539
00540 };
00541
00542
00543
00544
00545
00546 struct polynomial_euclidean {};
00547
00548 template<typename V>
00549 struct implementation<polynomial_euclidean,V,polynomial_naive>:
00550 public implementation<polynomial_divide,V>
00551 {
00552 typedef implementation<polynomial_divide,V> Pol;
00553 typedef implementation<vector_linear,V> Vec;
00554
00555 private:
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 TMPL static void
00569 euclidean_sequence (C*& d1, C*& d2, nat& n1 , nat& n2,
00570 C*& u1, C*& u2, nat& nu1, nat& nu2,
00571 C*& v1, C*& v2, nat& nv1, nat& nv2,
00572 nat* n, C* rho, C* q, C** r, C** co1, C** co2,
00573 nat k) {
00574
00575
00576
00577
00578
00579 VERIFY (n1 >= n2, "bug");
00580 VERIFY (n1 > k, "bug");
00581 if (n != NULL) Vec::clear (n, n2);
00582 C c1= invert (d1[n1-1]), c2= invert (d2[n2-1]);
00583 Vec::mul (d1, c1, n1); Vec::mul (d2, c2, n2);
00584 if (rho != NULL) Pol::clear (rho, n2);
00585 if (u1 != NULL) {
00586 VERIFY (v1 != NULL, "bug");
00587 Pol::clear (u1, n2); u1[0]= c1; nu1= 1;
00588 Pol::clear (v1, n2); nv1= 0; }
00589 if (u2 != NULL) {
00590 VERIFY (v2 != NULL, "bug");
00591 Pol::clear (u2, n1); nu2= 0;
00592 Pol::clear (v2, n1); v2[0]= c2; nv2= 1; }
00593 nat i= 0;
00594 while (n2 > k)
00595 if (n1 >= n2) {
00596 C m= - d1[n1-1]; nat s= n1-n2;
00597 if (q != NULL) q[n1-1]= m;
00598 Vec::mul_add (d1 + s, m, d2, n2); Pol::trim (d1, n1);
00599 if (u1 != NULL && nv1 != 0) {
00600 Vec::mul_add (u1 + s, m, v1, nv1);
00601 nu1 = max (nu1, nv1 + s); Pol::trim (u1, nu1);
00602 }
00603 if (u2 != NULL && nv2 != 0 ) {
00604 Vec::mul_add (u2 + s, m, v2, nv2);
00605 nu2 = max (nu2, nv2 + s); Pol::trim (u2, nu2);
00606 }
00607 }
00608 else {
00609 if (n != NULL) n[i]= n1; i++;
00610 if (rho != NULL)
00611 rho[n1]= rho[n2-1]= n1 == 0 ? promote (1, c1) : d1[n1-1];
00612 c1= invert (n1 == 0 ? promote (1, c1) : d1[n1-1]);
00613 Vec::mul (d1, c1, n1);
00614 if (u1 != NULL) Vec::mul (u1, c1, nu1);
00615 if (u2 != NULL) Vec::mul (u2, c1, nu2);
00616 if (r != NULL && r[n1] != NULL)
00617 Pol::copy (r[n1], d1, n1);
00618 if (n1 + 1 != n2 && r != NULL && r[n2-1] != NULL)
00619 Pol::copy (r[n2-1], d1, n1);
00620 if (co1 != NULL && co1[n1] != NULL)
00621 Pol::copy (co1[n1], u1, nu1);
00622 if (n1 + 1 != n2 && co1 != NULL && co1[n2-1] != NULL)
00623 Pol::copy (co1[n2-1], u1, nu1);
00624 if (co2 != NULL && co2[n1] != NULL)
00625 Pol::copy (co2[n1], u2, nu2);
00626 if (n1 + 1 != n2 && co2 != NULL && co2[n2-1] != NULL)
00627 Pol::copy (co2[n2-1], u2, nu2);
00628 swap (d1, d2); swap (n1 , n2 );
00629 swap (u1, v1); swap (nu1, nv1);
00630 swap (u2, v2); swap (nu2, nv2);
00631 }
00632 }
00633
00634 public:
00635
00636 TMPL static void
00637 euclidean_sequence (const C* s1, const C* s2, nat n1, nat n2,
00638 C* d1, C* d2, nat& m1 , nat& m2,
00639 C* u1, C* u2, nat& nu1, nat& nu2,
00640 C* v1, C* v2, nat& nv1, nat& nv2,
00641 nat* n, C* rho, C* q, C** r, C** co1, C** co2, nat k= 0) {
00642
00643 VERIFY (n1 >= n2, "bug");
00644 nat l1= aligned_size<C,V> (n1), l2= aligned_size<C,V> (n2);
00645 nat l= max (l1, l2);
00646 C* t1= mmx_new<C> (l), * t2= mmx_new<C> (l);
00647 Pol::copy (t1, s1, n1); Pol::copy (t2, s2, n2);
00648 bool opt_co1= ! (u1 == NULL && v1 == NULL && co1 == NULL);
00649 bool opt_co2= ! (u2 == NULL && v2 == NULL && co2 == NULL);
00650 C* uu1= NULL, * uu2= NULL, * vv1= NULL, * vv2= NULL;
00651 if (opt_co1) { uu1= mmx_new<C> (l2); vv1= mmx_new<C> (l2); }
00652 if (opt_co2) { uu2= mmx_new<C> (l1); vv2= mmx_new<C> (l1); }
00653 nat mm1= n1, mm2= n2, mu1, mu2, mv1, mv2;
00654
00655 if (d1 == NULL && d2 == NULL && !opt_co1 && !opt_co2) {
00656 while (k < n2 &&
00657 (r == NULL || r [k] == NULL) &&
00658 (co1 == NULL || co1[k] == NULL) &&
00659 (co2 == NULL || co2[k] == NULL)) k++;
00660 }
00661 euclidean_sequence (t1 , t2 , mm1, mm2,
00662 uu1, uu2, mu1, mu2,
00663 vv1, vv2, mv1, mv2,
00664 n, rho, q, r, co1, co2, k);
00665 if (d1 != NULL) { Pol::copy (d1, t1, mm1); m1= mm1; }
00666 if (d2 != NULL) { Pol::copy (d2, t2, mm2); m2= mm2; }
00667 mmx_delete<C> (t1, l); mmx_delete<C> (t2, l);
00668 if (u1 != NULL) { Pol::copy (u1, uu1, mu1); nu1= mu1; }
00669 if (u2 != NULL) { Pol::copy (u2, uu2, mu2); nu2= mu2; }
00670 if (v1 != NULL) { Pol::copy (v1, vv1, mv1); nv1= mv1; }
00671 if (v2 != NULL) { Pol::copy (v2, vv2, mv2); nv2= mv2; }
00672 if (opt_co1) { mmx_delete<C> (uu1, l2); mmx_delete<C> (vv1, l2); }
00673 if (opt_co2) { mmx_delete<C> (uu2, l1); mmx_delete<C> (vv2, l1); }
00674 }
00675
00676 TMPL static void
00677 gcd (C* g, nat& n, const C* s1, const C* s2, nat n1, nat n2,
00678 C* u1, C* u2, nat& nu1, nat& nu2) {
00679 VERIFY (n1>0 && n2>0 && s1[n1-1] != 0 && s2[n2-1] != 0,
00680 "invalid hypothesis for gcd computation");
00681 if (n1 < n2) return gcd (g, n, s2, s1, n2, n1, u2, u1, nu2, nu1);
00682 n= max (n1, n2); nat m= min (n1, n2);
00683 nat l1= aligned_size<C,V> (n1), l2= aligned_size<C,V> (n2);
00684 nat l= aligned_size<C,V> (n);
00685 C* d1= mmx_new<C> (l), * d2= mmx_new<C> (l);
00686 C* v1= u1 == NULL ? NULL : mmx_new<C> (l2);
00687 C* v2= u2 == NULL ? NULL : mmx_new<C> (l1);
00688 nat m1=0, m2=0, nv1=0, nv2=0;
00689 euclidean_sequence (s1, s2, n1, n2,
00690 d1, d2, m1, m2,
00691 u1, u2, nu1, nu2,
00692 v1, v2, nv1, nv2,
00693 (nat*)NULL, (C*)NULL, (C*)NULL,
00694 (C**)NULL, (C**)NULL, (C**)NULL);
00695 Pol::copy (g, d1, m1); Pol::clear (g + m1, m - m1); n= m1;
00696 mmx_delete<C> (d1, l); mmx_delete<C> (d2, l);
00697 if (u1 != NULL) mmx_delete<C> (v1, l2);
00698 if (u2 != NULL) mmx_delete<C> (v2, l1);
00699 }
00700
00701 TMPL static void
00702 reconstruct (C* r, C* t, const C* s, nat m, const C* p, nat n, nat k) {
00703
00704
00705 VERIFY (n > k && n > 0 && s[m-1]!= 0 && m <= n,
00706 "invalid hypothesis for reconstruction");
00707 nat n1= n+1, n2= m, l1= aligned_size<C,V> (n1);
00708 C* s1= mmx_new<C> (l1);
00709 Pol::copy (s1, p, n1);
00710 C* d1= NULL, * d2= mmx_new<C> (l1);
00711 C* u1= NULL, * u2= mmx_new<C> (l1);
00712 C* v1= NULL, * v2= mmx_new<C> (l1);
00713 nat nu1=0, nu2=0, nv1=0, nv2=0, nd1=0, nd2=0;
00714 euclidean_sequence (s1, s , n1, n2,
00715 d1, d2, nd1, nd2,
00716 u1, u2, nu1, nu2,
00717 v1, v2, nv1, nv2,
00718 (nat*)NULL, (C*)NULL, (C*)NULL,
00719 (C**)NULL, (C**)NULL, (C**)NULL, k);
00720 VERIFY (nd2 <= k, "bug");
00721 VERIFY (nv2 <= n-k+1, "bug");
00722 Pol::copy (r, d2, nd2); Pol::clear (r + nd2, k - nd2);
00723 Pol::copy (t, v2, nv2); Pol::clear (t + nv2, n-k+1 - nv2);
00724 mmx_delete<C> (d2, l1);
00725 mmx_delete<C> (u2, l1); mmx_delete<C> (v2, l1);
00726 }
00727
00728 };
00729
00730
00731
00732
00733
00734 struct polynomial_gcd {};
00735
00736 template<typename V>
00737 struct implementation<polynomial_gcd,V,polynomial_naive>:
00738 public implementation<polynomial_divide,V>
00739 {
00740 typedef implementation<polynomial_euclidean,V> Pol;
00741 typedef implementation<vector_linear,V> Vec;
00742
00743 #define C typename scalar_type_helper<Polynomial >::val
00744
00745 TMPLP static Polynomial
00746 gcd (const Polynomial& P1, const Polynomial& P2,
00747 Polynomial& U1, Polynomial& U2) {
00748 bool opt1= U1 != 0, opt2= U2 != 0;
00749 nat n1= N(P1), n2= N(P2);
00750 C c1= P1[n1-1], c2= P2[n2-1];
00751 if (n1 == 0 && n2 == 0) {
00752 if (opt1) set_as (U1, 0);
00753 if (opt2) set_as (U2, 0);
00754 return promote (0, P1); }
00755 if (n2 == 0) {
00756 if (opt1) U1= promote (1, c1) / c1;
00757 if (opt2) set_as (U2, 0);
00758 return P1 / c1; }
00759 if (n1 == 0) {
00760 if (opt1) set_as (U1, 0);
00761 if (opt2) U2= promote (1, c2) / c2;
00762 return P2 / c2; }
00763 nat m = min (n1, n2), nu1, nu2;
00764 nat l = aligned_size<C,V> (m);
00765 nat l1= aligned_size<C,V> (n1), l2= aligned_size<C,V> (n2);
00766 C* tmp= mmx_new<C> (l);
00767 C* u1= opt1 ? mmx_new<C> (l2) : NULL;
00768 C* u2= opt2 ? mmx_new<C> (l1) : NULL;
00769 Pol::gcd (tmp, m, seg (P1), seg (P2), n1, n2, u1, u2, nu1, nu2);
00770 if (opt1) U1= Polynomial (u1, nu1, l2, CF(P1));
00771 if (opt2) U2= Polynomial (u2, nu2, l1, CF(P1));
00772 nat lg = aligned_size<C,V> (m);
00773 C* g= mmx_new<C> (lg);
00774 Pol::copy (g, tmp, m);
00775 mmx_delete<C> (tmp, l);
00776 return Polynomial (g, m, lg, CF(P1)); }
00777
00778 TMPLP static Polynomial
00779 gcd (const Polynomial& P1, const Polynomial& P2) {
00780 Polynomial U1= promote (0, P1), U2= promote (0, P2);
00781 return gcd (P1, P2, U1, U2); }
00782
00783 TMPLP static inline Polynomial
00784 lcm (const Polynomial& P1, const Polynomial& P2) {
00785 Polynomial U1= promote (0, P1), U2= promote (0, P1);
00786 return
00787 (P1 == 0 && P2 == 0) ?
00788 promote (0, P1) :
00789 P1 * (P2 / gcd (P1, P2, U1, U2)); }
00790
00791 TMPLP static Polynomial
00792 invert_mod (const Polynomial& P, const Polynomial& Q) {
00793
00794 Polynomial inv_P= C(1), dummy= C(0);
00795 Polynomial G= gcd (P, Q, inv_P, dummy);
00796 if (deg (G) != 0 || G[0] == 0) inv_P= 0;
00797 return inv_P / G[0]; }
00798
00799 TMPLP static void
00800 reconstruct (const Polynomial& P, const Polynomial& Q, nat k,
00801 Polynomial& Num, Polynomial& Den) {
00802
00803
00804
00805 VERIFY (deg (Q) >= 0, "invalid argument");
00806 nat n= deg (Q);
00807 VERIFY (k <= n && k > 0, "invalid argument");
00808 nat m= N(P);
00809 if (n == 0 || m == 0) { Num= 0; Den= 1; return; }
00810 if (k == n) { Num= P; Den= 1; return; }
00811 nat lnum = aligned_size<C,V> (k), lden= aligned_size<C,V> (n-k+1);
00812 C* num= mmx_new<C> (lnum), * den= mmx_new<C> (lden);
00813 Pol::reconstruct (num, den, seg (P), m, seg (Q), n, k);
00814 Num= Polynomial (num, k, lnum, CF(P));
00815 Den= Polynomial (den, n-k+1, lden, CF(P)); }
00816
00817 #undef C
00818 };
00819
00820
00821
00822
00823
00824 struct polynomial_subresultant_base {};
00825 struct polynomial_subresultant {};
00826
00827 template<typename V>
00828 struct implementation<polynomial_subresultant_base,V,polynomial_naive>:
00829 public implementation<polynomial_divide,V>
00830 {
00831 typedef implementation<polynomial_euclidean,V> Pol;
00832 typedef implementation<vector_linear,V> Vec;
00833
00834 TMPLP static void
00835 subresultant_sequence (const Polynomial& f, const Polynomial& g,
00836 vector<Polynomial>& res,
00837 vector<Polynomial>& cof, vector<Polynomial>& cog,
00838 Polynomial& d1, Polynomial& u1, Polynomial& v1,
00839 Polynomial& d2, Polynomial& u2, Polynomial& v2,
00840 nat dest_deg= 0) {
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851 typedef typename scalar_type_helper<Polynomial>::val C;
00852 nat n1= N(f), n2= N(g);
00853 VERIFY (n1 >= n2, "bug");
00854 if (n2 <= 1) return;
00855 nat l1= aligned_size<C,V> (n1), l2= aligned_size<C,V> (n2);
00856 vector<C> rho (C(0), n2); C** sub= mmx_new<C*> (n2, (C*) NULL);
00857 vector<nat> ns ((nat) 0, n2);
00858 C* dd1= (d1 == 0 && u1 == 0 && v1 == 0) ? NULL : mmx_new<C> (l1);
00859 C* dd2= (d2 == 0 && u2 == 0 && v2 == 0) ? NULL : mmx_new<C> (l1);
00860 C* uu1= u1 == 0 ? NULL : mmx_new<C> (l2);
00861 C* vv1= v1 == 0 ? NULL : mmx_new<C> (l1);
00862 C* uu2= u2 == 0 ? NULL : mmx_new<C> (l2);
00863 C* vv2= v2 == 0 ? NULL : mmx_new<C> (l1);
00864 nat nd1= 0, nd2= 0, nu1= 0, nu2= 0, nv1= 0, nv2= 0;
00865 C** co1= mmx_new<C*> (n2, (C*) NULL); C** co2= mmx_new<C*> (n2, (C*) NULL);
00866 for (nat i = 1; i < n2; i++) {
00867 if (i-1 < N(res) && res[i-1] != 0)
00868 sub[i]= mmx_new<C> (aligned_size<C,V> (i), C(0));
00869 if (i-1 < N(cof) && cof[i-1] != 0)
00870 co1[i]= mmx_new<C> (l2, C(0));
00871 if (i-1 < N(cog) && cog[i-1] != 0)
00872 co2[i]= mmx_new<C> (l1, C(0));
00873 }
00874 Pol::euclidean_sequence (seg(f), seg(g), n1, n2,
00875 dd1, dd2, nd1, nd2,
00876 uu1, uu2, nu1, nu2,
00877 vv1, vv2, nv1, nv2,
00878 seg (ns), seg (rho), (C*) NULL,
00879 sub, co1, co2, dest_deg);
00880 for (nat i = 1; i < n2; i++) {
00881 if (i-1 < N(res) && res[i-1] != 0)
00882 res[i-1]= Polynomial (sub[i], i, aligned_size<C,V> (i), CF(f));
00883 if (i-1 < N(cof) && cof[i-1] != 0)
00884 cof[i-1]= Polynomial (co1[i], n2, l2, CF(f));
00885 if (i-1 < N(cog) && cog[i-1] != 0)
00886 cog[i-1]= Polynomial (co2[i], n1, l1, CF(f));
00887 }
00888 if (d1 != 0) d1= Polynomial (dd1, nd1, l1, CF(f));
00889 if (d2 != 0) d2= Polynomial (dd2, nd2, l1, CF(f));
00890 if (u1 != 0) u1= Polynomial (uu1, nu1, l2, CF(f));
00891 if (u2 != 0) u2= Polynomial (uu2, nu2, l2, CF(f));
00892 if (v1 != 0) v1= Polynomial (vv1, nv1, l1, CF(f));
00893 if (v2 != 0) v2= Polynomial (vv2, nv2, l1, CF(f));
00894 mmx_delete<C*> (sub, n2);
00895 mmx_delete<C*> (co1, n2); mmx_delete<C*> (co2, n2);
00896 vector<C> c (promote (0, CF(f)), n2);
00897
00898
00899 nat n= n2 - 1, m= ns[0] - 1, i= 0;
00900 C c_n= g[n], c_n_1= f[n1-1] * binpow (g[n], n1 - n2 + 1) * rho[ns[0]];
00901 C d= binpow (g[n], n1 - n2);
00902 c[n-1]= c_n_1;
00903 while (m + 1 > 0) {
00904 C t0= binpow (c_n_1, n-m-1), t1= binpow (d, n-m-1);
00905 c[m]= (t0 / t1) * c_n_1;
00906 if (m == 0) break;
00907 t0 *= square_op::op (c_n_1); t1 *= ((n-m) & 1) ? c_n * d : -c_n * d;
00908 c[m-1]= (t0 * c_n * rho[m]) / t1;
00909 n= m; c_n= c[m]; d= c[m]; c_n_1= c[m-1]; i++; m= ns[i] - 1;
00910 }
00911 for (nat i= 0; i < N(res); i++) res[i] *= c[i];
00912 for (nat i= 0; i < N(cof); i++) cof[i] *= c[i];
00913 for (nat i= 0; i < N(cog); i++) cog[i] *= c[i];
00914 d= (nd1 > n2 || nd1 == 0) ? promote (0, d) : c[nd1 - 1];
00915 d1 *= d; u1 *= d; v1 *= d;
00916 d= (nd1 > n2 || nd1 < 2) ? promote (1, d) : c[nd1 - 2];
00917 d2 *= d; u2 *= d; v2 *= d; }
00918
00919 };
00920
00921 template<typename V>
00922 struct implementation<polynomial_subresultant,V,polynomial_naive>:
00923 public implementation<polynomial_subresultant_base,V>
00924 {
00925
00926 typedef implementation<polynomial_subresultant_base,V> Pol;
00927
00928 TMPLP static void
00929 subresultant_sequence (const Polynomial& f, const Polynomial& g,
00930 vector<Polynomial>& res,
00931 vector<Polynomial>& cof, vector<Polynomial>& cog,
00932 Polynomial& d1, Polynomial& u1, Polynomial& v1,
00933 Polynomial& d2, Polynomial& u2, Polynomial& v2,
00934 nat dest_deg= 0) {
00935 int n= degree (f), m= degree (g);
00936 if (n <= 0 || m <= 0) {
00937 set_as (d1, 0); set_as (u1, 0); set_as (v1, 0);
00938 set_as (d2, 0); set_as (u2, 0); set_as (v2, 0);
00939 return;
00940 }
00941 if (n < m) {
00942 Pol::subresultant_sequence (g, f, res, cog, cof,
00943 d1, v1, u1, d2, v2, u2, dest_deg);
00944 for (nat k= 0; k < (nat) n; k++)
00945 if ((m+n-1) & (n-k) & 1) {
00946 if (k < N(res)) res[k]= -res[k];
00947 if (k < N(cof)) cof[k]= -cof[k];
00948 if (k < N(cog)) cog[k]= -cog[k];
00949 }
00950 if ((m+n-1) & (n-degree (d1)) & 1) { d1= -d1; u1= -u1; v1= -v1; }
00951 else { d2= -d2; u2= -u2; v2= -v2; }
00952 }
00953 else
00954 Pol::subresultant_sequence (f, g, res, cof, cog,
00955 d1, u1, v1, d2, u2, v2, dest_deg); }
00956
00957 };
00958
00959
00960
00961
00962
00963 struct polynomial_evaluate {};
00964
00965 template<typename V>
00966 struct implementation<polynomial_evaluate,V,polynomial_naive>:
00967 public implementation<polynomial_divide,V>
00968 {
00969 typedef implementation<polynomial_divide,V> Pol;
00970 typedef implementation<vector_linear,V> Vec;
00971
00972 TMPL static void
00973 multi_mod (C* r, const C* p, const C* q, const nat* d, nat n, nat k) {
00974
00975
00976
00977
00978 nat l= aligned_size<C,V> (n);
00979 C* tmp_q= mmx_new <C> (l);
00980 C* tmp_r= mmx_new <C> (l);
00981 for (nat i= 0; i < k; i++) {
00982 if (n < d[i]) {
00983 Pol::copy (r, p, n);
00984 Pol::clear (r+n, d[i]-1-n);
00985 }
00986 else {
00987 Pol::copy (tmp_r, p, n);
00988 Pol::quo_rem (tmp_q, tmp_r, q, n, d[i]);
00989 Pol::copy (r, tmp_r, d[i]-1);
00990 }
00991 r += d[i]; q += d[i];
00992 }
00993 mmx_delete<C> (tmp_q, l);
00994 mmx_delete<C> (tmp_r, l);
00995 }
00996
00997 TMPL static void
00998 annulator (C* d, const C* s, nat n) {
00999
01000
01001 switch (n) {
01002 case 0:
01003 d[0]= promote (1, d[0]);
01004 break;
01005 case 1:
01006 d[1]= promote (1, d[0]);
01007 d[0]= -s[0];
01008 break;
01009 case 2:
01010 d[2]= promote (1, d[0]);
01011 d[1]= -(s[0]+s[1]);
01012 d[0]= s[0]*s[1];
01013 break;
01014 case 3:
01015 d[3]= promote (1, d[0]);
01016 d[2]= -(s[0]+s[1]+s[2]);
01017 d[1]= s[0]*s[1] + s[1]*s[2]+ s[2]*s[0];
01018 d[0]= -s[0]*s[1]*s[2];
01019 break;
01020 default:
01021 {
01022 nat h= n>>1;
01023 nat l= aligned_size<C,V> (n+2);
01024 C* aux= mmx_new<C> (l);
01025 annulator (aux, s, h);
01026 annulator (aux+h+1, s+h, n-h);
01027 Pol::mul (d, aux, aux+h+1, h+1, n+1-h);
01028 mmx_delete<C> (aux, l);
01029 }
01030 }
01031 }
01032
01033 TMPL static C
01034 evaluate (const C* p, const C& x, nat l) {
01035
01036 if (l == 0) return promote (0, x);
01037 C r= p[l-1];
01038 for (nat i=l-2; i!=((nat)(-1)); i--)
01039 r= (x*r) + p[i];
01040 return r;
01041 }
01042
01043 TMPL void
01044 tevaluate (const C& v, C* p, const C& x, nat l) {
01045
01046 if (l == 0) return;
01047 p[0] = v;
01048 for (nat i= 1; i < l; i++) p[i] = x * p[i-1];
01049 }
01050
01051 TMPL static void
01052 evaluate (C* v, const C* p, const C* x, nat l, nat n) {
01053
01054 for (nat j=0; j<n; j++)
01055 if (l == 0) v[j]= 0;
01056 else {
01057 C r= p[l-1];
01058 for (nat i=l-2; i!=((nat)(-1)); i--)
01059 r= (x[j]*r) + p[i];
01060 v[j]= r;
01061 }
01062 }
01063
01064 TMPL static void
01065 tevaluate (const C* v, C* p, const C* x, nat l, nat n) {
01066
01067 nat l_y= aligned_size<C,V> (n);
01068 C* y= mmx_new<C> (l_y);
01069 Pol::set (y, C(1), n);
01070 for (nat j= 0; j < l; j++) {
01071 p[j]= Vec::inn_prod (y, v, n);
01072 Vec::mul (y, x, n);
01073 }
01074 mmx_delete<C> (y, l_y);
01075 }
01076
01077 TMPL static void
01078 interpolate (C* p, const C* v, const C* x, nat n) {
01079
01080
01081 if (n == 0) return;
01082 format<C> fm= get_format (v[0]);
01083 nat l= aligned_size<C,V> (n+1), i, j;
01084 C ** buf= mmx_new<C*> (n+1);
01085 for (i= 0; i < n+1; i++)
01086 buf[i]= mmx_formatted_new<C> (l, fm);
01087 C * tmp0= mmx_formatted_new<C> (l, fm);
01088 C * tmp1= mmx_formatted_new<C> (l, fm);
01089 buf[0][0]= promote (1, fm);
01090 for (i= 0; i < n; i++) {
01091 for (j= 0; j < i; j++) {
01092 Pol::copy (tmp0 + 1, buf[j], i); tmp0[0]= promote (0, fm);
01093 Pol::mul_sc (tmp1, buf[j], x[i], i); tmp1[i]= promote (0, fm);
01094 Pol::sub (buf[j], tmp0, tmp1, i+1);
01095 }
01096 Pol::copy (tmp0 + 1, buf[j], i + 1); tmp0[0]= promote (0, fm);
01097 Pol::mul_sc (tmp1, buf[j], x[i], i + 1); tmp1[i+1]= promote (0, fm);
01098 Pol::sub (buf[j+1], tmp0, tmp1, i + 2);
01099 }
01100 Pol::derive (tmp1, buf[n], n+1);
01101 evaluate (tmp0, tmp1, x, n, n);
01102 Vec::div (tmp1, v, tmp0, n);
01103 Pol::clear (p, n);
01104 for (i= 0; i < n; i++) {
01105 Pol::mul_sc (tmp0, buf[i], tmp1[i], n);
01106 Pol::add (p, tmp0, n);
01107 }
01108 mmx_delete<C> (tmp0, l); mmx_delete<C> (tmp1, l);
01109 for (i= 0; i < n+1; i++) mmx_delete<C> (buf[i], l);
01110 mmx_delete<C*> (buf, n+1);
01111 }
01112
01113 TMPL static void
01114 tinterpolate (const C* p, C* v, const C* x, nat n) {
01115
01116
01117 if (n == 0) return;
01118 format<C> fm= get_format (v[0]);
01119 nat l= aligned_size<C,V> (n+1), i, j;
01120 C ** buf= mmx_new<C*> (n+1);
01121 for (i= 0; i < n+1; i++)
01122 buf[i]= mmx_formatted_new<C> (l, fm);
01123 C * tmp0= mmx_formatted_new<C> (l, fm);
01124 C * tmp1= mmx_formatted_new<C> (l, fm);
01125 buf[0][0]= promote (1, fm);
01126 for (i= 0; i < n; i++) {
01127 for (j= 0; j < i; j++) {
01128 Pol::copy (tmp0 + 1, buf[j], i); tmp0[0]= promote (0, fm);
01129 Pol::mul_sc (tmp1, buf[j], x[i], i); tmp1[i]= promote (0, fm);
01130 Pol::sub (buf[j], tmp0, tmp1, i+1);
01131 }
01132 Pol::copy (tmp0 + 1, buf[j], i + 1); tmp0[0]= promote (0, fm);
01133 Pol::mul_sc (tmp1, buf[j], x[i], i + 1); tmp1[i+1]= promote (0, fm);
01134 Pol::sub (buf[j+1], tmp0, tmp1, i + 2);
01135 }
01136 Pol::derive (tmp1, buf[n], n+1);
01137 evaluate (tmp0, tmp1, x, n, n);
01138 for (i= 0; i < n; i++)
01139 v[i]= Vec::inn_prod (buf[i], p, n);
01140 Vec::div (v, tmp0, n);
01141 mmx_delete<C> (tmp0, l); mmx_delete<C> (tmp1, l);
01142 for (i= 0; i < n+1; i++) mmx_delete<C> (buf[i], l);
01143 mmx_delete<C*> (buf, n+1);
01144 }
01145
01146 TMPL static void
01147 expand (C** v, const C* p, const C* x, const nat* nu, nat n, nat k) {
01148 (void) v; (void) p; (void) x; (void) nu; (void) n; (void) k;
01149 ERROR ("expand not yet implemented");
01150 }
01151
01152 #define C typename scalar_type_helper<Polynomial>::val
01153
01154 TMPLP static vector<Polynomial>
01155 multi_rem (const Polynomial& p, const vector<Polynomial>& q) {
01156 ASSERT (is_non_scalar (q), "non-scalar vector expected");
01157 nat k= N(q), n= N(p);
01158 if (k == 0) return q;
01159 vector<nat> d ((nat) 0, k);
01160 for (nat i= 0; i < k; i++) {
01161 d[i]= N(q[i]);
01162 ASSERT (d[i] > 0, "division by 0");
01163 }
01164 if (n == 0) return vector<Polynomial> (Polynomial (C(0)), k);
01165 nat m= big_add (d), l= aligned_size<C,V> (m);
01166 C* qq= mmx_new<C> (l), * r= mmx_new<C> (l), * tmp= qq;
01167 for (nat i= 0; i < k; i++) {
01168 Pol::copy (tmp, seg (q[i]), d[i]);
01169 if (q[i][d[i]-1] != 1)
01170 Pol::mul_sc (tmp, 1/q[i][d[i]-1], d[i]);
01171 tmp += d[i];
01172 }
01173 multi_mod (r, seg(p), qq, seg (d), n, k);
01174
01175 mmx_delete<C> (qq, l);
01176 vector<Polynomial> ans (Polynomial (C(0)), k);
01177 tmp= r;
01178 for (nat i= 0; i < k; i++) {
01179 nat l_t= aligned_size<C,V> (d[i]-1);
01180 C* t= mmx_new<C> (l_t);
01181 Pol::copy (t, tmp, d[i]-1);
01182 ans[i]= Polynomial (t, d[i]-1, l_t, CF(p));
01183 tmp += d[i];
01184 }
01185 mmx_delete<C> (r, l);
01186 return ans; }
01187
01188 TMPLP static vector<Polynomial>
01189 multi_prem (const Polynomial& P, const vector<Polynomial>& Q) {
01190 return binary_map_scalar<prem_op> (Q, P); }
01191
01192 TMPLP static vector<Polynomial>
01193 multi_gcd (const Polynomial& P, const vector<Polynomial>& Q) {
01194 return binary_map<gcd_op> (rem (P, Q), Q); }
01195
01196 TMPLP static Polynomial
01197 annulator (const Vector& x) {
01198 ASSERT (is_non_scalar (x), "non-scalar vector expected");
01199 nat l= aligned_size<C,V> (N(x)+1);
01200 C* r= mmx_new<C> (l);
01201 annulator (r, seg(x), N(x));
01202 return Polynomial (r, N(x)+1, l, CF(x)); }
01203
01204 TMPLP static inline Vector
01205 evaluate (const Polynomial& p, const Vector& x) {
01206 ASSERT (is_non_scalar (x), "non-scalar vector expected");
01207 nat l= default_aligned_size<C> (N(x));
01208 C* r= mmx_new<C> (l);
01209 evaluate (r, seg(p), seg(x), N(p), N(x));
01210 return Vector (r, N(x), l, CF(x)); }
01211
01212 TMPLP static inline Polynomial
01213 tevaluate (const Vector& v, const Vector& x, nat l) {
01214 ASSERT (is_non_scalar (x), "non-scalar vector expected");
01215 nat l_r= aligned_size<C,V> (l), n= N(x);
01216 C* r= mmx_new<C> (l_r);
01217 tevaluate (seg(v), r, seg(x), l, n);
01218 return Polynomial (r, l, l_r, CF(v)); }
01219
01220 TMPLP static Polynomial
01221 interpolate (const Vector& v, const Vector& x) {
01222 ASSERT (is_non_scalar (x), "non-scalar vector expected");
01223 ASSERT (N(v) == N(x), "dimensions don't match");
01224 nat n= N(v), l= aligned_size<C,V> (n);
01225 C* r= mmx_new<C> (l);
01226 interpolate (r, seg(v), seg(x), n);
01227 return Polynomial (r, n, l, CF(v)); }
01228
01229 TMPLP static Vector
01230 tinterpolate (const Polynomial& p, const Vector& x) {
01231 ASSERT (is_non_scalar (x), "non-scalar vector expected");
01232 ASSERT (N(p) <= N(x), "dimensions don't match");
01233 nat n= N(x), lv = default_aligned_size<C> (n);
01234 nat lp= aligned_size<C,V> (n);
01235 C* r= mmx_new<C> (lv); C* tmp= mmx_new<C> (lp);
01236 Pol::copy (tmp, seg(p), N(p)); Pol::clear (tmp + N(p), n - N(p));
01237 tinterpolate (tmp, r, seg(x), n);
01238 mmx_delete<C> (tmp, lp);
01239 return Vector (r, n, lv); }
01240 #undef C
01241
01242 };
01243
01244 #undef TMPL
01245 #undef TMPLK
01246 #undef TMPLX
01247 #undef TMPLP
01248 }
01249 #endif //__MMX__POLYNOMIAL_NAIVE__HPP