BWAPI
|
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://afabri@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ 00016 // $Id: Polynomial.h 46502 2008-10-28 08:36:59Z hemmer $ 00017 // 00018 // 00019 // Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de> 00020 00021 00022 #ifndef CGAL_POLYNOMIAL_RESULTANT_H 00023 #define CGAL_POLYNOMIAL_RESULTANT_H 00024 00025 // Modular arithmetic is slower, hence the default is 0 00026 #ifndef CGAL_RESULTANT_USE_MODULAR_ARITHMETIC 00027 #define CGAL_RESULTANT_USE_MODULAR_ARITHMETIC 0 00028 #endif 00029 00030 #ifndef CGAL_RESULTANT_USE_DECOMPOSE 00031 #define CGAL_RESULTANT_USE_DECOMPOSE 1 00032 #endif 00033 00034 00035 #include <CGAL/basic.h> 00036 #include <CGAL/Polynomial.h> 00037 00038 #include <CGAL/Polynomial_traits_d.h> 00039 #include <CGAL/Polynomial/Interpolator.h> 00040 #include <CGAL/Polynomial/prs_resultant.h> 00041 #include <CGAL/Polynomial/bezout_matrix.h> 00042 00043 #include <CGAL/Residue.h> 00044 #include <CGAL/Modular_traits.h> 00045 #include <CGAL/Chinese_remainder_traits.h> 00046 #include <CGAL/primes.h> 00047 #include <CGAL/Polynomial/Cached_extended_euclidean_algorithm.h> 00048 00049 CGAL_BEGIN_NAMESPACE 00050 00051 00052 // The main function provided within this file is CGAL::CGALi::resultant(F,G), 00053 // all other functions are used for dispatching. 00054 // The implementation uses interpolatation for multivariate polynomials 00055 // Due to the recursive structuture of CGAL::Polynomial<Coeff> it is better 00056 // to write the function such that the inner most variabel is eliminated. 00057 // However, CGAL::CGALi::resultant(F,G) eliminates the outer most variabel. 00058 // This is due to backward compatibility issues with code base on EXACUS. 00059 // In turn CGAL::CGALi::resultant_(F,G) eliminates the innermost variable. 00060 00061 // Dispatching 00062 // CGAL::CGALi::resultant_decompose applies if Coeff is a Fraction 00063 // CGAL::CGALi::resultant_modularize applies if Coeff is Modularizable 00064 // CGAL::CGALi::resultant_interpolate applies for multivairate polynomials 00065 // CGAL::CGALi::resultant_univariate selects the proper algorithm for IC 00066 00067 // CGAL_RESULTANT_USE_DECOMPOSE ( default = 1 ) 00068 // CGAL_RESULTANT_USE_MODULAR_ARITHMETIC (default = 0 ) 00069 00070 namespace CGALi{ 00071 00072 template <class Coeff> 00073 inline Coeff resultant_interpolate( 00074 const CGAL::Polynomial<Coeff>&, const CGAL::Polynomial<Coeff>& ); 00075 template <class Coeff> 00076 inline Coeff resultant_modularize( 00077 const CGAL::Polynomial<Coeff>&, 00078 const CGAL::Polynomial<Coeff>&, CGAL::Tag_true); 00079 template <class Coeff> 00080 inline Coeff resultant_modularize( 00081 const CGAL::Polynomial<Coeff>&, 00082 const CGAL::Polynomial<Coeff>&, CGAL::Tag_false); 00083 template <class Coeff> 00084 inline Coeff resultant_decompose( 00085 const CGAL::Polynomial<Coeff>&, 00086 const CGAL::Polynomial<Coeff>&, CGAL::Tag_true); 00087 template <class Coeff> 00088 inline Coeff resultant_decompose( 00089 const CGAL::Polynomial<Coeff>&, 00090 const CGAL::Polynomial<Coeff>&, CGAL::Tag_false); 00091 template <class Coeff> 00092 inline Coeff resultant_( 00093 const CGAL::Polynomial<Coeff>&, const CGAL::Polynomial<Coeff>&); 00094 00095 template <class Coeff> 00096 inline Coeff resultant_univariate( 00097 const CGAL::Polynomial<Coeff>& A, 00098 const CGAL::Polynomial<Coeff>& B, 00099 CGAL::Integral_domain_without_division_tag){ 00100 return hybrid_bezout_subresultant(A,B,0); 00101 } 00102 template <class Coeff> 00103 inline Coeff resultant_univariate( 00104 const CGAL::Polynomial<Coeff>& A, 00105 const CGAL::Polynomial<Coeff>& B, CGAL::Integral_domain_tag){ 00106 // this seems to help for for large polynomials 00107 return prs_resultant_integral_domain(A,B); 00108 } 00109 template <class Coeff> 00110 inline Coeff resultant_univariate( 00111 const CGAL::Polynomial<Coeff>& A, 00112 const CGAL::Polynomial<Coeff>& B, CGAL::Unique_factorization_domain_tag){ 00113 return prs_resultant_ufd(A,B); 00114 } 00115 00116 template <class Coeff> 00117 inline Coeff resultant_univariate( 00118 const CGAL::Polynomial<Coeff>& A, 00119 const CGAL::Polynomial<Coeff>& B, CGAL::Field_tag){ 00120 return prs_resultant_field(A,B); 00121 } 00122 00123 } // namespace CGALi 00124 00125 namespace CGALi{ 00126 00127 00128 template <class IC> 00129 inline IC 00130 resultant_interpolate( 00131 const CGAL::Polynomial<IC>& F, 00132 const CGAL::Polynomial<IC>& G){ 00133 CGAL_precondition(CGAL::Polynomial_traits_d<CGAL::Polynomial<IC> >::d == 1); 00134 typedef CGAL::Algebraic_structure_traits<IC> AST_IC; 00135 typedef typename AST_IC::Algebraic_category Algebraic_category; 00136 return CGALi::resultant_univariate(F,G,Algebraic_category()); 00137 } 00138 00139 template <class Coeff_2> 00140 inline 00141 CGAL::Polynomial<Coeff_2> resultant_interpolate( 00142 const CGAL::Polynomial<CGAL::Polynomial<Coeff_2> >& F, 00143 const CGAL::Polynomial<CGAL::Polynomial<Coeff_2> >& G){ 00144 00145 typedef CGAL::Polynomial<Coeff_2> Coeff_1; 00146 typedef CGAL::Polynomial<Coeff_1> POLY; 00147 typedef CGAL::Polynomial_traits_d<POLY> PT; 00148 typedef typename PT::Innermost_coefficient_type IC; 00149 00150 CGAL_precondition(PT::d >= 2); 00151 00152 typename PT::Degree degree; 00153 int maxdegree = degree(F,0)*degree(G,PT::d-1) + degree(F,PT::d-1)*degree(G,0); 00154 00155 typedef std::pair<IC,Coeff_2> Point; 00156 std::vector<Point> points; // interpolation points 00157 00158 00159 typename CGAL::Polynomial_traits_d<Coeff_1>::Degree coeff_degree; 00160 int i(-maxdegree/2); 00161 int deg_f(0); 00162 int deg_g(0); 00163 00164 00165 while((int) points.size() <= maxdegree + 1){ 00166 i++; 00167 // timer1.start(); 00168 Coeff_1 Fat_i = typename PT::Evaluate()(F,IC(i)); 00169 Coeff_1 Gat_i = typename PT::Evaluate()(G,IC(i)); 00170 // timer1.stop(); 00171 00172 int deg_f_at_i = coeff_degree(Fat_i,0); 00173 int deg_g_at_i = coeff_degree(Gat_i,0); 00174 00175 // std::cout << F << std::endl; 00176 // std::cout << Fat_i << std::endl; 00177 // std::cout << deg_f_at_i << " vs. " << deg_f << std::endl; 00178 if(deg_f_at_i > deg_f ){ 00179 points.clear(); 00180 deg_f = deg_f_at_i; 00181 CGAL_postcondition(points.size() == 0); 00182 } 00183 00184 if(deg_g_at_i > deg_g){ 00185 points.clear(); 00186 deg_g = deg_g_at_i; 00187 CGAL_postcondition(points.size() == 0); 00188 } 00189 00190 if(deg_f_at_i == deg_f && deg_g_at_i == deg_g){ 00191 // timer2.start(); 00192 Coeff_2 res_at_i = resultant_interpolate(Fat_i, Gat_i); 00193 // timer2.stop(); 00194 points.push_back(Point(IC(i),res_at_i)); 00195 00196 // std::cout << typename Polynomial_traits_d<Coeff_2>::Degree()(res_at_i) << std::endl ; 00197 } 00198 } 00199 00200 // timer3.start(); 00201 CGAL::CGALi::Interpolator<Coeff_1> interpolator(points.begin(),points.end()); 00202 Coeff_1 result = interpolator.get_interpolant(); 00203 // timer3.stop(); 00204 00205 #ifndef CGAL_NDEBUG 00206 while((int) points.size() <= maxdegree + 3){ 00207 i++; 00208 Coeff_1 Fat_i = typename PT::Evaluate()(F,IC(i)); 00209 Coeff_1 Gat_i = typename PT::Evaluate()(G,IC(i)); 00210 00211 assert(coeff_degree(Fat_i,0) <= deg_f); 00212 assert(coeff_degree(Gat_i,0) <= deg_g); 00213 00214 if(coeff_degree( Fat_i , 0) == deg_f && coeff_degree( Gat_i , 0 ) == deg_g){ 00215 Coeff_2 res_at_i = resultant_interpolate(Fat_i, Gat_i); 00216 points.push_back(Point(IC(i), res_at_i)); 00217 } 00218 } 00219 CGAL::CGALi::Interpolator<Coeff_1> 00220 interpolator_(points.begin(),points.end()); 00221 Coeff_1 result_= interpolator_.get_interpolant(); 00222 00223 // the interpolate polynomial has to be stable ! 00224 assert(result_ == result); 00225 #endif 00226 return result; 00227 } 00228 00229 template <class Coeff> 00230 inline 00231 Coeff resultant_modularize( 00232 const CGAL::Polynomial<Coeff>& F, 00233 const CGAL::Polynomial<Coeff>& G, 00234 CGAL::Tag_false){ 00235 return resultant_interpolate(F,G); 00236 }; 00237 00238 template <class Coeff> 00239 inline 00240 Coeff resultant_modularize( 00241 const CGAL::Polynomial<Coeff>& F, 00242 const CGAL::Polynomial<Coeff>& G, 00243 CGAL::Tag_true){ 00244 00245 // Enforce IEEE double precision and to nearest before using modular arithmetic 00246 CGAL::Protect_FPU_rounding<true> pfr(CGAL_FE_TONEAREST); 00247 00248 00249 typedef Polynomial_traits_d<CGAL::Polynomial<Coeff> > PT; 00250 typedef typename PT::Polynomial_d Polynomial; 00251 typedef typename PT::Innermost_coefficient_type IC; 00252 00253 00254 typedef Chinese_remainder_traits<Coeff> CRT; 00255 typedef typename CRT::Scalar_type Scalar; 00256 00257 00258 typedef typename CGAL::Modular_traits<Polynomial>::Residue_type MPolynomial; 00259 typedef typename CGAL::Modular_traits<Coeff>::Residue_type MCoeff; 00260 typedef typename CGAL::Modular_traits<Scalar>::Residue_type MScalar; 00261 00262 typename CRT::Chinese_remainder chinese_remainder; 00263 typename CGAL::Modular_traits<Coeff>::Modular_image_representative inv_map; 00264 00265 00266 typename PT::Degree_vector degree_vector; 00267 typename CGAL::Polynomial_traits_d<MPolynomial>::Degree_vector mdegree_vector; 00268 00269 bool solved = false; 00270 int prime_index = 0; 00271 int n = 0; 00272 Scalar p,q,pq,s,t; 00273 Coeff R, R_old; 00274 00275 // CGAL::Timer timer_evaluate, timer_resultant, timer_cr; 00276 00277 do{ 00278 MPolynomial mF, mG; 00279 MCoeff mR; 00280 //timer_evaluate.start(); 00281 do{ 00282 // select a prime number 00283 int current_prime = -1; 00284 prime_index++; 00285 if(prime_index >= 2000){ 00286 std::cerr<<"primes in the array exhausted"<<std::endl; 00287 assert(false); 00288 current_prime = CGALi::get_next_lower_prime(current_prime); 00289 } else{ 00290 current_prime = CGALi::primes[prime_index]; 00291 } 00292 CGAL::Residue::set_current_prime(current_prime); 00293 00294 mF = CGAL::modular_image(F); 00295 mG = CGAL::modular_image(G); 00296 00297 }while( degree_vector(F) != mdegree_vector(mF) || 00298 degree_vector(G) != mdegree_vector(mG)); 00299 //timer_evaluate.stop(); 00300 00301 //timer_resultant.start(); 00302 n++; 00303 mR = resultant_interpolate(mF,mG); 00304 //timer_resultant.stop(); 00305 //timer_cr.start(); 00306 if(n == 1){ 00307 // init chinese remainder 00308 q = CGAL::Residue::get_current_prime(); // implicit ! 00309 R = inv_map(mR); 00310 }else{ 00311 // continue chinese remainder 00312 p = CGAL::Residue::get_current_prime(); // implicit! 00313 R_old = R ; 00314 // chinese_remainder(q,Gs ,p,inv_map(mG_),pq,Gs); 00315 // cached_extended_euclidean_algorithm(q,p,s,t); 00316 CGALi::Cached_extended_euclidean_algorithm 00317 <typename CRT::Scalar_type> ceea; 00318 ceea(q,p,s,t); 00319 pq =p*q; 00320 chinese_remainder(q,p,pq,s,t,R_old,inv_map(mR),R); 00321 q=pq; 00322 } 00323 solved = (R==R_old); 00324 //timer_cr.stop(); 00325 } while(!solved); 00326 00327 //std::cout << "Time Evaluate : " << timer_evaluate.time() << std::endl; 00328 //std::cout << "Time Resultant : " << timer_resultant.time() << std::endl; 00329 //std::cout << "Time Chinese R : " << timer_cr.time() << std::endl; 00330 // CGAL_postcondition(R == resultant_interpolate(F,G)); 00331 return R; 00332 // return resultant_interpolate(F,G); 00333 } 00334 00335 00336 template <class Coeff> 00337 inline 00338 Coeff resultant_decompose( 00339 const CGAL::Polynomial<Coeff>& F, 00340 const CGAL::Polynomial<Coeff>& G, 00341 CGAL::Tag_false){ 00342 #if CGAL_RESULTANT_USE_MODULAR_ARITHMETIC 00343 typedef CGAL::Polynomial<Coeff> Polynomial; 00344 typedef typename Modular_traits<Polynomial>::Is_modularizable Is_modularizable; 00345 return resultant_modularize(F,G,Is_modularizable()); 00346 #else 00347 return resultant_modularize(F,G,CGAL::Tag_false()); 00348 #endif 00349 } 00350 00351 template <class Coeff> 00352 inline 00353 Coeff resultant_decompose( 00354 const CGAL::Polynomial<Coeff>& F, 00355 const CGAL::Polynomial<Coeff>& G, 00356 CGAL::Tag_true){ 00357 00358 typedef Polynomial<Coeff> POLY; 00359 typedef typename Fraction_traits<POLY>::Numerator_type Numerator; 00360 typedef typename Fraction_traits<POLY>::Denominator_type Denominator; 00361 typename Fraction_traits<POLY>::Decompose decompose; 00362 typedef typename Numerator::NT RES; 00363 00364 Denominator a, b; 00365 // F.simplify_coefficients(); not const 00366 // G.simplify_coefficients(); not const 00367 Numerator F0; decompose(F,F0,a); 00368 Numerator G0; decompose(G,G0,b); 00369 Denominator c = CGAL::ipower(a, G.degree()) * CGAL::ipower(b, F.degree()); 00370 typedef Algebraic_structure_traits<RES> AST_RES; 00371 typedef typename AST_RES::Algebraic_category Algebraic_category; 00372 RES res0 = CGAL::CGALi::resultant_(F0, G0); 00373 typename Fraction_traits<Coeff>::Compose comp_frac; 00374 Coeff res = comp_frac(res0, c); 00375 typename Algebraic_structure_traits<Coeff>::Simplify simplify; 00376 simplify(res); 00377 return res; 00378 } 00379 00380 00381 template <class Coeff> 00382 inline 00383 Coeff resultant_( 00384 const CGAL::Polynomial<Coeff>& F, 00385 const CGAL::Polynomial<Coeff>& G){ 00386 #if CGAL_RESULTANT_USE_DECOMPOSE 00387 typedef CGAL::Fraction_traits<Polynomial<Coeff > > FT; 00388 typedef typename FT::Is_fraction Is_fraction; 00389 return resultant_decompose(F,G,Is_fraction()); 00390 #else 00391 return resultant_decompose(F,G,CGAL::Tag_false()); 00392 #endif 00393 } 00394 00395 00396 00397 template <class Coeff> 00398 inline 00399 Coeff resultant( 00400 const CGAL::Polynomial<Coeff>& F_, 00401 const CGAL::Polynomial<Coeff>& G_){ 00402 // make the variable to be elimnated the innermost one. 00403 typedef CGAL::Polynomial_traits_d<CGAL::Polynomial<Coeff> > PT; 00404 CGAL::Polynomial<Coeff> F = typename PT::Move()(F_, PT::d-1, 0); 00405 CGAL::Polynomial<Coeff> G = typename PT::Move()(G_, PT::d-1, 0); 00406 return CGALi::resultant_(F,G); 00407 } 00408 00409 } // namespace CGALi 00410 CGAL_END_NAMESPACE 00411 00412 00413 00414 #endif // CGAL_POLYNOMIAL_RESULTANT_H 00415