BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polynomial/polynomial_gcd.h
Go to the documentation of this file.
00001 // Copyright (c) 2008 Max-Planck-Institute Saarbruecken (Germany).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License as
00006 // published by the Free Software Foundation; version 2.1 of the License.
00007 // See the file LICENSE.LGPL distributed with CGAL.
00008 //
00009 // Licensees holding a valid commercial license may use this file in
00010 // accordance with the commercial license agreement provided with the software.
00011 //
00012 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014 //
00015 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Polynomial/include/CGAL/Polynomial/polynomial_gcd.h $
00016 // $Id: polynomial_gcd.h 47254 2008-12-06 21:18:27Z afabri $
00017 //
00018 //
00019 // Author(s)     : Arno Eigenwillig <arno@mpi-inf.mpg.de>
00020 //                 Tobias Reithmann <treith@mpi-inf.mpg.de>
00021 //                 Michael Hemmer   <hemmer@informatik.uni-mainz.de>
00022 //                 Michael Kerber   <mkerber@mpi-inf.mpg.de>
00023 //                 Dominik Huelse   <dominik.huelse@gmx.de>
00024 // ============================================================================
00025 
00030 #ifndef CGAL_POLYNOMIAL_GCD_H
00031 #define CGAL_POLYNOMIAL_GCD_H
00032 
00033 #ifndef CGAL_USE_INTERNAL_MODULAR_GCD
00034 #define CGAL_USE_INTERNAL_MODULAR_GCD 1
00035 #endif
00036  
00037 #include <CGAL/basic.h>
00038 #include <CGAL/Residue.h>
00039 #include <CGAL/Polynomial.h>
00040 #include <CGAL/Scalar_factor_traits.h>
00041 #include <CGAL/Real_timer.h>
00042 #include <CGAL/Polynomial/Polynomial_type.h>
00043 #include <CGAL/Polynomial/misc.h>
00044 #include <CGAL/Polynomial/polynomial_gcd_implementations.h>
00045 #include <CGAL/polynomial_utils.h>
00046 
00047 //#undef LiS_HAVE_NTL
00048 #ifdef LiS_HAVE_NTL
00049 #include <CGAL/Polynomial/polynomial_gcd_ntl.h>
00050 #endif
00051 
00052 #if CGAL_USE_INTERNAL_MODULAR_GCD 
00053 #include <CGAL/Polynomial/modular_gcd.h>
00054 #endif
00055 
00056 
00057 // 1) gcd (basic form without cofactors)
00058 //     uses three level of dispatch on tag types:
00059 //     a) if the algebra type of the innermost coefficient is a field,
00060 //         ask for decomposability. for UFDs compute the gcd directly
00061 //     b) if NT supports integralization, the gcd is computed on
00062 //         integralized polynomials
00063 //     c) over a field (unless integralized), use the Euclidean algorithm;
00064 //         over a UFD, use the subresultant algorithm
00065 //
00066 // NOTICE: For better performance, especially in AlciX, there exist special
00067 // modular implementations for the polynmials with coefficient type 
00068 // leda::integer and the CORE::BigInt type which use, when the 
00069 // NTL library is available.
00070 // see CGAL/Polynomial/polynomial_gcd_ntl.h
00071 
00072 namespace CGAL { 
00073 namespace CGALi {
00074 
00075 template <class NT> 
00076 inline
00077 Polynomial<NT> gcd_(
00078         const Polynomial<NT>& p1, 
00079         const Polynomial<NT>& p2, 
00080         Field_tag)
00081 { 
00082     return CGAL::CGALi::gcd_utcf(p1,p2);
00083 }
00084 
00085 template <class NT> 
00086 inline
00087 Polynomial<NT> gcd_(
00088         const Polynomial<NT>& p1, 
00089         const Polynomial<NT>& p2, 
00090         Unique_factorization_domain_tag)
00091 { 
00092         typedef Polynomial<NT> POLY;
00093     typedef Polynomial_traits_d<POLY> PT;  
00094     typedef typename PT::Innermost_coefficient_type IC; 
00095         
00096     typename PT::Multivariate_content mcont; 
00097     IC mcont_p1 = mcont(p1);
00098     IC mcont_p2 = mcont(p2);
00099     
00100     typename CGAL::Coercion_traits<POLY,IC>::Cast ictp; 
00101     POLY p1_ = CGAL::integral_division(p1,ictp(mcont_p1));
00102     POLY p2_ = CGAL::integral_division(p2,ictp(mcont_p2));
00103             
00104     return CGAL::CGALi::gcd_utcf(p1_, p2_) * ictp(CGAL::gcd(mcont_p1, mcont_p2)); 
00105 }
00106 
00107 
00108 
00109 // name gcd() forwarded to the CGALi::gcd_() dispatch function
00116 template <class NT> 
00117 inline
00118 Polynomial<NT> gcd(const Polynomial<NT>& p1, const Polynomial<NT>& p2)
00119 { 
00120     typedef typename CGALi::Innermost_coefficient_type<Polynomial<NT> >::Type IC;
00121     typedef typename Algebraic_structure_traits<IC>::Algebraic_category Algebraic_category;
00122 
00123     // Filter for zero-polynomials
00124     if( p1 == Polynomial<NT>(0) )
00125         return p2;
00126     if( p2 == Polynomial<NT>(0) )
00127         return p1;
00128     return CGALi::gcd_(p1,p2,Algebraic_category());
00129 }
00130 
00131 } // namespace CGALi
00132 
00133 // 2) gcd_utcf computation
00134 //     (gcd up to scalar factors, for non-UFD non-field coefficients)
00135 //     a) first try to decompose the coefficients
00136 //     b) second dispatch depends on the algebra type of NT
00137 
00138 namespace CGALi {
00139 
00140 template <class NT> Polynomial<NT> 
00141 gcd_utcf_(const Polynomial<NT>&, const Polynomial<NT>&);
00142 
00143 // is fraction ? 
00144 template <class NT> Polynomial<NT> 
00145 gcd_utcf_is_fraction_( const Polynomial<NT>&, const Polynomial<NT>&, 
00146         ::CGAL::Tag_true); 
00147 template <class NT> Polynomial<NT> 
00148 gcd_utcf_is_fraction_( const Polynomial<NT>&, const Polynomial<NT>&, 
00149         ::CGAL::Tag_false);
00150 
00151 // is type modularizable 
00152 template <class NT> Polynomial<NT> 
00153 gcd_utcf_modularizable_algebra_( const Polynomial<NT>&, const Polynomial<NT>&, 
00154         ::CGAL::Tag_false, Integral_domain_tag);
00155 template <class NT> Polynomial<NT> 
00156 gcd_utcf_modularizable_algebra_( const Polynomial<NT>&, const Polynomial<NT>&, 
00157         ::CGAL::Tag_false, Unique_factorization_domain_tag);
00158 template <class NT> Polynomial<NT> 
00159 gcd_utcf_modularizable_algebra_( const Polynomial<NT>&, const Polynomial<NT>&, 
00160         ::CGAL::Tag_false, Field_tag);
00161 
00162 template <class NT> Polynomial<NT> 
00163 gcd_utcf_modularizable_algebra_( const Polynomial<NT>&, const Polynomial<NT>&, 
00164         ::CGAL::Tag_true, Integral_domain_tag);
00165 template <class NT> Polynomial<NT> 
00166 gcd_utcf_modularizable_algebra_( const Polynomial<NT>&, const Polynomial<NT>&, 
00167         ::CGAL::Tag_true, Unique_factorization_domain_tag);
00168 template <class NT> Polynomial<NT> 
00169 gcd_utcf_modularizable_algebra_( const Polynomial<NT>&, const Polynomial<NT>&, 
00170         ::CGAL::Tag_true, Field_tag);
00171 
00172 
00173 template <class NT> Polynomial<NT> inline
00174 gcd_utcf_(const Polynomial<NT>& p1, const Polynomial<NT>& p2){
00175     typedef CGAL::Fraction_traits< Polynomial<NT> > FT;
00176     typedef typename FT::Is_fraction Is_fraction;
00177     return gcd_utcf_is_fraction_(p1, p2, Is_fraction());
00178 }
00179 
00180 // is fraction ? 
00181 template <class NT> Polynomial<NT> inline
00182 gcd_utcf_is_fraction_( 
00183         const Polynomial<NT>& p1, 
00184         const Polynomial<NT>& p2, 
00185         ::CGAL::Tag_true)
00186 {
00187     typedef Polynomial<NT> POLY;
00188     typedef Polynomial_traits_d<POLY> PT;
00189     typedef Fraction_traits<POLY> FT;
00190 
00191     typename FT::Denominator_type dummy;
00192     typename FT::Numerator_type p1i, p2i; 
00193     
00194     typename FT::Decompose()(p1,p1i, dummy);
00195     typename FT::Decompose()(p2,p2i, dummy);
00196 
00197     typename Coercion_traits<POLY,typename FT::Numerator_type>::Cast cast;
00198     return typename PT::Canonicalize()(cast(CGALi::gcd_utcf(p1i, p2i)));
00199 }
00200 
00201 template <class NT> Polynomial<NT> inline
00202 gcd_utcf_is_fraction_( 
00203         const Polynomial<NT>& p1, 
00204         const Polynomial<NT>& p2, 
00205         ::CGAL::Tag_false)
00206 {
00207     typedef Algebraic_structure_traits< Polynomial<NT> > NTT;
00208     typedef CGAL::Modular_traits<Polynomial<NT> > MT;
00209     
00210     return gcd_utcf_modularizable_algebra_(
00211             p1,p2,typename MT::Is_modularizable(),typename NTT::Algebraic_category());
00212 }
00213 
00214 // is type modularizable 
00215 template <class NT> Polynomial<NT> inline
00216 gcd_utcf_modularizable_algebra_( 
00217         const Polynomial<NT>& p1,  
00218         const Polynomial<NT>& p2, 
00219         ::CGAL::Tag_false, 
00220         Integral_domain_tag){
00221     return CGALi::gcd_utcf_Integral_domain(p1, p2);   
00222 }
00223 template <class NT> Polynomial<NT> inline
00224 gcd_utcf_modularizable_algebra_( 
00225         const Polynomial<NT>& p1, 
00226         const Polynomial<NT>& p2, 
00227         ::CGAL::Tag_false, 
00228         Unique_factorization_domain_tag){
00229     return CGALi::gcd_utcf_UFD(p1, p2);   
00230 }
00231 template <class NT> Polynomial<NT> inline
00232 gcd_utcf_modularizable_algebra_( 
00233         const Polynomial<NT>& p1, 
00234         const Polynomial<NT>& p2, 
00235         ::CGAL::Tag_false, 
00236         Euclidean_ring_tag){
00237     return CGALi::gcd_Euclidean_ring(p1, p2);
00238 }
00239 
00240 #if CGAL_USE_INTERNAL_MODULAR_GCD 
00241 template <class NT> Polynomial<NT> inline
00242 gcd_utcf_modularizable_algebra_( 
00243         const Polynomial<NT>& p1, 
00244         const Polynomial<NT>& p2, 
00245         ::CGAL::Tag_true, 
00246         Integral_domain_tag tag){
00247     return modular_gcd_utcf(p1, p2, tag);
00248 //    return modular_gcd_utcf_with_wang(p1, p2);
00249 }
00250 template <class NT> Polynomial<NT> inline
00251 gcd_utcf_modularizable_algebra_( 
00252         const Polynomial<NT>& p1, 
00253         const Polynomial<NT>& p2, 
00254         ::CGAL::Tag_true, 
00255         Unique_factorization_domain_tag tag){
00256     return modular_gcd_utcf(p1, p2, tag);
00257 //    return modular_gcd_utcf_algorithm_M(p1, p2);
00258 }
00259 #else
00260 template <class NT> Polynomial<NT> inline
00261 gcd_utcf_modularizable_algebra_( 
00262         const Polynomial<NT>& p1, 
00263         const Polynomial<NT>& p2, 
00264         ::CGAL::Tag_true, 
00265         Integral_domain_tag){
00266     return CGALi::gcd_utcf_Integral_domain(p1, p2);
00267 }
00268 template <class NT> Polynomial<NT> inline
00269 gcd_utcf_modularizable_algebra_( 
00270         const Polynomial<NT>& p1, 
00271         const Polynomial<NT>& p2, 
00272         ::CGAL::Tag_true, 
00273         Unique_factorization_domain_tag){
00274     return CGALi::gcd_utcf_UFD(p1, p2);   
00275 }
00276 #endif
00277 
00278 template <class NT> Polynomial<NT> inline
00279 gcd_utcf_modularizable_algebra_( 
00280         const Polynomial<NT>& p1, 
00281         const Polynomial<NT>& p2, 
00282         ::CGAL::Tag_true, 
00283         Euclidean_ring_tag){
00284     // No modular algorithm available
00285     return CGALi::gcd_Euclidean_ring(p1, p2);
00286 }
00287 
00288 template <class NT> Polynomial<NT> inline
00289 gcd_utcf(const Polynomial<NT>& p1, const Polynomial<NT>& p2){
00290     return CGALi::gcd_utcf_(p1,p2);
00291 }
00292 
00293 } // namespace CGALi 
00294 
00295 
00296 // 3) extended gcd computation (with cofactors)
00297 //     with dispatch similar to gcd
00298 
00299 namespace CGALi {
00300 
00301 template <class NT> 
00302 inline
00303 Polynomial<NT> gcdex_(
00304         Polynomial<NT> x, Polynomial<NT> y,
00305         Polynomial<NT>& xf, Polynomial<NT>& yf,
00306         ::CGAL::Tag_false
00307 ) {
00308     typedef typename Algebraic_structure_traits<NT>::Algebraic_category Algebraic_category;
00309     return gcdex_(x, y, xf, yf, Algebraic_category());
00310 };
00311 
00312 template <class NT>
00313 inline
00314 Polynomial<NT> gcdex_(
00315         Polynomial<NT> x, Polynomial<NT> y,
00316         Polynomial<NT>& xf, Polynomial<NT>& yf,
00317         Field_tag
00318 ) {
00319     /* The extended Euclidean algorithm for univariate polynomials.
00320      * See [Cohen, 1993], algorithm 3.2.2
00321      */
00322     typedef Polynomial<NT> POLY;
00323     typename Algebraic_structure_traits<NT>::Integral_div idiv;
00324 
00325     // handle trivial cases
00326     if (x.is_zero()) {
00327         if (y.is_zero()) CGAL_error_msg("gcdex(0,0) is undefined");
00328         xf = NT(0); yf = idiv(NT(1), y.unit_part());
00329         return yf * y;
00330     }
00331     if (y.is_zero()) {
00332         yf = NT(0); xf = idiv(NT(1), x.unit_part());
00333         return xf * x;
00334     }
00335     bool swapped = x.degree() < y.degree();
00336     if (swapped) { POLY t = x; x = y; y = t; }
00337 
00338     // main loop
00339     POLY u = x, v = y, q, r, m11(1), m21(0), m21old;
00340     for (;;) {
00341         /* invariant: (i) There exist m12 and m22 such that
00342          *   u = m11*x + m12*y
00343          *   v = m21*x + m22*y
00344          * (ii) and we have
00345          *   gcd(u,v) == gcd(x,y)
00346          */
00347 
00348         // compute next element of remainder sequence
00349         POLY::euclidean_division(u, v, q, r);  //  u == qv + r
00350         if (r.is_zero()) break;
00351 
00352         // update u and v while preserving invariant
00353         u = v; v = r;
00354         /* Since r = u - qv, this preserves invariant (part ii)
00355          * and corresponds to the matrix assignment
00356          *   (u) = (0  1) (u)
00357          *   (v)   (1 -q) (v)
00358          */
00359         m21old = m21; m21 = m11 - q*m21; m11 = m21old;
00360         /* This simulates the matching matrix assignment
00361          *   (m11 m12) = (0  1) (m11 m12)
00362          *   (m21 m22)   (1 -q) (m21 m22)
00363          * which preserves the invariant (part i)
00364          */
00365         if (r.degree() == 0) break;
00366     }
00367     /* postcondition:  invariant holds  and  v divides u */
00368 
00369     // make gcd unit-normal
00370     m21 /= v.unit_part(); v /= v.unit_part();
00371 
00372     // obtain m22 such that  v == m21*x + m22*y
00373     POLY m22;
00374     POLY::euclidean_division(v - m21*x, y, m22, r);
00375     CGAL_assertion(r.is_zero());
00376 
00377     // check computation
00378     CGAL_assertion(v == m21*x + m22*y);
00379 
00380     // return results
00381     if (swapped) {
00382         xf = m22; yf = m21;
00383     } else {
00384         xf = m21; yf = m22;
00385     }
00386     return v;
00387 }
00388 
00389 template <class NT> 
00390 inline
00391 Polynomial<NT> gcdex_(
00392         Polynomial<NT> x, Polynomial<NT> y,
00393         Polynomial<NT>& xf, Polynomial<NT>& yf,
00394         ::CGAL::Tag_true
00395 ) {
00396     typedef Polynomial<NT> POLY;
00397     typedef typename CGAL::Fraction_traits<POLY>::Numerator_type INTPOLY;
00398     typedef typename CGAL::Fraction_traits<POLY>::Denominator_type DENOM;
00399     typedef typename INTPOLY::NT INTNT;
00400     
00401     typename CGAL::Fraction_traits<POLY>::Decompose decompose;
00402     typename CGAL::Fraction_traits<POLY>::Compose   compose;
00403     
00404 
00405     // rewrite  x as xi/xd  and  y as yi/yd  with integral polynomials xi, yi
00406     DENOM xd, yd;
00407     x.simplify_coefficients();
00408     y.simplify_coefficients();
00409     INTPOLY xi ,yi; 
00410     decompose(x,xi,xd);
00411     decompose(y,yi,yd);
00412 
00413     // compute the integral gcd with cofactors:
00414     // vi = gcd(xi, yi);  vfi*vi == xfi*xi + yfi*yi
00415     INTPOLY xfi, yfi; INTNT vfi;
00416     INTPOLY vi = pseudo_gcdex(xi, yi, xfi, yfi, vfi);
00417 
00418     // proceed to vfi*v == xfi*x + yfi*y  with v = gcd(x,y) (unit-normal)
00419     POLY v = compose(vi, vi.lcoeff());
00420     v.simplify_coefficients();
00421     CGAL_assertion(v.unit_part() == NT(1));
00422     vfi *= vi.lcoeff(); xfi *= xd; yfi *= yd;
00423 
00424     // compute xf, yf such that gcd(x,y) == v == xf*x + yf*y
00425     xf = compose(xfi, vfi);
00426     yf = compose(yfi, vfi);
00427     xf.simplify_coefficients();
00428     yf.simplify_coefficients();
00429     return v;
00430 };
00431 
00432 } // namespace CGALi
00433 
00455 template <class NT> 
00456 inline
00457 Polynomial<NT> gcdex(
00458         Polynomial<NT> p1, Polynomial<NT> p2,
00459         Polynomial<NT>& f1, Polynomial<NT>& f2
00460 ) {
00461     typedef typename CGAL::Fraction_traits< Polynomial<NT> >
00462         ::Is_fraction Is_fraction;
00463     return CGALi::gcdex_(p1, p2, f1, f2, Is_fraction());
00464 };
00465 
00466 
00483 template <class NT>
00484 inline
00485 Polynomial<NT> pseudo_gcdex(
00486 #ifdef DOXYGEN_RUNNING
00487         Polynomial<NT> p1, Polynomial<NT> p2,
00488         Polynomial<NT>& f2, Polynomial<NT>& f2, NT& v
00489 #else
00490         Polynomial<NT> x, Polynomial<NT> y,
00491         Polynomial<NT>& xf, Polynomial<NT>& yf, NT& vf
00492 #endif // DOXYGEN_RUNNING
00493 ) {
00494     /* implemented using the extended subresultant algorithm
00495      * for gcd computation with Bezout factors
00496      *
00497      * To understand this, you need to understand the computation of
00498      * cofactors as in the basic extended Euclidean algorithm (see
00499      * the code above of gcdex_(..., Field_tag)), and the subresultant
00500      * gcd algorithm, see gcd_(..., Unique_factorization_domain_tag).
00501      *
00502      * The crucial point of the combination of both is the observation
00503      * that the subresultant factor (called rho here) divided out of the
00504      * new remainder in each step can also be divided out of the
00505      * cofactors.
00506      */
00507 
00508     typedef Polynomial<NT> POLY;
00509     typename Algebraic_structure_traits<NT>::Integral_division idiv;
00510     typename Algebraic_structure_traits<NT>::Gcd          gcd;
00511 
00512     // handle trivial cases
00513     if (x.is_zero()) {
00514         if (y.is_zero()) CGAL_error_msg("gcdex(0,0) is undefined");
00515         xf = NT(0); yf = NT(1); vf = y.unit_part();
00516         return y / vf;
00517     }
00518     if (y.is_zero()) {
00519         xf = NT(1); yf = NT(0); vf = x.unit_part();
00520         return x / vf;
00521     }
00522     bool swapped = x.degree() < y.degree();
00523     if (swapped) { POLY t = x; x = y; y = t; }
00524 
00525     // compute gcd of content
00526     NT xcont = x.content(); NT ycont = y.content();
00527     NT gcdcont = gcd(xcont, ycont);
00528 
00529     // compute gcd of primitive parts
00530     POLY xprim = x / xcont; POLY yprim = y / ycont;
00531     POLY u = xprim, v = yprim, q, r;
00532     POLY m11(1), m21(0), m21old;
00533     NT g(1), h(1), d, rho;
00534     for (;;) {
00535         int delta = u.degree() - v.degree();
00536         POLY::pseudo_division(u, v, q, r, d);
00537         CGAL_assertion(d == ipower(v.lcoeff(), delta+1));
00538         if (r.is_zero()) break;
00539         rho = g * ipower(h, delta);
00540         u = v; v = r / rho;
00541         m21old = m21; m21 = (d*m11 - q*m21) / rho; m11 = m21old;
00542         /* The transition from (u, v) to (v, r/rho) corresponds
00543          * to multiplication with the matrix
00544          *   __1__ (0 rho)
00545          *    rho  (d  -q)
00546          * The comments and correctness arguments from
00547          * gcdex(..., Field_tag) apply analogously.
00548          */
00549         g = u.lcoeff();
00550         CGAL::CGALi::hgdelta_update(h, g, delta);
00551         if (r.degree() == 0) break;
00552     }
00553 
00554     // obtain v == m21*xprim + m22*yprim
00555     // the correct m21 was already computed above
00556     POLY m22;
00557     POLY::euclidean_division(v - m21*xprim, yprim, m22, r);
00558     CGAL_assertion(r.is_zero());
00559 
00560     // now obtain gcd(x,y) == gcdcont * v/v.content() == (m21*x + m22*y)/denom
00561     NT vcont = v.content(), vup = v.unit_part();
00562     v /= vup * vcont; v *= gcdcont;
00563     m21 *= ycont; m22 *= xcont;
00564     vf = idiv(xcont, gcdcont) * ycont * (vup * vcont);
00565     CGAL_assertion(vf * v == m21*x + m22*y);
00566 
00567     // return results
00568     if (swapped) {
00569         xf = m22; yf = m21;
00570     } else {
00571         xf = m21; yf = m22;
00572     }
00573     return v;
00574 }
00575 
00576 
00577 
00578 
00579 
00580 } // namespace CGAL
00581 
00582 #endif // CGAL_POLYNOMIAL_GCD_H
00583 
00584 // EOF
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines