BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polynomial/modular_gcd_utcf_algorithm_M.h
Go to the documentation of this file.
00001 // Copyright (c) 2002-2008 Max-Planck-Institute Saarbruecken (Germany)
00002 //
00003 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public License as
00005 // published by the Free Software Foundation; version 2.1 of the License.
00006 // See the file LICENSE.LGPL 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://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Polynomial/include/CGAL/Polynomial/modular_gcd_utcf_algorithm_M.h $
00015 // $Id: modular_gcd_utcf_algorithm_M.h 47339 2008-12-10 10:22:51Z hemmer $
00016 //
00017 //
00018 // Author(s)     :  Dominik Huelse <dominik.huelse@gmx.de>
00019 //                  Michael Hemmer <mhemmer@uni-mainz.de>
00020 //                 
00021 // ============================================================================
00022 
00028 #ifndef CGAL_POLYNOMIAL_MODULAR_GCD_UTCF_ALGORITHM_M_H
00029 #define CGAL_POLYNOMIAL_MODULAR_GCD_UTCF_ALGORITHM_M_H 1
00030 
00031 #include <CGAL/basic.h>
00032 #include <CGAL/Residue.h>
00033 #include <CGAL/Polynomial/modular_gcd.h>
00034 #include <CGAL/Polynomial.h>
00035 #include <CGAL/Polynomial/Cached_extended_euclidean_algorithm.h>
00036 #include <CGAL/Scalar_factor_traits.h>
00037 #include <CGAL/Chinese_remainder_traits.h>
00038 #include <CGAL/Cache.h>
00039 #include <CGAL/Real_timer.h>
00040 
00041 // algorithm M for integer polynomials, without denominator bound
00042 
00043 namespace CGAL {
00044 
00045 namespace CGALi{
00046 template <class NT> Polynomial<NT> gcd_utcf_UFD(Polynomial<NT>,Polynomial<NT>);
00047 
00048 
00049 template <class NT> 
00050 Polynomial< Polynomial<NT> > modular_gcd_utcf_algorithm_M(
00051         const Polynomial< Polynomial<NT> >& FF1 ,
00052         const Polynomial< Polynomial<NT> >& FF2 ){
00053     return gcd_utcf_UFD(FF1, FF2);
00054 }
00055 
00056 template <class NT> 
00057 Polynomial<NT> modular_gcd_utcf_algorithm_M(
00058         const Polynomial<NT>& FF1 ,
00059         const Polynomial<NT>& FF2 ){
00060 
00061   // Enforce IEEE double precision and to nearest before using modular arithmetic
00062   CGAL::Protect_FPU_rounding<true> pfr(CGAL_FE_TONEAREST);
00063 
00064 //    std::cout << "start modular_gcd_utcf_algorithm_M " << std::endl;
00065 #ifdef CGAL_MODULAR_GCD_TIMER
00066     timer_init.start();
00067 #endif
00068     typedef Polynomial<NT> Poly;
00069     typedef Polynomial_traits_d<Poly> PT;
00070 
00071     typedef typename PT::Innermost_coefficient_type IC;
00072     
00073     // will paly the role of content
00074     typedef typename CGAL::Scalar_factor_traits<Poly>::Scalar  Scalar;
00075 
00076     typedef typename CGAL::Modular_traits<Poly>::Residue_type   MPoly;
00077     typedef typename CGAL::Modular_traits<Scalar>::Residue_type MScalar;
00078     
00079     typedef Chinese_remainder_traits<Poly> CRT;
00080     typename CRT::Chinese_remainder chinese_remainder; 
00081     
00082     CGAL::Real_timer timer; 
00083     
00084  
00085     if(FF1.is_zero()){
00086         if(FF2.is_zero()){
00087             return Poly(1);// TODO: return 0 for CGAL 
00088         }
00089         else{
00090             //      std::cout<<"\nFF1 is zero"<<std::endl;
00091 
00092             return CGAL::canonicalize(FF2);
00093         }
00094     }
00095     if(FF2.is_zero()){
00096         return CGAL::canonicalize(FF1);
00097     }
00098     if(FF1.degree() == 0 || FF2.degree() == 0){
00099         Poly result;
00100         result = CGAL::gcd(FF1.content(),FF2.content());
00101         return CGAL::canonicalize(result);
00102     }
00103         
00104     Poly F1 = CGAL::canonicalize(FF1);
00105     Poly F2 = CGAL::canonicalize(FF2);
00106        
00107     Scalar f1 = scalar_factor(F1.lcoeff());  // ilcoeff(F1) 
00108     Scalar f2 = scalar_factor(F2.lcoeff());  // ilcoeff(F2) 
00109     Scalar g_ = scalar_factor(f1,f2);
00110     
00111     //std::cout <<" g_   : "<< g_ << std::endl;
00112     
00113     bool solved = false;
00114     int prime_index = -1;
00115     int n = 0; // number of lucky primes 
00116     int degree_F1 = F1.degree();
00117     int degree_F2 = F2.degree();
00118     int degree_e = std::min(degree_F1,degree_F2);
00119 
00120     MScalar mg_;
00121     MPoly   mF1,mF2,mG_;
00122 
00123     typename CRT::Scalar_type p,q,pq,s,t;
00124     Poly Gs,H1s,H2s, Gs_old; // s =^ star 
00125 #ifdef CGAL_MODULAR_GCD_TIMER
00126     timer_init.stop();
00127 #endif
00128 
00129     while(!solved){
00130         do{
00131             //---------------------------------------
00132             //choose prime not deviding f1 or f2
00133             MScalar tmp1, tmp2;
00134             do{
00135                 int current_prime = -1;
00136                 prime_index++;
00137                 if(prime_index >= 2000){
00138                     std::cerr<<"primes in the array exhausted"<<std::endl;
00139                     current_prime = CGALi::get_next_lower_prime(current_prime);
00140                 }
00141                 else{
00142                     current_prime = CGALi::primes[prime_index];
00143                 }
00144                 CGAL::Residue::set_current_prime(current_prime);
00145 #ifdef CGAL_MODULAR_GCD_TIMER
00146                 timer_image.start();
00147 #endif
00148                 tmp1 = CGAL::modular_image(f1);
00149                 tmp2 = CGAL::modular_image(f2);
00150 #ifdef CGAL_MODULAR_GCD_TIMER
00151                 timer_image.stop();
00152 #endif
00153             }
00154             while(!(( tmp1 != 0 ) && ( tmp2 != 0 )));
00155             // --------------------------------------
00156             // invoke gcd for current prime
00157 #ifdef CGAL_MODULAR_GCD_TIMER
00158             timer_image.start();
00159 #endif
00160             mg_ = CGAL::modular_image(g_);
00161             mF1 = CGAL::modular_image(F1);
00162             mF2 = CGAL::modular_image(F2);
00163 #ifdef CGAL_MODULAR_GCD_TIMER
00164             timer_image.stop();
00165             // replace mG_ = CGAL::gcd (mF1,mF2)*MPoly(mg_); for multivariat
00166             timer_gcd.start();
00167 #endif
00168             mG_ = CGAL::gcd(mF1,mF2)*MPoly(mg_);
00169 #ifdef CGAL_MODULAR_GCD_TIMER
00170             timer_gcd.stop();
00171 #endif
00172             
00173             //mH1 = CGAL::integral_div(mF1,mG_);
00174             //mH2 = CGAL::integral_div(mF2,mG_);
00175             //---------------------------------------
00176             // return if G is constant 
00177             if (mG_ == MPoly(1)) return Poly(1);
00178             // --------------------------------------
00179         }// repeat until mG_ degree is less equal the known bound
00180          // check prime 
00181         while( mG_.degree() > degree_e);
00182        
00183         if( mG_.degree() < degree_e ){
00184             if( n != 0 ) std::cout << "UNLUCKY PRIME !!"<< std::endl; 
00185 
00186             // restart chinese remainder 
00187             // ignore previous unlucky primes
00188             n=1; 
00189             degree_e= mG_.degree();
00190         }else{
00191             CGAL_postcondition( mG_.degree() == degree_e);
00192             n++; // increase number of lucky primes
00193         }
00194      
00195         // --------------------------------------
00196         // try chinese remainder
00197         
00198 //        std::cout <<" chinese remainder round :" << n << std::endl; 
00199         typename CGAL::Modular_traits<Poly>::Modular_image_representative inv_map;
00200         if(n == 1){ 
00201             // init chinese remainder
00202             q =  CGAL::Residue::get_current_prime(); // implicit ! 
00203             Gs_old  = Gs  = inv_map(mG_);
00204             
00205             //H1s_old = H1s = inv_map(mH1);
00206             //H2s_old = H2s = inv_map(mH2);
00207         }else{
00208             // continue chinese remainder
00209             
00210             p = CGAL::Residue::get_current_prime(); // implicit! 
00211              
00212             Gs_old  = Gs ;
00213             //H1s_old = H1s ;
00214             //H2s_old = H2s ;
00215 #ifdef CGAL_MODULAR_GCD_TIMER
00216             timer_CR.start();
00217 #endif
00218 //            chinese_remainder(q,Gs ,p,inv_map(mG_),pq,Gs);             
00219 //            cached_extended_euclidean_algorithm(q,p,s,t);
00220             CGALi::Cached_extended_euclidean_algorithm
00221               <typename CRT::Scalar_type, 1> ceea;
00222             ceea(q,p,s,t);
00223             pq =p*q;
00224             chinese_remainder(q,p,pq,s,t,Gs,inv_map(mG_),Gs);
00225 #ifdef CGAL_MODULAR_GCD_TIMER
00226             timer_CR.stop();
00227 #endif
00228             q=pq;
00229         }
00230 
00231         try{
00232             if( n != 1 && Gs == Gs_old ){
00233                 Poly r1,r2; 
00234 #ifdef CGAL_MODULAR_GCD_TIMER
00235                 timer_division.start();
00236 #endif 
00237 
00238                 typedef CGAL::Algebraic_structure_traits< Poly > ASTE_Poly;
00239                 typename ASTE_Poly::Divides divides;
00240 
00241                 bool div1=divides(Gs,g_*F1,H1s);
00242                 bool div2=divides(Gs,g_*F2,H2s);
00243                 if (div1 && div2){
00244                     solved = true; 
00245                 }
00246                 // this is the old code
00247 //                 NT dummy; 
00248 //                Poly::euclidean_division(g_*F1,Gs,H1s,r1);
00249 //                Poly::euclidean_division(g_*F2,Gs,H2s,r2);
00250 //                if (r1.is_zero() && r2.is_zero())
00251 //                      solved = true;       
00252       
00253 #ifdef CGAL_MODULAR_GCD_TIMER
00254                 timer_division.stop();
00255 #endif
00256 //                std::cout << "number of primes used : "<< n << std::endl;
00257             } // end while
00258            
00259         }catch(...){}
00260  
00261     }
00262     
00263     
00264     //TODO CGAL: change this to multivariat content
00265 //    Scalar scalar_content_f1 = scalar_factor(FF1);
00266 //    Scalar scalar_content_f2 = scalar_factor(FF2);
00267 //    Scalar scalar_content_gcd = CGAL::gcd(scalar_content_f1,scalar_content_f2);
00268 //    Poly result = CGAL::canonicalize(Gs)*Poly(scalar_content_gcd);
00269 //    return result; 
00270 
00271     return CGAL::canonicalize(Gs);
00272     
00273 }
00274 
00275 }  // namespace CGALi
00276 
00277 }  // namespace CGAL
00278 
00279 #endif // CGAL_POLYNOMIAL_MODULAR_GCD_UTCF_ALGORITHM_M_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines