BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polynomial/square_free_factorize.h
Go to the documentation of this file.
00001 // Copyright (c) 1997  INRIA Sophia-Antipolis (France).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00005 // the terms of the Q Public License version 1.0.
00006 // See the file LICENSE.QPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://afabri@scm.gforge.inria.fr/svn/cgal/trunk/Alpha_shapes_2/include/CGAL/Alpha_shape_2.h $
00015 // $Id: Alpha_shape_2.h 47026 2008-11-25 13:21:09Z afabri $
00016 //
00017 //
00018 // Author(s)     :  Michael Hemmer
00019 //
00020 // ============================================================================
00021 #ifndef CGAL_POLYNOMIAL_SQUARE_FREE_FACTORIZATION_H
00022 #define CGAL_POLYNOMIAL_SQUARE_FREE_FACTORIZATION_H
00023 
00024 #include <CGAL/basic.h>
00025 #include <CGAL/Polynomial/fwd.h>
00026 #include <CGAL/Polynomial/misc.h>
00027 #include <CGAL/Polynomial/Polynomial.h>
00028 
00029 CGAL_BEGIN_NAMESPACE
00030 namespace CGALi {
00031 
00032 // square-free factorization
00033 // 
00034 // the implementation uses two dispatches:
00035 //   a) first look at the coefficient's algebra type
00036 //   b) if the algebra type is of the concept field, try to decompose
00037 // the same holds for square-free factorization up to constant factors (utcf)
00038 //
00039 // sqff -------> algebra type ? ----field-----> decomposable ?
00040 //                     |                   A       |     |
00041 //                    UFD                  |       no   yes
00042 //                     |                   |       |     |
00043 //                     V                           |     |
00044 //               Yun's algo <----------------------      |
00045 //                     A                                 |
00046 //                     |                   |             |
00047 //                    UFD                  |             V
00048 //                     |                   |         decompose and use
00049 // sqff_utcf --> algebra_type ? ----field--          sqff_utcf with numerator
00050 //                     |
00051 //               integral domain
00052 //                     |
00053 //                     V
00054 //               Yun's algo (utcf)
00055 
00056 template <class IC,  class OutputIterator1, class OutputIterator2>
00057 inline int square_free_factorize(const IC&, OutputIterator1, OutputIterator2){
00058     return 0;
00059 }
00060 template <class IC,  class OutputIterator1, class OutputIterator2>
00061 inline int square_free_factorize_for_regular_polynomial(const IC&, OutputIterator1, OutputIterator2){
00062     return 0;
00063 }
00064 
00065 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00066 inline int square_free_factorize(const Polynomial<Coeff>&, OutputIterator1, OutputIterator2);
00067 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00068 inline int square_free_factorize_for_regular_polynomial(const Polynomial<Coeff>&, OutputIterator1, OutputIterator2);
00069 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00070 inline int square_free_factorize_for_regular_polynomial_(const Polynomial<Coeff>&, OutputIterator1, OutputIterator2, CGAL::Tag_true);
00071 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00072 inline int square_free_factorize_for_regular_polynomial_(const Polynomial<Coeff>&, OutputIterator1, OutputIterator2, CGAL::Tag_false);
00073 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00074 inline int square_free_factorize_for_regular_polynomial_(const Polynomial<Coeff>&, OutputIterator1, OutputIterator2, Integral_domain_tag);
00075 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00076 inline int square_free_factorize_for_regular_polynomial_(const Polynomial<Coeff>&, OutputIterator1, OutputIterator2, Unique_factorization_domain_tag);
00077 
00078 
00079 
00080 
00081 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00082 inline int square_free_factorize
00083 (const Polynomial<Coeff>&  poly, OutputIterator1 factors, OutputIterator2 multiplicities)
00084 {
00085     typedef Polynomial<Coeff> POLY;
00086     typedef Polynomial_traits_d< POLY > PT;
00087     typedef typename PT::Univariate_content_up_to_constant_factor Ucont_utcf;
00088     typedef typename PT::Integral_division_up_to_constant_factor  Idiv_utcf;
00089     
00090     if (typename PT::Total_degree()(poly) == 0){return 0;}
00091    
00092     Coeff ucont_utcf = Ucont_utcf()(poly); 
00093     POLY  regular_poly = Idiv_utcf()(poly,ucont_utcf);
00094 
00095     int result = square_free_factorize_for_regular_polynomial( 
00096             regular_poly, factors, multiplicities);
00097 
00098     if (typename PT::Total_degree()(ucont_utcf) > 0){
00099         typedef std::vector< Coeff > Factors_uc;
00100         typedef std::vector< int > Multiplicities_uc;
00101         Factors_uc factors_uc;
00102         Multiplicities_uc multiplicities_uc;
00103         result += square_free_factorize( ucont_utcf,
00104                 std::back_inserter(factors_uc),
00105                 std::back_inserter(multiplicities_uc) );
00106         
00107         for( typename Factors_uc::iterator it = factors_uc.begin(); 
00108              it != factors_uc.end(); ++it ){
00109             *factors++ = POLY(*it);
00110         }
00111         for( Multiplicities_uc::iterator it = multiplicities_uc.begin();
00112              it != multiplicities_uc.end(); ++it ){
00113             *multiplicities++ = (*it);
00114         }
00115     }
00116     return result;                                
00117 }
00118 
00119 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00120 inline int square_free_factorize_for_regular_polynomial
00121 (const Polynomial<Coeff>&  p, OutputIterator1 factors, OutputIterator2 multiplicities){
00122     typedef Polynomial<Coeff> POLY;
00123     typedef typename CGAL::Fraction_traits<POLY>::Is_fraction Is_fraction;
00124     return square_free_factorize_for_regular_polynomial_(p,factors,multiplicities,Is_fraction());
00125 }
00126 
00127 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00128 inline int square_free_factorize_for_regular_polynomial_
00129 (const Polynomial<Coeff>& p, OutputIterator1 factors, OutputIterator2 multiplicities, CGAL::Tag_true){
00130     
00131     typedef Polynomial<Coeff> POLY;
00132     typedef Polynomial_traits_d< POLY > PT;
00133     typedef Fraction_traits<POLY> FT; 
00134     
00135     typename FT::Numerator_type num; 
00136     typename FT::Denominator_type denom; 
00137     typename FT::Decompose()(p,num,denom);
00138     
00139     std::vector<typename FT::Numerator_type> ifacs;
00140     int result =  square_free_factorize_for_regular_polynomial(num,std::back_inserter(ifacs),multiplicities);
00141     
00142     typedef typename std::vector<typename FT::Numerator_type>::iterator Iterator;
00143     denom = typename FT::Denominator_type(1);
00144     for ( Iterator it = ifacs.begin(); it != ifacs.end(); ++it) {
00145         POLY q = typename FT::Compose()(*it, denom);
00146         *factors++ = typename PT::Canonicalize()(q);
00147     }
00148     
00149     return result; 
00150 }
00151 
00152 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00153 inline int square_free_factorize_for_regular_polynomial_
00154 (const Polynomial<Coeff>& p, OutputIterator1 factors, OutputIterator2 multiplicities, CGAL::Tag_false){
00155     typedef Polynomial<Coeff> POLY;
00156     typedef typename Algebraic_structure_traits<POLY>::Algebraic_category Algebraic_category;
00157     return square_free_factorize_for_regular_polynomial_(p,factors,multiplicities,Algebraic_category());
00158 }
00159 
00160 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00161 inline int square_free_factorize_for_regular_polynomial_
00162 (const Polynomial<Coeff>& p, OutputIterator1 factors, OutputIterator2 multiplicities, Integral_domain_tag){
00163     // Yun's Square-Free Factorization
00164     // see [Geddes et al, 1992], Algorithm 8.2
00165 
00166     typedef Polynomial<Coeff> POLY;
00167     typedef Polynomial_traits_d<POLY> PT;
00168     typedef typename PT::Innermost_coefficient_type IC;
00169     typename PT::Innermost_leading_coefficient ilcoeff;
00170     //typename PT::Innermost_coefficient_to_polynomial ictp;
00171     typename PT::Construct_innermost_coefficient_const_iterator_range range;
00172     typename Algebraic_extension_traits<IC>::Denominator_for_algebraic_integers dfai;
00173     typename Algebraic_extension_traits<IC>::Normalization_factor nfac;
00174     typename Scalar_factor_traits<POLY>::Scalar_factor sfac;  
00175     typename Scalar_factor_traits<POLY>::Scalar_div sdiv;
00176     typedef typename Scalar_factor_traits<POLY>::Scalar Scalar;
00177 
00178     
00179     if (typename PT::Total_degree()(p) == 0) return 0;
00180 
00181     POLY a = CGAL::canonicalize(p);
00182     POLY b = diff(a);
00183     POLY c = CGAL::CGALi::gcd_utcf(a, b);
00184 
00185     if (c == Coeff(1)) {
00186         *factors = a;
00187         *multiplicities = 1;
00188         return 1;
00189     }
00190 
00191     int i = 1, n = 0;
00192 
00193     // extending both polynomials a and b by the denominator for algebraic 
00194     // integers, which comes out from c=gcd(a,b), such that a and b are 
00195     // divisible by c
00196     IC lcoeff = ilcoeff(c);
00197     IC denom = dfai(range(c).first, range(c).second);
00198     lcoeff *= denom * nfac(denom);
00199     POLY w = (a * POLY(lcoeff)) / c;
00200     POLY y = (b * POLY(lcoeff)) / c;
00201 
00202     // extracting a common scalar factor out of w=a/c and y=b/c simultaneously,
00203     // such that the parts in z=y-w' are canceled out as they should
00204     Scalar sfactor = sfac(y,sfac(w));
00205     sdiv(w, sfactor); 
00206     sdiv(y, sfactor);
00207 
00208     POLY  z = y - diff(w);
00209     POLY g;
00210 
00211     while (!z.is_zero()) {
00212         g = CGAL::CGALi::gcd_utcf(w, z);
00213         if (g.degree() > 0) {
00214             *factors++ = g;
00215             *multiplicities++ = i;
00216             n++;
00217         }
00218         i++;
00219         lcoeff = ilcoeff(g); // same as above
00220         denom =dfai(range(c).first, range(c).second); 
00221         lcoeff *= denom * nfac(denom);
00222         w = (w * POLY(lcoeff)) / g;
00223         y = (z * POLY(lcoeff)) / g;
00224         Scalar sfactor = sfac(y,sfac(w));
00225         sdiv(w, sfactor); 
00226         sdiv(y, sfactor);
00227        
00228         z = y - diff(w);
00229     }
00230 
00231     *factors = w;
00232     *multiplicities++ = i;
00233     n++;
00234 
00235     return n;
00236 }
00237 
00238 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00239 inline int square_free_factorize_for_regular_polynomial_
00240 (const Polynomial<Coeff>& p, OutputIterator1 factors, OutputIterator2 multiplicities, Unique_factorization_domain_tag){
00241     // Yun's Square-Free Factorization
00242     // see [Geddes et al, 1992], Algorithm 8.2
00243     /* 
00244        @inproceedings{y-osfda-76,
00245        author = {David Y.Y. Yun},
00246        title = {On square-free decomposition algorithms},
00247        booktitle = {SYMSAC '76: Proceedings of the third ACM symposium on Symbolic 
00248                     and algebraic computation},
00249        year = {1976},
00250        pages = {26--35},
00251        location = {Yorktown Heights, New York, United States},
00252        doi = {http://doi.acm.org/10.1145/800205.806320},
00253        publisher = {ACM Press},
00254        address = {New York, NY, USA},
00255        }
00256     */
00257     
00258     typedef Polynomial<Coeff> POLY;
00259     typedef Polynomial_traits_d<POLY> PT;
00260 
00261     if (typename PT::Total_degree()(p) == 0) return 0;
00262     POLY a = CGAL::canonicalize(p);
00263 
00264     POLY b = diff(a);  
00265     POLY c = CGAL::gcd(a, b);
00266    
00267     if (c == Coeff(1)) {
00268         *factors = a;
00269         *multiplicities = 1;
00270         return 1;
00271     }
00272 
00273     int i = 1, n = 0;
00274     POLY w = a/c, y = b/c, z = y - diff(w), g;
00275     while (!z.is_zero()) {
00276         g = CGAL::gcd(w, z);
00277         if (g.degree() > 0) {
00278             *factors++ = g;
00279             *multiplicities++ = i;
00280             n++;
00281         }
00282         i++;
00283         w /= g;
00284         y = z/g;
00285         z = y - diff(w);
00286     }
00287     *factors = w;
00288     *multiplicities++ = i;
00289     n++;
00290 
00291     return n;
00292 }
00293 
00294 
00295 
00296 
00297 // square-free factorization utcf 
00298 
00299 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00300 inline int square_free_factorize_utcf
00301 (const Polynomial<Coeff>&  p, OutputIterator1 factors, OutputIterator2 multiplicities)
00302 {
00303     return square_free_factorize(p,factors,multiplicities);
00304 }
00305 
00306 template <class Coeff,  class OutputIterator1, class OutputIterator2>
00307 inline int square_free_factorize_utcf_for_regular_polynomial
00308 (const Polynomial<Coeff>&  p, OutputIterator1 factors, OutputIterator2 multiplicities)
00309 {
00310     return square_free_factorize_for_regular_polynomial(p,factors,multiplicities);
00311 }
00312 
00313 
00314 
00315 
00316 // filtered square-free factorization
00317 
00318 // ### filtered versions #### 
00319 
00325 template <class Coeff, class OutputIterator1, class OutputIterator2> 
00326 inline
00327 int filtered_square_free_factorize(
00328                                        Polynomial<Coeff> p,
00329                                        OutputIterator1 factors,
00330                                        OutputIterator2 multiplicities)
00331 {
00332   if(CGAL::CGALi::may_have_multiple_factor(p)){
00333       return CGALi::square_free_factorize(p, factors, multiplicities);
00334   }else{
00335       *factors++        = CGAL::canonicalize(p);
00336       *multiplicities++ = 1;
00337       return 1;
00338   }
00339 }
00340 
00346 template <class Coeff,  class OutputIterator1, class OutputIterator2> 
00347 inline
00348 int filtered_square_free_factorize_utcf( const Polynomial<Coeff>& p, 
00349                                          OutputIterator1 factors,
00350                                          OutputIterator2 multiplicities)
00351 {
00352     return filtered_square_free_factorize(p,factors,multiplicities);
00353 }
00354 
00355 } // namespace CGALi
00356 CGAL_END_NAMESPACE
00357 
00358 #endif // CGAL_POLYNOMIAL_SQUARE_FREE_FACTORIZATION_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines