algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/polynomial_ring_dicho.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines