algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : polynomial_ring_naive.hpp 00004 * DESCRIPTION: naive polynomial arithmetic over rings 00005 * COPYRIGHT : (C) 2008 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_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 * Naive variant for polynomials over rings without division 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 * Naive variant for polynomials over rings without division, but with a gcd 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 * Ducos optimization of naive variant over rings with a gcd 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 * Naive but general implementation of subresultants 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 // If l = k then it returns the matrix of the following map: 00102 // P_{dp - k} x P_{dq - k} --> P_{dp + dq - 2k} 00103 // (u, v) :--> (u * f + v * g) quo x^k, 00104 // in the canonical basis 1, x, x^2, etc. 00105 // In general, the determinant of the matrix returned is the coefficient 00106 // of degree l of the kth subresultant. 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 }; // implementation<polynomial_subresultant_base,V,polynomial_ring_naive<W> > 00214 00215 /****************************************************************************** 00216 * General implementation of subresultants via pseudo-remaindering 00217 ******************************************************************************/ 00218 00219 template<typename V, typename W> 00220 struct implementation<polynomial_subresultant_base,V, 00221 polynomial_gcd_ring_naive_inc<W> > { 00222 // Lionel Ducos, "Optimizations of the subresultant algorithm", 00223 // JPAA, 1998 (p. 150). 00224 00225 template<typename T> static inline T 00226 defected_pow (const T& x, const T& y, int n) { 00227 // return x^n / y^(n-1) 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 }; // implementation<polynomial_subresultant_base,V, 00345 // polynomial_gcd_ring_naive_inc<W> > 00346 00347 /****************************************************************************** 00348 * Optimized subresultants following Ducos 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 // return x^n / y^(n-1) 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 // Ibid. p. 153. 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 // The code below corresponds to (discarding the cofactors): 00378 // r= rem (c_m * c_n_1 * s_n, s_n_1) / x; 00379 // return ((n-m+1) & 1) ? r / (-s_n[n]) : r / s_n[n]; 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 }; // implementation<polynomial_subresultant_base,V, 00495 // polynomial_gcd_ring_ducos_inc<BV> > 00496 00497 /****************************************************************************** 00498 * Gcd computations 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 // inverse of P modulo Q, return 0 if non-invertible 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 pade (const Polynomial& P, nat n, nat k, 00553 Polynomial& Num, Polynomial &Den) { 00554 // In return P = Num/Den + O(x^n), with 00555 // deg (Num) < k and deg (Den) <= n-k. 00556 // Note that Num and Den are not ensured to be coprime. 00557 VERIFY (k <= n && k > 0, "invalid argument"); 00558 nat m= N(P); 00559 if (n == 0 || m == 0) { Num= 0; Den= 1; return; } 00560 Polynomial S (C(1), n), D (0); 00561 Polynomial zero= promote (0, CF(P)); 00562 vector<Polynomial> T (zero, 0); 00563 Num= 1; Den= 1; 00564 Pol::subresultant_sequence (S, P, T, T, T, D, D, D, Num, D, Den, k); 00565 if (Num == 0) { Num= P; Den= 1; } 00566 } 00567 00568 }; // implementation<polynomial_gcd,V,polynomial_ring_naive<W> > 00569 00570 #undef Matrix 00571 #undef TMPL 00572 #undef C 00573 } // namespace mmx 00574 #endif //__MMX__POLYNOMIAL_RING_NAIVE__HPP