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