algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : polynomial_ring_dicho.hpp 00004 * DESCRIPTION: dichotomic algorithms over rings 00005 * COPYRIGHT : (C) 2009 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_RING_DICHO__HPP 00014 #define __MMX__POLYNOMIAL_RING_DICHO__HPP 00015 #include <algebramix/polynomial_ring_naive.hpp> 00016 #include <algebramix/polynomial_dicho.hpp> 00017 #include <algebramix/matrix.hpp> 00018 00019 namespace mmx { 00020 #define TMPL template<typename C> 00021 #define TMPLP template <typename Polynomial> 00022 00023 /****************************************************************************** 00024 * Dichotomic variants for polynomials over rings without division 00025 ******************************************************************************/ 00026 00027 template<typename V> 00028 struct polynomial_ring_dicho_inc: public V { 00029 typedef typename V::Vec Vec; 00030 typedef typename V::Naive Naive; 00031 typedef typename V::Positive Positive; 00032 typedef polynomial_ring_dicho_inc<typename V::No_simd> No_simd; 00033 typedef polynomial_ring_dicho_inc<typename V::No_thread> No_thread; 00034 typedef polynomial_ring_dicho_inc<typename V::No_scaled> No_scaled; 00035 }; 00036 00037 template<typename F, typename V, typename W> 00038 struct implementation<F,V,polynomial_ring_dicho_inc<W> >: 00039 public implementation<F,V,W> {}; 00040 00041 DEFINE_VARIANT_1 (typename V, V, 00042 polynomial_ring_dicho, 00043 polynomial_ring_dicho_inc< 00044 polynomial_ring_naive< 00045 polynomial_dicho<V> > >) 00046 00047 /****************************************************************************** 00048 * Dichotomic variants for polynomials over rings with gcd without division 00049 ******************************************************************************/ 00050 00051 template<typename V> 00052 struct polynomial_gcd_ring_dicho_inc: 00053 public V {}; 00054 00055 template<typename F, typename V, typename W> 00056 struct implementation<F,V,polynomial_gcd_ring_dicho_inc<W> >: 00057 public implementation<F,V,W> {}; 00058 00059 DEFINE_VARIANT_1 (typename V, V, 00060 polynomial_gcd_ring_dicho, 00061 polynomial_gcd_ring_dicho_inc< 00062 polynomial_gcd_ring_naive< 00063 polynomial_ring_dicho<V> > >) 00064 00065 /****************************************************************************** 00066 * Division 00067 ******************************************************************************/ 00068 00069 template<typename V, typename W> 00070 struct implementation<polynomial_divide,V,polynomial_ring_dicho_inc<W> >: 00071 public implementation<polynomial_multiply,V> 00072 { 00073 typedef polynomial_divide_threshold<polynomial_ring_dicho<W> > Th; 00074 typedef implementation<polynomial_multiply,V> Pol; 00075 typedef implementation<polynomial_divide,polynomial_naive> Fallback; 00076 00077 TMPL static void 00078 quo_rem (C* dest, C* s1, const C* s2, nat n1, nat n2) { 00079 // NOTE: C must support exact division 00080 if (n1 < n2); 00081 else if (n1 < Threshold(C,Th)) 00082 Fallback::quo_rem (dest, s1, s2, n1, n2); 00083 else { 00084 nat l= n1-n2+1; 00085 if (n2 > l) { 00086 nat d= n2-l; 00087 quo_rem (dest, s1+d, s2+d, n1-d, l); 00088 nat buf_size= aligned_size<C,V> (l+d-1); 00089 C* buf= mmx_new<C> (buf_size); 00090 Pol::mul (buf, dest, s2, l, d); 00091 Pol::sub (s1, buf, l+d-1); 00092 mmx_delete<C> (buf, buf_size); 00093 } 00094 else { 00095 nat h= (n2+1) >> 1; 00096 nat d= l-h; 00097 quo_rem (dest+d, s1+d, s2, n1-d, n2); 00098 quo_rem (dest, s1, s2, n1-h, n2); 00099 } 00100 } 00101 } 00102 00103 TMPL static void 00104 tquo_rem (C* dest, const C* s1, const C* s2, nat n1, nat n2) { 00105 // (s1, n2-1) contains the part corresponding to the remainder, while 00106 // (s2+n2-1, n1-n2+1) occupies the one of the quotient. 00107 // We assume n2>0 and s2[n2-1] != 0. 00108 // (dest, n1) contains the output. 00109 // NOTE: C can be an euclidean ring (not necessarily a field) 00110 if (n1 < n2) 00111 Pol::copy (dest, s1, n1); 00112 else if (n1 < Threshold(C,Th)) 00113 Fallback::tquo_rem (dest, s1, s2, n1, n2); 00114 else { 00115 nat l= n1-n2+1; 00116 if (n2 > l) { 00117 nat d= n2-l; 00118 nat buf_size= aligned_size<C,V> (l+d-1); 00119 C* buf= mmx_new<C> (buf_size); 00120 nat tmp_size= aligned_size<C,V> (n1); 00121 C* tmp= mmx_new<C> (tmp_size); 00122 Pol::neg (buf , s1 , l+d-1); 00123 Pol::tmul (tmp+n2-1, s2 , buf, d, l); 00124 Pol::add (tmp+n2-1, s1+n2-1, l); 00125 Pol::copy (tmp , s1 , n2-1); 00126 Pol::tquo_rem (dest+d , tmp+d , s2+d, n1-d, l); 00127 Pol::copy (dest , s1 , d); 00128 mmx_delete<C> (buf, buf_size); 00129 mmx_delete<C> (tmp, tmp_size); 00130 } 00131 else { 00132 nat h= (n2+1) >> 1; 00133 nat d= l-h; 00134 nat tmp_size= aligned_size<C,V> (n1-d); 00135 C* tmp= mmx_new<C> (tmp_size); 00136 tquo_rem (dest , s1 , s2, n1-h, n2); 00137 Pol::copy (tmp , dest + d, n2-1); 00138 Pol::copy (tmp+n2-1, s1+n1-h , h); 00139 tquo_rem (dest+d , tmp , s2, n1-d, n2); 00140 mmx_delete<C> (tmp, tmp_size); 00141 } 00142 } 00143 } 00144 00145 TMPL static void 00146 pquo_rem (C* dest, C* s1, const C* s2, nat n1, nat n2) { 00147 if (n1 < n2); 00148 else if (n1 < Threshold(C,Th)) 00149 Fallback::pquo_rem (dest, s1, s2, n1, n2); 00150 else { 00151 nat l= n1-n2+1; 00152 if (n2 > l) { 00153 nat d= n2-l; 00154 pquo_rem (dest, s1+d, s2+d, n1-d, l); 00155 nat buf_size= aligned_size<C,V> (l+d-1); 00156 C* buf= mmx_new<C> (buf_size); 00157 Pol::mul (buf, dest, s2, l, d); 00158 Pol::mul_sc (s1, binpow (s2[n2-1], l), d); 00159 Pol::sub (s1, buf, l+d-1); 00160 mmx_delete<C> (buf, buf_size); 00161 } 00162 else { 00163 nat h= (n2+1) >> 1; 00164 nat d= l-h; 00165 pquo_rem (dest+d, s1+d, s2, n1-d, n2); 00166 Pol::mul_sc (s1, binpow (s2[n2-1], h), d); 00167 pquo_rem (dest, s1, s2, n1-h, n2); 00168 Pol::mul_sc (dest+d, binpow (s2[n2-1], d), h); 00169 } 00170 } 00171 } 00172 00173 }; // implementation<polynomial_divide,V,polynomial_ring_dicho_inc<W> > 00174 00175 /****************************************************************************** 00176 * Dichotomic subresultant 00177 ******************************************************************************/ 00178 00179 template<typename V, typename BV> 00180 struct implementation<polynomial_subresultant_base,V, 00181 polynomial_gcd_ring_dicho_inc<BV> > { 00182 00183 template<typename T> static inline T 00184 defected_pow (const T& x, const T& y, int n) { 00185 // return x^n / y^(n-1) 00186 VERIFY (n >= 0, "bug"); 00187 if (n == 0) return y; 00188 if (n == 1) return x; 00189 T z= square_op::op (defected_pow (x, y, n >> 1)) / y; 00190 return ((n & 1) == 0) ? z : ((x * z) / y); 00191 } 00192 00193 #define C typename scalar_type_helper<Polynomial>::val 00194 00195 TMPLP static void 00196 subresultant_compose (matrix<Polynomial>& num_R, 00197 const matrix<Polynomial>& num_S, 00198 const C& den_S, nat k= 0) { 00199 if (k == 0) 00200 num_R= num_S * num_R; 00201 else { 00202 num_R(0,0)= range (range (num_R(0,0), 0, k) * range (num_S(0,0), 0, k) + 00203 range (num_R(0,1), 0, k) * range (num_S(1,0), 0, k), 00204 0, k); 00205 num_R(0,1)= range (range (num_R(0,0), 0, k) * range (num_S(0,1), 0, k) + 00206 range (num_R(0,1), 0, k) * range (num_S(1,1), 0, k), 00207 0, k); 00208 num_R(1,0)= range (range (num_R(1,0), 0, k) * range (num_S(0,0), 0, k) + 00209 range (num_R(1,1), 0, k) * range (num_S(1,0), 0, k), 00210 0, k); 00211 num_R(1,1)= range (range (num_R(1,0), 0, k) * range (num_S(0,1), 0, k) + 00212 range (num_R(1,1), 0, k) * range (num_S(1,1), 0, k), 00213 0, k); 00214 } 00215 num_R(0,0) /= den_S; num_R(0,1) /= den_S; 00216 num_R(1,0) /= den_S; num_R(1,1) /= den_S; } 00217 00218 TMPLP static void 00219 subresultant_compose (matrix<Polynomial>& num_R, 00220 const vector<matrix<Polynomial> >& num_S, 00221 const vector<C>& den_S, nat k=0) { 00222 // dichotomic computation of (big_mul (num_S) * num_R) / den_S 00223 // truncated to precision k (if k > 0). 00224 nat n= N(num_S); 00225 if (n == 0) return; 00226 if (n == 1) { 00227 subresultant_compose (num_R, num_S[0], den_S[0], k); 00228 return; 00229 } 00230 nat m= n >> 1; 00231 matrix<Polynomial> num_T (Polynomial(C(0)), 2, 2); 00232 C det_num_R= num_R(0,0)[0] * num_R(1,1)[0] - num_R(1,0)[0] * num_R(0,1)[0]; 00233 num_T(0,0)= num_T(1,1)= det_num_R; 00234 subresultant_compose (num_T, range (num_S, 0, m), range (den_S, 0, m)); 00235 subresultant_compose (num_R, num_T, det_num_R); 00236 det_num_R= num_R(0,0)[0] * num_R(1,1)[0] - num_R(1,0)[0] * num_R(0,1)[0]; 00237 num_T(0,0)= num_T(1,1)= det_num_R; 00238 num_T(0,1)= num_T(1,0)= 0; 00239 subresultant_compose (num_T, range (num_S, m, n), range (den_S, m, n)); 00240 subresultant_compose (num_R, num_T, det_num_R); } 00241 00242 TMPLP static void 00243 half_subresultant_rec (const Polynomial& r0, const Polynomial& r1, 00244 bool defected, const C& num, 00245 matrix<Polynomial>& num_R, C& den_R, nat& k_out, 00246 vector<matrix<Polynomial> >& Q, vector<C>& rho, 00247 nat k) { 00248 // Get a maximum total of at most k terms of the quotients. 00249 // k = n0 performs a complete sequence. 00250 // defected means that r0 and r1 are strict truncations. 00251 nat n0= N(r0), n1= N(r1), l, l0, l1, h1, k2= (k << 1) - 1; 00252 VERIFY (n0 > n1, "bad input sizes"); 00253 VERIFY (k <= n0, "index k out of range"); 00254 if (k < n0 - n1 + 1) { 00255 num_R= matrix<Polynomial> (Polynomial (C(0)), 2, 2); 00256 num_R(0,0)= num; num_R(1,1)= num; den_R= num; 00257 k_out= 1; 00258 return; 00259 } 00260 half_subresultant_rec (r0, r1, defected, num, 00261 num_R, den_R, k_out, Q, rho, k >> 1); 00262 VERIFY (k_out <= (k >> 1), "bug"); 00263 00264 Polynomial s0, s1, t0, t1, q; 00265 if (k2 >= n0) { 00266 t0= r0; t1= r1; 00267 } 00268 else { 00269 t0= range (r0, n0 - k2, n0); t1= range (r1, n0 - k2, n1); 00270 defected= true; 00271 } 00272 s1= num_R(1,0) * t0 + num_R(1,1) * t1; 00273 if (s1 == 0) { return; } 00274 s0= num_R(0,0) * t0 + num_R(0,1) * t1; 00275 nat m0= N(s0), m1= N(s1); 00276 if (defected) { 00277 s1= range (s1, k_out - 1, m1); 00278 if (s1 == 0) { return; } 00279 s0= range (s0, k_out - 1, m0); 00280 m0 -= k_out - 1; m1 -= k_out - 1; 00281 } 00282 s0 /= den_R; s1 /= den_R; 00283 if (k < k_out + m0 - m1) return; 00284 C c0= s0[m0-1], c1= s1[m1-1], den_S= square_op::op (c0); 00285 C a= defected_pow (c1, c0, m0 - m1 - 1); 00286 t0= (m0 == m1 + 1) ? s1 : ((a * s1) / c0); 00287 C b0= t0[m1-1]; 00288 t1= rem (b0 * c1 * s0, s1, q); 00289 l0= N(t0), l1= N(t1), l= N(q); 00290 matrix<Polynomial> num_S (Polynomial (C(0)), 2, 2); 00291 num_S(0,0)= 0 ; num_S(0,1)= a * c0; 00292 if ((m0-m1-1) & 1) { num_S(1,0)= (-b0) * c1; num_S(1,1)= q; } 00293 else { num_S(1,0)= b0 * c1; num_S(1,1)= -q; } 00294 Q << num_S; rho << den_S; 00295 subresultant_compose (num_R, num_S, den_S); k_out += l - 1; 00296 if (defected && l0 >= l-1 && l1 >= l-1) { 00297 t0= range (t0, l - 1, l0); t1= range (t1, l - 1, l1); 00298 l0 -= l - 1; l1 -= l - 1; 00299 } 00300 t1 /= ((m0-m1-1) & 1) ? (-den_S) : den_S; 00301 C det_num_R= num_R(0,0)[0] * num_R(1,1)[0] - num_R(1,0)[0] * num_R(0,1)[0]; 00302 if (t1 == 0) { return; } 00303 half_subresultant_rec (t0, t1, defected, det_num_R, 00304 num_S, den_S, h1, Q, rho, k - k_out + 1); 00305 VERIFY (h1 <= k - k_out + 1, "bug"); 00306 subresultant_compose (num_R, num_S, den_S); k_out += h1 - 1; } 00307 00308 TMPLP static void 00309 half_subresultant (const Polynomial& f, const Polynomial& g, 00310 matrix<Polynomial>& R, 00311 vector<matrix<Polynomial> >& Q, vector<C>& rho, nat k) { 00312 // Handle the two first (particular) rounds before entering the recurrence. 00313 nat n= N(f), m= N(g), k_out, k_rem; 00314 VERIFY (m > 1 && n >= m, "bad input sizes"); 00315 VERIFY (k <= n, "index k out of range"); 00316 C d= binpow (g[m-1], n-m); 00317 Polynomial q; 00318 Polynomial s0= g, s1= prem (f, g, q); k_rem = k - N(q) + 1; 00319 nat m0= N(s0), m1= N(s1); 00320 R= matrix<Polynomial> (Polynomial (C(0)), 2, 2); 00321 R(0,0)= 0 ; R(0,1)= 1; 00322 R(1,0)= g[m-1] * d; R(1,1)= - q; 00323 Q= vec (R); rho= vec (C(1)); 00324 if (m1 == 0 || k < n - m1 + 1) return; 00325 C c0= s0[m0-1], c1= s1[m1-1]; 00326 C a= defected_pow (c1, d, m0-m1-1); 00327 Polynomial t0= (m0 == m1+1) ? s1 : ((a * s1) / d); 00328 C b0= t0[m1-1]; 00329 Polynomial t1= rem (b0 * c1 * s0, s1, q); k_rem -= N(q) - 1; 00330 matrix<Polynomial> num_S (Polynomial (C(0)), 2, 2); C den_S (d * c0); 00331 t1 /= ((m0-m1-1) & 1) ? -den_S : den_S; 00332 num_S(0,0)= 0 ; num_S(0,1)= a * c0; 00333 if ((m0-m1-1) & 1) { num_S(1,0)= -(b0 * c1); num_S(1,1)= q; } 00334 else { num_S(1,0)= b0 * c1 ; num_S(1,1)= -q; } 00335 Q << num_S; rho << den_S; 00336 subresultant_compose (R, num_S, den_S); 00337 if (N(t1) == 0 || k < n - N(t1) + 1) return; 00338 C det_R= R(0,0)[0] * R(1,1)[0] - R(1,0)[0] * R(0,1)[0]; 00339 half_subresultant_rec (t0, t1, false, det_R, 00340 num_S, den_S, k_out, Q, rho, k_rem); 00341 subresultant_compose (R, num_S, den_S); } 00342 00343 TMPLP static Polynomial 00344 _half_gcd (const Polynomial& f, const Polynomial& g, 00345 const Polynomial& first_prem) { 00346 // Special support for multi_gcd below: the first pseudo 00347 // remainder is given as an argument. 00348 // The gcd of the contents is not taken into account within this function. 00349 nat n= N(f), m= N(g); 00350 VERIFY (m > 1 && n >= m, "bad input sizes"); 00351 00352 C d= binpow (g[m-1], n-m); 00353 Polynomial q, s0= g, s1= first_prem; 00354 nat m0= N(s0), m1= N(s1); 00355 if (m1 == 0) return g; 00356 if (m1 == 1) return s1; 00357 00358 C c0= s0[m0-1], c1= s1[m1-1]; 00359 C a= defected_pow (c1, d, m0-m1-1); 00360 Polynomial t0= (m0 == m1+1) ? s1 : ((a * s1) / d); 00361 C b0= t0[m1-1]; 00362 Polynomial t1= rem (b0 * c1 * s0, s1, q); 00363 if (N(t1) == 0) return s1; 00364 if (N(t1) == 1) return t1; 00365 matrix<Polynomial> num_S (Polynomial (C(0)), 2, 2); C den_S (d * c0); 00366 t1 /= ((m0-m1-1) & 1) ? -den_S : den_S; 00367 num_S(0,0)= 0 ; num_S(0,1)= a * c0; 00368 if ((m0-m1-1) & 1) { num_S(1,0)= -(b0 * c1); num_S(1,1)= q; } 00369 else { num_S(1,0)= b0 * c1 ; num_S(1,1)= -q; } 00370 00371 C den= (- g[m-1] * d * (num_S(0,0)[0] * num_S(1,1)[0] 00372 - num_S(1,0)[0] * num_S(0,1)[0])) / den_S; 00373 vector<matrix<Polynomial> > Q; vector<C> rho; 00374 matrix<Polynomial> num_T (Polynomial (C(0)), 2, 2); C den_T; nat k_out; 00375 half_subresultant_rec (t0, t1, false, den, 00376 num_T, den_T, k_out, Q, rho, N(t1)); 00377 Polynomial h; 00378 nat k= N(t1) - degree (num_T(1,0)); 00379 h= range (range (num_T(1,0), 0, k) * range (t0, 0, k) + 00380 range (num_T(1,1), 0, k) * range (t1, 0, k), 0, k); 00381 if (h != 0) return (den * h) / den_T; 00382 k= N(t1) - degree (num_T(0,0)); 00383 h= range (range (num_T(0,0), 0, k) * range (t0, 0, k) + 00384 range (num_T(0,1), 0, k) * range (t1, 0, k), 0, k); 00385 VERIFY (h != 0, "bug"); 00386 return (den * h) / den_T; } 00387 00388 public: 00389 00390 TMPLP static void 00391 subresultant_sequence (const Polynomial& f, const Polynomial& g, 00392 vector<Polynomial>& res, 00393 vector<Polynomial>& cof, vector<Polynomial>& cog, 00394 Polynomial& d1, Polynomial& u1, Polynomial& v1, 00395 Polynomial& d2, Polynomial& u2, Polynomial& v2, 00396 nat dest_deg) { 00397 // See documentation in subresultant_naive.hpp. 00398 VERIFY (degree (f) >= degree (g) && degree (g) > 0, "incorrect degrees"); 00399 nat n= degree (f), m= degree (g), k; 00400 nat min_deg_res= (d1 != 0 || d2 != 0) ? dest_deg : m; 00401 for (k= min_deg_res; k+1 > 0; k--) 00402 if (k < N(res) && res[k] != 0) min_deg_res= k; 00403 nat min_deg_cof= (u1 != 0 || u2 != 0) ? dest_deg : m; 00404 for (k= min_deg_cof; k+1 > 0; k--) 00405 if (k < N(cof) && cof[k] != 0) min_deg_cof= k; 00406 nat min_deg_cog= (v1 != 0 || v2 != 0) ? dest_deg : m; 00407 for (k= min_deg_cog; k+1 > 0; k--) 00408 if (k < N(cog) && cog[k] != 0) min_deg_cog= k; 00409 nat min_deg_co= min (min_deg_cof, min_deg_cog); 00410 bool opt_res= res != 0 || d1 != 0 || d2 != 0; 00411 bool opt_cof= cof != 0 || u1 != 0 || u2 != 0; 00412 bool opt_cog= cog != 0 || v1 != 0 || v2 != 0; 00413 if (!(opt_res || opt_cof || opt_cog)) return; 00414 vector<matrix<Polynomial> > Q; vector<C> rho; matrix<Polynomial> R; 00415 half_subresultant (f, g, R, Q, rho, n + 1 - dest_deg); 00416 if (u1 != 0) u1= R(0,0); if (v1 != 0) v1= R(0,1); 00417 if (u2 != 0) u2= R(1,0); if (v2 != 0) v2= R(1,1); 00418 if (d1 != 0) { 00419 k= N(g) - degree (R(0,0)); 00420 d1= range (range (R(0,0), 0, k) * range (f, 0, k) + 00421 range (R(0,1), 0, k) * range (g, 0, k), 0, k); 00422 } 00423 if (d2 != 0) { 00424 k= N(g) - degree (R(1,0)); 00425 d2= range (range (R(1,0), 0, k) * range (f, 0, k) + 00426 range (R(1,1), 0, k) * range (g, 0, k), 0, k); 00427 } 00428 R= identity_matrix<Polynomial> (2); 00429 vector<Polynomial> r= vec<Polynomial> (f, g); 00430 vector<nat> nn= vec<nat> (N(g)); 00431 // nn is the sequence of the successive sizes. 00432 for (nat i= 1; i < N(Q); i++) nn << (nn[i-1] - degree (Q[i](1,1))); 00433 nn << 0; nat l0= 0, l1; k= m; 00434 while (k > 0) { 00435 while ((k-1 >= N(res) || res[k-1] == 0) && 00436 (k-1 >= N(cof) || cof[k-1] == 0) && 00437 (k-1 >= N(cog) || cog[k-1] == 0) && k > 0) k--; 00438 if (k == 0) break; 00439 l1= find (nn, k); 00440 // If k is found then res[k-1] is regular. 00441 if (l1 >= N(nn)) { 00442 l1= find (nn, k+1); 00443 // If k+1 is found then res[k] is regular and res[k-1] 00444 // is defective, otherwise res[k-1] is zero. 00445 if (l1 >= N(nn)) { 00446 if (k-1 < N(res)) res[k-1] = 0; 00447 if (k-1 < N(cof)) cof[k-1] = 0; 00448 if (k-1 < N(cog)) cog[k-1] = 0; 00449 k--; continue; 00450 } 00451 k++; 00452 } 00453 subresultant_compose (R, range (Q, l0, l1+1), range (rho, l0, l1+1), 00454 k-1 >= min_deg_co ? 0 : k); 00455 if (k-1 < N(res) && res[k-1] != 0) 00456 res[k-1]= range (range (R(0,0), 0, k) * range (f, 0, k) + 00457 range (R(0,1), 0, k) * range (g, 0, k), 0, k); 00458 if (k-1 < N(cof) && cof[k-1] != 0) cof[k-1]= R(0,0); 00459 if (k-1 < N(cog) && cog[k-1] != 0) cog[k-1]= R(0,1); 00460 k--; if (k == 0) break; 00461 if (k-1 < N(res) && res[k-1] != 0) 00462 res[k-1]= range (range (R(1,0), 0, k) * range (f, 0, k) + 00463 range (R(1,1), 0, k) * range (g, 0, k), 0, k); 00464 if (k-1 < N(cof) && cof[k-1] != 0) cof[k-1]= R(1,0); 00465 if (k-1 < N(cog) && cog[k-1] != 0) cog[k-1]= R(1,1); 00466 k--; l0= l1+1; 00467 } 00468 } 00469 00470 #undef C 00471 }; // implementation<polynomial_subresultant_base,V,polynomial_gcd_ring_dicho_inc<BV> > 00472 00473 /****************************************************************************** 00474 * Dichotomic multi-gcd 00475 ******************************************************************************/ 00476 00477 template<typename V, typename W> 00478 struct implementation<polynomial_evaluate,V,polynomial_gcd_ring_dicho_inc<W> >: 00479 public implementation<polynomial_evaluate,V,W> 00480 { 00481 typedef implementation<polynomial_subresultant_base,V, 00482 polynomial_gcd_ring_dicho_inc<W> > Pol; 00483 00484 #define C typename scalar_type_helper<Polynomial>::val 00485 private: 00486 TMPLP static Polynomial 00487 gcd_with_first_prem (const Polynomial& P1, const Polynomial& P2, 00488 const Polynomial& R) { 00489 // This is a special hack: the pseudoremainder R of P1 and P2 00490 // is forwarded to the subresultant computation. 00491 // R is only used when deg(P1) >= deg (P2). 00492 nat n1= N(P1), n2= N(P2); 00493 if (n1 < n2) return gcd_op::op (P2, P1); 00494 if (n2 == 0) { return P1; } 00495 if (n1 == 0) { return P2; } 00496 if (R == 0) { 00497 C c2; Polynomial T= primitive_part (P2, c2); 00498 return T * gcd_op::op (contents (P1), c2); 00499 } 00500 Polynomial G= Pol::_half_gcd (P1, P2, R); 00501 return primitive_part (G) * gcd_op::op (contents (P1), contents (P2)); 00502 } 00503 #undef C 00504 00505 public: 00506 TMPLP static vector<Polynomial> 00507 multi_gcd (const Polynomial& P, const vector<Polynomial>& Q) { 00508 vector<Polynomial> R= prem (P, Q); 00509 for (nat i = 0; i < N(Q); i++) 00510 R[i]= gcd_with_first_prem (P, Q[i], R[i]); 00511 return R; 00512 } 00513 00514 }; // implementation<polynomial_evaluate,V,polynomial_gcd_ring_dicho_inc<W> > 00515 00516 #undef TMPL 00517 #undef TMPLP 00518 } // namespace mmx 00519 #endif //__MMX__POLYNOMIAL_RING_DICHO__HPP