00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX__POLYNOMIAL_RING_NAIVE__HPP
00014 #define __MMX__POLYNOMIAL_RING_NAIVE__HPP
00015 #include <algebramix/matrix.hpp>
00016 #include <algebramix/matrix_ring_naive.hpp>
00017 #include <algebramix/polynomial_naive.hpp>
00018
00019 namespace mmx {
00020 #define TMPL template<typename Polynomial>
00021 #define C typename scalar_type_helper<Polynomial>::val
00022 #define Matrix matrix<C,matrix_ring_naive<matrix_naive> >
00023
00024
00025
00026
00027
00028 template<typename V>
00029 struct polynomial_ring_naive: public V {
00030 typedef typename V::Vec Vec;
00031 typedef polynomial_ring_naive<typename V::Naive> Naive;
00032 typedef polynomial_ring_naive<typename V::Positive> Positive;
00033 typedef polynomial_ring_naive<typename V::No_simd> No_simd;
00034 typedef polynomial_ring_naive<typename V::No_thread> No_thread;
00035 typedef polynomial_ring_naive<typename V::No_scaled> No_scaled;
00036 };
00037
00038 template<typename F, typename V, typename W>
00039 struct implementation<F,V,polynomial_ring_naive<W> >:
00040 public implementation<F,V,W> {};
00041
00042
00043
00044
00045
00046 template<typename V>
00047 struct polynomial_gcd_ring_naive_inc: public V {
00048 typedef typename V::Vec Vec;
00049 typedef polynomial_gcd_ring_naive_inc<typename V::Naive> Naive;
00050 typedef polynomial_gcd_ring_naive_inc<typename V::Positive> Positive;
00051 typedef polynomial_gcd_ring_naive_inc<typename V::No_simd> No_simd;
00052 typedef polynomial_gcd_ring_naive_inc<typename V::No_thread> No_thread;
00053 typedef polynomial_gcd_ring_naive_inc<typename V::No_scaled> No_scaled;
00054 };
00055
00056 template<typename F, typename V, typename W>
00057 struct implementation<F,V,polynomial_gcd_ring_naive_inc<W> >:
00058 public implementation<F,V,W> {};
00059
00060 DEFINE_VARIANT_1 (typename V, V,
00061 polynomial_gcd_ring_naive,
00062 polynomial_gcd_ring_naive_inc<
00063 polynomial_ring_naive<V> >)
00064
00065
00066
00067
00068
00069 template<typename V>
00070 struct polynomial_gcd_ring_ducos_inc: public V {
00071 typedef typename V::Vec Vec;
00072 typedef polynomial_gcd_ring_ducos_inc<typename V::Naive> Naive;
00073 typedef polynomial_gcd_ring_ducos_inc<typename V::Positive> Positive;
00074 typedef polynomial_gcd_ring_ducos_inc<typename V::No_simd> No_simd;
00075 typedef polynomial_gcd_ring_ducos_inc<typename V::No_thread> No_thread;
00076 typedef polynomial_gcd_ring_ducos_inc<typename V::No_scaled> No_scaled;
00077 };
00078
00079 template<typename F, typename V, typename W>
00080 struct implementation<F,V,polynomial_gcd_ring_ducos_inc<W> >:
00081 public implementation<F,V,W> {};
00082
00083 DEFINE_VARIANT_1 (typename V, V,
00084 polynomial_gcd_ring_ducos,
00085 polynomial_gcd_ring_ducos_inc<
00086 polynomial_gcd_ring_naive<V> >)
00087
00088
00089
00090
00091
00092 template<typename V, typename W>
00093 struct implementation<polynomial_subresultant_base,V,
00094 polynomial_ring_naive<W> >:
00095 public implementation<polynomial_divide,V>
00096 {
00097 private:
00098
00099 TMPL static Matrix
00100 sylvester_matrix (const Polynomial& f, const Polynomial& g, int k, int l) {
00101
00102
00103
00104
00105
00106
00107 int n = max (deg (f), 0), m = max (deg (g), 0), k2= 2*k;
00108 ASSERT (k >= 0 && k <= min (n, m), "out of range");
00109 ASSERT (l >= 0 && l <= k, "out of range");
00110 Matrix S (C (0), n + m - k2, n + m - k2);
00111 for (int j= 0; j < m - k; j++)
00112 S (0, j) = f[l - j];
00113 for (int j= 0; j < n - k; j++)
00114 S (0, j + m - k) = g[l - j];
00115 for (int j= 0; j < m - k; j++)
00116 for (int i= 1; i < n + m - k2; i++)
00117 S (i, j) = f[k + i - j];
00118 for (int j= 0; j < n - k; j++)
00119 for (int i= 1; i < n + m - k2; i++)
00120 S (i, j + m - k) = g[k + i - j];
00121 return S;
00122 }
00123
00124 TMPL static inline C
00125 subresultant (const Polynomial& f, const Polynomial& g, int k, int l) {
00127 int m= min (deg (f), deg (g));
00128 if (m < 0 ||
00129 k < 0 || k >= m ||
00130 l < 0 || l > k) return C(0);
00131 return det (sylvester_matrix (f, g, k, l));
00132 }
00133
00134 TMPL static Polynomial
00135 subresultant_co1 (const Polynomial& f, const Polynomial& g, int k) {
00137 int m= min (deg (f), deg (g));
00138 if (m < 0 ||
00139 k < 0 || k >= m) return Polynomial (C(0));
00140 Matrix S= sylvester_matrix (f, g, k, k);
00141 Polynomial cof(C(0));
00142 for (int l= 0; l < deg (g) - k; l++)
00143 cof += Polynomial (cofactor (S, 0, l), l);
00144 return cof;
00145 }
00146
00147 TMPL static Polynomial
00148 subresultant_co2 (const Polynomial& f, const Polynomial& g, int k) {
00150 int m= min (deg (f), deg (g));
00151 if (m < 0 ||
00152 k < 0 || k >= m) return Polynomial (C(0));
00153 Matrix S= sylvester_matrix (f, g, k, k);
00154 Polynomial cog(C(0));
00155 m= deg (g);
00156 for (int l= 0; l < deg (f) - k; l++)
00157 cog += Polynomial (cofactor (S, 0, m - k + l), l);
00158 return cog;
00159 }
00160
00161 public:
00162
00163 TMPL static Polynomial
00164 subresultant (const Polynomial& f, const Polynomial& g, int k) {
00167 Polynomial r(C(0));
00168 for (int l= 0; l <= k; l++)
00169 r += Polynomial (subresultant (f, g, k, l), l);
00170 return r;
00171 }
00172
00173 public:
00174
00175 TMPL static void
00176 subresultant_sequence (const Polynomial& f, const Polynomial& g,
00177 vector<Polynomial>& res,
00178 vector<Polynomial>& cof, vector<Polynomial>& cog,
00179 Polynomial& d1, Polynomial& u1, Polynomial& v1,
00180 Polynomial& d2, Polynomial& u2, Polynomial& v2,
00181 nat dest_deg= 0) {
00182 nat k, m= min (N (f), N (g)) - 1;
00183 if (m + 1 == 0) {
00184 d1= 0; u1= 0; v1= 0;
00185 d2= 0; u2= 0; v2= 0;
00186 return;
00187 }
00188 for (k= 0; k < m; k++) {
00189 if (k < N(res) && res[k] != 0) res[k]= subresultant (f, g, k);
00190 if (k < N(cof) && cof[k] != 0) cof[k]= subresultant_co1 (f, g, k);
00191 if (k < N(cog) && cog[k] != 0) cog[k]= subresultant_co2 (f, g, k);
00192 }
00193 if (d1 != 0 || u1 != 0 || v1 != 0) {
00194 Polynomial d= subresultant (f, g, dest_deg);
00195 for (k= dest_deg; k < m;) {
00196 Polynomial tmp= C(0);
00197 if (d == 0) { k++; d= subresultant (f, g, k); continue; }
00198 if (k == m-1 || (tmp= subresultant (f, g, k+1)) != 0) break;
00199 else { k++; d= tmp; }
00200 }
00201 if (d1 != 0) d1= d;
00202 if (u1 != 0) u1= k < m ? subresultant_co1 (f, g, k) : 0;
00203 if (v1 != 0) v1= k < m ? subresultant_co2 (f, g, k) : 0;
00204 }
00205 if (d2 != 0 || u2 != 0 || v2 != 0) {
00206 Polynomial d= C(0);
00207 for (k= dest_deg - 1; k + 1 != 0 && d == 0; k--)
00208 d= subresultant (f, g, k);
00209 if (d2 != 0) d2= d;
00210 if (u2 != 0) u2= subresultant_co1 (f, g, k+1);
00211 if (v2 != 0) v2= subresultant_co2 (f, g, k+1); } }
00212
00213 };
00214
00215
00216
00217
00218
00219 template<typename V, typename W>
00220 struct implementation<polynomial_subresultant_base,V,
00221 polynomial_gcd_ring_naive_inc<W> > {
00222
00223
00224
00225 template<typename T> static inline T
00226 defected_pow (const T& x, const T& y, int n) {
00227
00228 VERIFY (n >= 0, "bug");
00229 if (n == 0) return y;
00230 if (n == 1) return x;
00231 T z= square_op::op (defected_pow (x, y, n >> 1)) / y;
00232 return ((n & 1) == 0) ? z : ((x * z) / y);
00233 }
00234
00235 TMPL static inline Polynomial
00236 defected_prem (const Polynomial& s_n, const Polynomial& s_n_1,
00237 const Polynomial& s_m, const C& x,
00238 Polynomial& u, const Polynomial& cof_n,
00239 const Polynomial& cof_n_1, const Polynomial& cof_m,
00240 bool opt_cof,
00241 Polynomial& v, const Polynomial& cog_n,
00242 const Polynomial& cog_n_1, const Polynomial& cog_m,
00243 bool opt_cog) {
00244 (void) cof_m; (void) cog_m;
00245 int n= degree (s_n), m= degree (s_n_1);
00246 C c_m= s_m[degree (s_m)], y= s_n_1[m];
00247 Polynomial r= s_n;
00248 if (opt_cof) u = y * cof_n - lshiftz (r[n] * cof_n_1, n-m);
00249 if (opt_cog) v = y * cog_n - lshiftz (r[n] * cog_n_1, n-m);
00250 r = y * r - lshiftz (r[n] * s_n_1, n-m);
00251 for (int k= n-1; k >= m; k--) {
00252 if (opt_cof) u = (y * u - lshiftz (r[k] * cof_n_1, k-m)) / x;
00253 if (opt_cog) v = (y * v - lshiftz (r[k] * cog_n_1, k-m)) / x;
00254 r = (y * r - lshiftz (r[k] * s_n_1, k-m)) / x;
00255 }
00256 y = ((n-m+1) & 1) ? -s_n[n] : s_n[n];
00257 r /= y;
00258 if (opt_cof) u /= y;
00259 if (opt_cog) v /= y;
00260 return r;
00261 }
00262
00263 TMPL static void
00264 subresultant_sequence (const Polynomial& f, const Polynomial& g,
00265 vector<Polynomial>& res,
00266 vector<Polynomial>& cof, vector<Polynomial>& cog,
00267 Polynomial& d1, Polynomial& u1, Polynomial& v1,
00268 Polynomial& d2, Polynomial& u2, Polynomial& v2,
00269 nat dest_deg) {
00270 VERIFY (degree (f) >= degree (g) && degree (g) > 0, "incorrect degrees");
00271 nat n= degree (f), m= degree (g), k;
00272 bool b= false;
00273 nat min_deg_res= (d1 != 0 || d2 != 0) ? dest_deg : m;
00274 for (k= min_deg_res; k+1 > 0; k--)
00275 if (k < N(res) && res[k] != 0) min_deg_res= k;
00276 nat min_deg_cof= (u1 != 0 || u2 != 0) ? dest_deg : m;
00277 for (k= min_deg_cof; k+1 > 0; k--)
00278 if (k < N(cof) && cof[k] != 0) min_deg_cof= k;
00279 nat min_deg_cog= (v1 != 0 || v2 != 0) ? dest_deg : m;
00280 for (k= min_deg_cog; k+1 > 0; k--)
00281 if (k < N(cog) && cog[k] != 0) min_deg_cog= k;
00282 nat min_deg= min (min_deg_res, min (min_deg_cof, min_deg_cog));
00283 bool opt_res= res != 0 || d1 != 0 || d2 != 0;
00284 bool opt_cof= cof != 0 || u1 != 0 || u2 != 0;
00285 bool opt_cog= cog != 0 || v1 != 0 || v2 != 0;
00286 if (!(opt_res || opt_cof || opt_cog)) return;
00287 if (m < dest_deg) { d1= 0; u1= 0; v1= 0; d2= 0; u2= 0; v2= 0; b= true; }
00288 C d= binpow (g[m], n-m);
00289 Polynomial q, s_n= g, s_n_1= prem (f, g, q);
00290 Polynomial cof_n= 0, cog_n= 1, cof_n_1= g[m] * d, cog_n_1= -q;
00291 n= degree (s_n); m= degree (s_n_1);
00292 if (n-1 < N(res) && res[n-1] != 0) res[n-1]= s_n_1;
00293 if (n-1 < N(cof) && cof[n-1] != 0) cof[n-1]= cof_n_1;
00294 if (n-1 < N(cog) && cog[n-1] != 0) cog[n-1]= cog_n_1;
00295 if (m+1 < dest_deg+1 && !b) {
00296 if (d1 != 0) d1= 0;
00297 if (u1 != 0) u1= 0;
00298 if (v1 != 0) v1= 0;
00299 if (d2 != 0) d2= s_n_1;
00300 if (u2 != 0) u2= cof_n_1;
00301 if (v2 != 0) v2= cog_n_1; b= true;
00302 }
00303 C t0, t1;
00304 Polynomial s_m , cof_m , cog_m;
00305 Polynomial s_m_1, cof_m_1, cog_m_1;
00306 while (true) {
00307 if (m+1 < dest_deg+1 && !b) {
00308 if (d1 != 0) d1= s_n;
00309 if (u1 != 0) u1= cof_n;
00310 if (v1 != 0) v1= cog_n;
00311 if (d2 != 0) d2= s_n_1;
00312 if (u2 != 0) u2= cof_n_1;
00313 if (v2 != 0) v2= cog_n_1; b= true;
00314 }
00315 for (k= m+1; k+1 < n; k++) {
00316 if (k < N(res) && res[k] != 0) res[k] = 0;
00317 if (k < N(cof) && cof[k] != 0) cof[k] = 0;
00318 if (k < N(cog) && cog[k] != 0) cog[k] = 0;
00319 }
00320 t0= binpow (s_n_1[m], n-m-1); t1= binpow (d, n-m-1);
00321 s_m= (t0 * s_n_1) / t1;
00322 if (opt_cof) cof_m= (t0 * cof_n_1) / t1;
00323 if (opt_cog) cog_m= (t0 * cog_n_1) / t1;
00324 if (m < N(res) && res[m] != 0) res[m] = s_m;
00325 if (m < N(cof) && cof[m] != 0) cof[m] = cof_m;
00326 if (m < N(cog) && cog[m] != 0) cog[m] = cog_m;
00327 if (m+1 < min_deg+1) break;
00328 t0 *= square_op::op (s_n_1[m]); t1 *= ((n-m) & 1) ? s_n[n] * d : -s_n[n] * d;
00329 s_m_1= prem (s_n, s_n_1, q) / t1;
00330 if (opt_cof) cof_m_1= (t0 * cof_n - q * cof_n_1) / t1;
00331 if (opt_cog) cog_m_1= (t0 * cog_n - q * cog_n_1) / t1;
00332 if (m-1 < N(res) && res[m-1] != 0) res[m-1]= s_m_1;
00333 if (m-1 < N(cof) && cof[m-1] != 0) cof[m-1]= cof_m_1;
00334 if (m-1 < N(cog) && cog[m-1] != 0) cog[m-1]= cog_m_1;
00335 s_n= s_m; s_n_1= s_m_1; d= s_n[m];
00336 n= degree (s_n); m= degree (s_n_1);
00337 if (opt_cof) { cof_n= cof_m; cof_n_1= cof_m_1; }
00338 if (opt_cog) { cog_n= cog_m; cog_n_1= cog_m_1; }
00339 opt_cof= m >= min_deg_cof;
00340 opt_cog= m >= min_deg_cog;
00341 }
00342 }
00343
00344 };
00345
00346
00347
00348
00349
00350
00351 template<typename V, typename BV>
00352 struct implementation<polynomial_subresultant_base,V,
00353 polynomial_gcd_ring_ducos_inc<BV> > {
00354
00355 template<typename T> static inline T
00356 defected_pow (const T& x, const T& y, int n) {
00357
00358 VERIFY (n >= 0, "bug");
00359 if (n == 0) return y;
00360 if (n == 1) return x;
00361 T z= square_op::op (defected_pow (x, y, n >> 1)) / y;
00362 return ((n & 1) == 0) ? z : ((x * z) / y);
00363 }
00364
00365 TMPL static inline Polynomial
00366 defected_prem (const Polynomial& s_n, const Polynomial& s_n_1,
00367 const Polynomial& s_m, const C& x,
00368 Polynomial& u, const Polynomial& cof_n,
00369 const Polynomial& cof_n_1, const Polynomial& cof_m,
00370 bool opt_cof,
00371 Polynomial& v, const Polynomial& cog_n,
00372 const Polynomial& cog_n_1, const Polynomial& cog_m,
00373 bool opt_cog) {
00374
00375 int n= degree (s_n), m= degree (s_n_1);
00376 C c_n= s_n[n], c_n_1= s_n_1[m], c_m= s_m[m];
00377
00378
00379
00380 Polynomial t, r, h= range (s_m, 0, m), hf= cof_m, hg= cog_m;
00381 Polynomial d= c_m * range (s_n, 0, m) - s_n[m] * h,
00382 df= c_m * cof_n - s_n[m] * hf, dg= c_m * cog_n - s_n[m] * hg;
00383 for (int i= m + 1; i < n; i++) {
00384 if (opt_cof) {
00385 hf= lshiftz (hf, 1) - (h[m-1] * cof_n_1) / c_n_1;
00386 df -= s_n[i] * hf;
00387 }
00388 if (opt_cog) {
00389 hg= lshiftz (hg, 1) - (h[m-1] * cog_n_1) / c_n_1;
00390 dg -= s_n[i] * hg;
00391 }
00392 h= lshiftz (h, 1) - (h[m-1] * s_n_1) / c_n_1;
00393 d -= s_n[i] * h;
00394 }
00395 if (opt_cof) u= c_n_1 * (df / c_n)
00396 - (c_n_1 * lshiftz (hf, 1) - h[m-1] * cof_n_1);
00397 if (opt_cog) v= c_n_1 * (dg / c_n)
00398 - (c_n_1 * lshiftz (hg, 1) - h[m-1] * cog_n_1);
00399 r= c_n_1 * (d / c_n) - (c_n_1 * lshiftz (h, 1) - h[m-1] * s_n_1);
00400 C y= ((n-m+1) & 1) ? -x : x;
00401 r /= y;
00402 if (opt_cof) u /= y;
00403 if (opt_cog) v /= y;
00404 return r;
00405 }
00406
00407 TMPL static void
00408 subresultant_sequence (const Polynomial& f, const Polynomial& g,
00409 vector<Polynomial>& res,
00410 vector<Polynomial>& cof, vector<Polynomial>& cog,
00411 Polynomial& d1, Polynomial& u1, Polynomial& v1,
00412 Polynomial& d2, Polynomial& u2, Polynomial& v2,
00413 nat dest_deg) {
00414 VERIFY (degree (f) >= degree (g) && degree (g) > 0, "incorrect degrees");
00415 nat n= degree (f), m= degree (g), k;
00416 bool b= false;
00417 nat min_deg_res= (d1 != 0 || d2 != 0) ? dest_deg : m;
00418 for (k= min_deg_res; k+1 > 0; k--)
00419 if (k < N(res) && res[k] != 0) min_deg_res= k;
00420 nat min_deg_cof= (u1 != 0 || u2 != 0) ? dest_deg : m;
00421 for (k= min_deg_cof; k+1 > 0; k--)
00422 if (k < N(cof) && cof[k] != 0) min_deg_cof= k;
00423 nat min_deg_cog= (v1 != 0 || v2 != 0) ? dest_deg : m;
00424 for (k= min_deg_cog; k+1 > 0; k--)
00425 if (k < N(cog) && cog[k] != 0) min_deg_cog= k;
00426 nat min_deg= min (min_deg_res, min (min_deg_cof, min_deg_cog));
00427 bool opt_res= res != 0 || d1 != 0 || d2 != 0;
00428 bool opt_cof= cof != 0 || u1 != 0 || u2 != 0;
00429 bool opt_cog= cog != 0 || v1 != 0 || v2 != 0;
00430 if (!(opt_res || opt_cof || opt_cog)) return;
00431 if (m < dest_deg) { d1= 0; u1= 0; v1= 0; d2= 0; u2= 0; v2= 0; b= true; }
00432 C d= binpow (g[m], n-m);
00433 Polynomial q, s_n= g, s_n_1= prem (f, g, q);
00434 Polynomial cof_n= 0, cof_n_1= g[m] * d, cog_n= 1, cog_n_1= -q;
00435 n= degree (s_n); m= degree (s_n_1);
00436 if (n-1 < N(res) && res[n-1] != 0) res[n-1]= s_n_1;
00437 if (n-1 < N(cof) && cof[n-1] != 0) cof[n-1]= cof_n_1;
00438 if (n-1 < N(cog) && cog[n-1] != 0) cog[n-1]= cog_n_1;
00439 if (m+1 < dest_deg+1 && !b) {
00440 if (d1 != 0) d1= 0;
00441 if (u1 != 0) u1= 0;
00442 if (v1 != 0) v1= 0;
00443 if (d2 != 0) d2= s_n_1;
00444 if (u2 != 0) u2= cof_n_1;
00445 if (v2 != 0) v2= cog_n_1; b= true;
00446 }
00447 C t0, t1;
00448 Polynomial s_m , cof_m , cog_m;
00449 Polynomial s_m_1, cof_m_1, cog_m_1;
00450 while (true) {
00451 if (m+1 < dest_deg+1 && !b) {
00452 if (d1 != 0) d1= s_n;
00453 if (u1 != 0) u1= cof_n;
00454 if (v1 != 0) v1= cog_n;
00455 if (d2 != 0) d2= s_n_1;
00456 if (u2 != 0) u2= cof_n_1;
00457 if (v2 != 0) v2= cog_n_1; b= true;
00458 }
00459 for (k= m+1; k+1 < n; k++) {
00460 if (k < N(res) && res[k] != 0) res[k] = 0;
00461 if (k < N(cof) && cof[k] != 0) cof[k] = 0;
00462 if (k < N(cog) && cog[k] != 0) cog[k] = 0;
00463 }
00464 if (n == m+1) {
00465 s_m= s_n_1;
00466 if (opt_cof) cof_m= cof_n_1;
00467 if (opt_cog) cog_m= cog_n_1;
00468 }
00469 else {
00470 C a= defected_pow (s_n_1[m], d, n-m-1);
00471 s_m= (a * s_n_1) / d;
00472 if (opt_cof) cof_m= (a * cof_n_1) / d;
00473 if (opt_cog) cog_m= (a * cog_n_1) / d;
00474 }
00475 if (m < N (res) && res[m] != 0) res[m] = s_m;
00476 if (m < N (cof) && cof[m] != 0) cof[m] = cof_m;
00477 if (m < N (cog) && cog[m] != 0) cog[m] = cog_m;
00478 if (m+1 < min_deg+1) break;
00479 s_m_1= defected_prem (s_n, s_n_1, s_m, d,
00480 cof_m_1, cof_n, cof_n_1, cof_m, opt_cof,
00481 cog_m_1, cog_n, cog_n_1, cog_m, opt_cog);
00482 if (m-1 < N (res) && res[m-1] != 0) res[m-1]= s_m_1;
00483 if (m-1 < N (cof) && cof[m-1] != 0) cof[m-1]= cof_m_1;
00484 if (m-1 < N (cog) && cog[m-1] != 0) cog[m-1]= cog_m_1;
00485 s_n= s_m; s_n_1= s_m_1; d= s_n[m];
00486 if (opt_cof) { cof_n= cof_m; cof_n_1= cof_m_1; }
00487 if (opt_cog) { cog_n= cog_m; cog_n_1= cog_m_1; }
00488 n= degree (s_n); m= degree (s_n_1);
00489 opt_cof= m >= min_deg_cof;
00490 opt_cog= m >= min_deg_cog;
00491 }
00492 }
00493
00494 };
00495
00496
00497
00498
00499
00500
00501 template<typename V, typename W>
00502 struct implementation<polynomial_gcd,V,polynomial_ring_naive<W> >:
00503 public implementation<polynomial_divide,V>
00504 {
00505 typedef implementation<polynomial_subresultant,V> Pol;
00506
00507 TMPL static Polynomial
00508 gcd (const Polynomial& P1, const Polynomial& P2) {
00509 nat n1= N(P1), n2= N(P2);
00510 C c1, c2;
00511 if (n2 == 0) { return P1; }
00512 if (n1 == 0) { return P2; }
00513 Polynomial Q1= primitive_part (P1, c1);
00514 Polynomial Q2= primitive_part (P2, c2);
00515 C c= gcd_op::op (c1, c2);
00516 Polynomial zero= promote (0, CF(P1));
00517 vector<Polynomial> T (zero, 0);
00518 Polynomial G(C(1)), H(C(1)), D(C(0));
00519 Pol::subresultant_sequence (Q1, Q2, T, T, T, G, D, D, H, D, D, 1);
00520 if (H != 0) { G= H; }
00521 if (G == 0) { if (n1 < n2) G= Q1; else G= Q2; }
00522 else { C c; G= primitive_part (G, c); }
00523 return G * c;
00524 }
00525
00526 TMPL static Polynomial
00527 gcd (const Polynomial& P1, const Polynomial& P2,
00528 Polynomial& U1, Polynomial& U2) {
00529 ERROR ("extended gcd is not defined in " *
00530 string (typeid (Polynomial).name ()));
00531 }
00532
00533 TMPL static vector<Polynomial>
00534 multi_gcd (const Polynomial& P, const vector<Polynomial>& Q) {
00535 return binary_map_scalar<gcd_op> (Q, P); }
00536
00537 TMPL static inline Polynomial
00538 lcm (const Polynomial& P1, const Polynomial& P2) {
00539 Polynomial dummy (0);
00540 return (P1 == 0 && P2 == 0) ? 0 : P1 * (P2 / gcd (P1, P2));
00541 }
00542
00543 TMPL static Polynomial
00544 invert_mod (const Polynomial& P, const Polynomial& Q) {
00545
00546 Polynomial inv_P= C(1), dummy= C(0), G= gcd (P, Q, inv_P, dummy);
00547 if (deg (G) != 0) inv_P= 0;
00548 return inv_P / G[0];
00549 }
00550
00551 TMPL static void
00552 reconstruct (const Polynomial& P, const Polynomial& Q, nat k,
00553 Polynomial& Num, Polynomial &Den) {
00554
00555
00556
00557 nat n= deg (Q);
00558 VERIFY (k <= n && k > 0, "invalid argument");
00559 nat m= N(P);
00560 if (n == 0 || m == 0) { Num= 0; Den= 1; return; }
00561 Polynomial S= Q, D (0);
00562 Polynomial zero= promote (0, CF(P));
00563 vector<Polynomial> T (zero, 0);
00564 Num= 1; Den= 1;
00565 Pol::subresultant_sequence (S, P, T, T, T, D, D, D, Num, D, Den, k);
00566 if (Num == 0) { Num= P; Den= 1; }
00567 }
00568
00569 };
00570
00571 #undef Matrix
00572 #undef TMPL
00573 #undef C
00574 }
00575 #endif //__MMX__POLYNOMIAL_RING_NAIVE__HPP