|
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://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Polynomial/include/CGAL/Polynomial/polynomial_gcd_implementations.h $ 00016 // $Id: polynomial_gcd_implementations.h 47254 2008-12-06 21:18:27Z afabri $ 00017 // 00018 // 00019 // Author(s) : Michael Hemmer <hemmer@informatik.uni-mainz.de> 00020 00021 #ifndef CGAL_POLYNOMIAL_GCD_IMPLEMENTATIONS_H 00022 #define CGAL_POLYNOMIAL_GCD_IMPLEMENTATIONS_H 00023 00024 00025 #include <CGAL/basic.h> 00026 #include <CGAL/Polynomial.h> 00027 #include <CGAL/Real_timer.h> 00028 #include <CGAL/polynomial_utils.h> 00029 #include <CGAL/Polynomial/hgdelta_update.h> 00030 #include <CGAL/Polynomial/polynomial_gcd.h> 00031 00032 00033 namespace CGAL { 00034 namespace CGALi { 00035 00036 template <class NT> 00037 inline 00038 Polynomial<NT> gcd_utcf_UFD( 00039 Polynomial<NT> p1, Polynomial<NT> p2 00040 ) { 00041 typedef CGAL::Polynomial_traits_d<Polynomial<NT> > PT; 00042 // implemented using the subresultant algorithm for gcd computation 00043 // see [Cohen, 1993], algorithm 3.3.1 00044 // handle trivial cases 00045 if (p1.is_zero()){ 00046 if (p2.is_zero()) return Polynomial<NT>(NT(1)); 00047 else { 00048 return CGAL::canonicalize(p2); 00049 } 00050 } 00051 if (p2.is_zero()){ 00052 return CGAL::canonicalize(p1); 00053 } 00054 if (p2.degree() > p1.degree()) { 00055 Polynomial<NT> p3 = p1; p1 = p2; p2 = p3; 00056 } 00057 00058 // compute gcd of content 00059 NT p1c = p1.content(), p2c = p2.content(); 00060 NT gcdcont = CGAL::gcd(p1c,p2c); 00061 00062 // compute gcd of primitive parts 00063 p1 /= p1c; p2 /= p2c; 00064 00065 NT dummy; 00066 Polynomial<NT> q, r; 00067 00068 NT g = NT(1), h = NT(1); 00069 for (;;) { 00070 Polynomial<NT>::pseudo_division(p1, p2, q, r, dummy); 00071 if (r.is_zero()) { break; } 00072 00073 if (r.degree() == 0) { 00074 return CGAL::canonicalize(Polynomial<NT>(gcdcont)); 00075 } 00076 int delta = p1.degree() - p2.degree(); 00077 p1 = p2; 00078 p2 = r / (g * ipower(h, delta)); 00079 g = p1.lcoeff(); 00080 // h = h^(1-delta) * g^delta 00081 CGAL::CGALi::hgdelta_update(h, g, delta); 00082 } 00083 00084 p2 /= p2.content() * p2.unit_part(); 00085 00086 // combine both parts to proper gcd 00087 p2 *= gcdcont; 00088 00089 return CGAL::canonicalize(p2); 00090 } 00091 00092 template <class NT> 00093 inline 00094 Polynomial<NT> gcd_Euclidean_ring( 00095 Polynomial<NT> p1, Polynomial<NT> p2 00096 ) { 00097 // std::cout<<" gcd_Field"<<std::endl; 00098 // handle trivial cases 00099 if (p1.is_zero()){ 00100 if (p2.is_zero()) return Polynomial<NT>(NT(1)); 00101 else return p2 / p2.unit_part(); 00102 } 00103 if (p2.is_zero()) 00104 return p1 / p1.unit_part(); 00105 if (p2.degree() > p1.degree()) { 00106 Polynomial<NT> p3 = p1; p1 = p2; p2 = p3; 00107 } 00108 00109 Polynomial<NT> q, r; 00110 while (!p2.is_zero()) { 00111 Polynomial<NT>::euclidean_division(p1, p2, q, r); 00112 p1 = p2; p2 = r; 00113 } 00114 p1 /= p1.lcoeff(); 00115 p1.simplify_coefficients(); 00116 return p1; 00117 } 00118 00119 template <class NT> 00120 inline 00121 NT content_utcf_(const Polynomial<NT>& p) 00122 { 00123 typename Algebraic_structure_traits<NT>::Integral_division idiv; 00124 typename Algebraic_structure_traits<NT>::Unit_part upart; 00125 typedef typename Polynomial<NT>::const_iterator const_iterator; 00126 00127 const_iterator it = p.begin(), ite = p.end(); 00128 while (*it == NT(0)) it++; 00129 NT cont = idiv(*it, upart(*it)); 00130 for( ; it != ite; it++) { 00131 if (cont == NT(1)) break; 00132 if (*it != NT(0)) cont = CGALi::gcd_utcf_(cont, *it); 00133 } 00134 00135 return cont; 00136 } 00137 00138 00139 template <class NT> 00140 inline 00141 Polynomial<NT> gcd_utcf_Integral_domain( Polynomial<NT> p1, Polynomial<NT> p2){ 00142 // std::cout<<" gcd_utcf_Integral_domain"<<std::endl; 00143 typedef Polynomial<NT> POLY; 00144 00145 // handle trivial cases 00146 if (p1.is_zero()){ 00147 if (p2.is_zero()){ 00148 return Polynomial<NT>(NT(1)); 00149 }else{ 00150 return CGAL::canonicalize(p2); 00151 } 00152 } 00153 if (p2.is_zero()){ 00154 return CGAL::canonicalize(p1); 00155 } 00156 00157 if (p2.degree() > p1.degree()) { 00158 Polynomial<NT> p3 = p1; p1 = p2; p2 = p3; 00159 } 00160 00161 // remove redundant scalar factors 00162 p1=CGAL::canonicalize(p1); 00163 p2=CGAL::canonicalize(p2); 00164 00165 // compute content of p1 and p2 00166 NT p1c = CGALi::content_utcf_(p1); 00167 NT p2c = CGALi::content_utcf_(p2); 00168 00169 00170 // compute gcd of content 00171 NT gcdcont = CGALi::gcd_utcf_(p1c, p2c); 00172 00173 // compute gcd of primitive parts 00174 p1 = integral_division_up_to_constant_factor(p1, POLY(p1c)); 00175 p2 = integral_division_up_to_constant_factor(p2, POLY(p2c)); 00176 00177 00178 Polynomial<NT> q, r; 00179 00180 // TODO measure preformance of both methodes with respect to 00181 // univariat polynomials on Integeres 00182 // univariat polynomials on Sqrt_extension<Integer,Integer> 00183 // multivariat polynomials 00184 // May write specializations for different cases 00185 #if 0 00186 // implemented using the subresultant algorithm for gcd computation 00187 // with respect to constant scalar factors 00188 // see [Cohen, 1993], algorithm 3.3.1 00189 NT g = NT(1), h = NT(1), dummy; 00190 for (;;) { 00191 Polynomial<NT>::pseudo_division(p1, p2, q, r, dummy); 00192 if (r.is_zero()) { break; } 00193 if (r.degree() == 0) { return Polynomial<NT>(gcdcont); } 00194 int delta = p1.degree() - p2.degree(); 00195 p1 = p2; 00196 p2 = r / (g * ipower(h, delta)); 00197 g = p1.lcoeff(); 00198 // h = h^(1-delta) * g^delta 00199 CGAL::CGALi::hgdelta_update(h, g, delta); 00200 } 00201 #else 00202 // implentaion using just the 'naive' methode 00203 // but performed much better as the one by Cohen 00204 // (for univariat polynomials with Sqrt_extension coeffs ) 00205 NT dummy; 00206 for (;;) { 00207 Polynomial<NT>::pseudo_division(p1, p2, q, r, dummy); 00208 if (r.is_zero()) { break; } 00209 if (r.degree() == 0) { return Polynomial<NT>(gcdcont); } 00210 p1 = p2; 00211 p2 = r ; 00212 p2=CGAL::canonicalize(p2); 00213 } 00214 #endif 00215 00216 p2 = integral_division_up_to_constant_factor(p2, POLY(content_utcf_(p2))); 00217 00218 // combine both parts to proper gcd 00219 p2 *= gcdcont; 00220 00221 Polynomial<NT> result; 00222 00223 // make poly unique 00224 result = CGAL::canonicalize(p2); 00225 return result; 00226 } 00227 00228 00229 } // namespace CGALi 00230 00231 } // namespace CGAL 00232 00233 #endif //CGAL_POLYNOMIAL_GCD_IMPLEMENTATIONS_H
1.7.6.1