BWAPI
|
00001 // Copyright (c) 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/Algebraic_structure_traits.h $ 00015 // $Id: Algebraic_structure_traits.h 47254 2008-12-06 21:18:27Z afabri $ 00016 // 00017 // 00018 // Author(s) : Arno Eigenwillig <arno@mpi-inf.mpg.de> 00019 // Michael Hemmer <hemmer@informatik.uni-mainz.de> 00020 // 00021 // ============================================================================ 00022 00023 // TODO: The comments are all original EXACUS comments and aren't adapted. So 00024 // they may be wrong now. 00025 00026 00027 #ifndef CGAL_POLYNOMIAL_ALGEBRAIC_STRUCTURE_TRAITS_H 00028 #define CGAL_POLYNOMIAL_ALGEBRAIC_STRUCTURE_TRAITS_H 00029 00030 #include <CGAL/basic.h> 00031 #include <CGAL/Coercion_traits.h> 00032 #include <CGAL/Polynomial/modular_filter.h> 00033 00034 CGAL_BEGIN_NAMESPACE 00035 00036 // Extend to a UFDomain as coefficient range 00037 // Forward declaration for <NiX/polynomial_gcd.h> for NT_traits<Poly...>::Gcd 00038 namespace CGALi { 00039 template <class NT> inline 00040 Polynomial<NT> gcd(const Polynomial<NT>&, const Polynomial<NT>&); 00041 } // namespace CGALi 00042 00043 00044 // Now we wrap up all of this in the actual NT_traits 00045 // specialization for Polynomial<NT> 00074 // Algebraic structure traits 00075 00076 template< class POLY, class Algebraic_type > 00077 class Polynomial_algebraic_structure_traits_base; 00078 00079 // The most basic suite of algebraic operations, suitable for the 00080 // most basic kind of coefficient range, viz. a IntegralDomainWithoutDiv. 00081 template< class POLY > 00082 class Polynomial_algebraic_structure_traits_base< POLY, 00083 Integral_domain_without_division_tag > 00084 : public Algebraic_structure_traits_base< POLY, 00085 Integral_domain_without_division_tag > { 00086 public: 00087 typedef Integral_domain_without_division_tag Algebraic_category; 00088 00089 class Simplify 00090 : public std::unary_function< POLY&, void > { 00091 public: 00092 void operator()( POLY& p ) const { 00093 p.simplify_coefficients(); 00094 } 00095 }; 00096 00097 class Unit_part 00098 : public std::unary_function< POLY, POLY > { 00099 public: 00100 POLY operator()( const POLY& x ) const { 00101 return POLY( x.unit_part() ); 00102 } 00103 }; 00104 }; 00105 00106 // Extend to the case that the coefficient range is a IntegralDomain (with div) 00107 template< class POLY > 00108 class Polynomial_algebraic_structure_traits_base< POLY, Integral_domain_tag > 00109 : public Polynomial_algebraic_structure_traits_base< POLY, 00110 Integral_domain_without_division_tag > { 00111 public: 00112 typedef Integral_domain_tag Algebraic_category; 00113 00114 class Integral_division 00115 : public std::binary_function< POLY, POLY, POLY > { 00116 public: 00117 POLY operator()( const POLY& x, const POLY& y ) const { 00118 return x / y; 00119 } 00120 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( POLY ) 00121 }; 00122 private: 00123 typedef typename POLY::NT COEFF; 00124 typedef Algebraic_structure_traits<COEFF> AST_COEFF; 00125 typedef typename AST_COEFF::Divides Divides_coeff; 00126 typedef typename Divides_coeff::result_type BOOL; 00127 public: 00128 class Divides 00129 : public std::binary_function<POLY,POLY,BOOL>{ 00130 public: 00131 BOOL operator()( const POLY& p1, const POLY& p2) const { 00132 POLY q; 00133 return (*this)(p1,p2,q); 00134 } 00135 BOOL operator()( const POLY& p1, const POLY& p2, POLY& q) const { 00136 Divides_coeff divides_coeff; 00137 00138 q=POLY(0); 00139 00140 COEFF q1; 00141 BOOL result; 00142 if (p2.is_zero()) { 00143 q=POLY(0); 00144 return true; 00145 } 00146 00147 int d1 = p1.degree(); 00148 int d2 = p2.degree(); 00149 if ( d2 < d1 ) { 00150 q = POLY(0); 00151 return false; 00152 } 00153 00154 typedef std::vector<COEFF> Vector; 00155 Vector V_R, V_Q; 00156 V_Q.reserve(d2); 00157 if(d1==0){ 00158 for(int i=d2;i>=0;--i){ 00159 result=divides_coeff(p1[0],p2[i],q1); 00160 if(!result) return false; 00161 V_Q.push_back(q1); 00162 } 00163 V_R.push_back(COEFF(0)); 00164 } 00165 else{ 00166 V_R.reserve(d2); 00167 V_R=Vector(p2.begin(),p2.end()); 00168 Vector tmp1; 00169 tmp1.reserve(d1); 00170 for(int k=0; k<=d2-d1; ++k){ 00171 result=divides_coeff(p1[d1],V_R[d2-k],q1); 00172 if(!result) return false; 00173 V_Q.push_back(q1); 00174 for(int j=0;j<d1;++j){ 00175 tmp1.push_back(p1[j]*V_Q[k]); 00176 } 00177 V_R[d2-k]=COEFF(0); 00178 for(int i=d2-d1-k;i<=d2-k-1;++i){ 00179 V_R[i]=V_R[i]-tmp1[i-(d2-d1-k)]; 00180 } 00181 tmp1.clear(); 00182 } 00183 00184 00185 } 00186 q = POLY(V_Q.rbegin(),V_Q.rend()); 00187 POLY r = POLY(V_R.begin(),V_R.end()); 00188 00189 return (r == POLY(0)); 00190 } 00191 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(POLY,BOOL); 00192 }; 00193 }; 00194 00195 template< class POLY > 00196 class Polynomial_algebraic_structure_traits_base< POLY, Unique_factorization_domain_tag > 00197 : public Polynomial_algebraic_structure_traits_base< POLY, 00198 Integral_domain_tag > { 00199 public: 00200 typedef Unique_factorization_domain_tag Algebraic_category; 00201 00202 class Gcd 00203 : public std::binary_function< POLY, POLY, POLY > { 00204 typedef typename Polynomial_traits_d<POLY>::Multivariate_content Mcontent; 00205 typedef typename Mcontent::result_type ICoeff; 00206 00207 ICoeff gcd_help(const ICoeff& x, const ICoeff& y, Field_tag) const { 00208 return ICoeff(1); 00209 } 00210 ICoeff gcd_help(const ICoeff& x, const ICoeff& y, 00211 Unique_factorization_domain_tag) const { 00212 return CGAL::gcd(x,y); 00213 } 00214 public: 00215 POLY operator()( const POLY& x, const POLY& y ) const { 00216 typedef Algebraic_structure_traits<POLY> AST; 00217 typename AST::Integral_division idiv; 00218 typename AST::Unit_part upart; 00219 00220 // First: the extreme cases and negative sign corrections. 00221 if (CGAL::is_zero(x)) { 00222 if (CGAL::is_zero(y)) 00223 return POLY(0); 00224 return idiv(y,upart(y)); 00225 } 00226 if (CGAL::is_zero(y)) 00227 return idiv(x,upart(x)); 00228 00229 if (CGALi::may_have_common_factor(x,y)) 00230 return CGALi::gcd(x,y); 00231 else{ 00232 typename Algebraic_structure_traits<ICoeff>::Algebraic_category category; 00233 return POLY(gcd_help(Mcontent()(x),Mcontent()(y), category)); 00234 } 00235 } 00236 00237 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( POLY ) 00238 }; 00239 }; 00240 00241 // Clone this for a EuclideanRing 00242 template< class POLY > 00243 class Polynomial_algebraic_structure_traits_base< POLY, Euclidean_ring_tag > 00244 : public Polynomial_algebraic_structure_traits_base< POLY, 00245 Unique_factorization_domain_tag > { 00246 // nothing new 00247 }; 00248 00249 // Extend to a field as coefficient range 00250 template< class POLY > 00251 class Polynomial_algebraic_structure_traits_base< POLY, Field_tag > 00252 : public Polynomial_algebraic_structure_traits_base< POLY, 00253 Unique_factorization_domain_tag > { 00254 public: 00255 typedef Euclidean_ring_tag Algebraic_category; 00256 00257 class Div_mod { 00258 public: 00259 typedef POLY first_argument_type; 00260 typedef POLY second_argument_type; 00261 typedef POLY& third_argument_type; 00262 typedef POLY& fourth_argument_type; 00263 typedef void result_type; 00264 00265 void operator()( const POLY& x, const POLY& y, 00266 POLY& q, POLY& r ) const { 00267 POLY::euclidean_division( x, y, q, r ); 00268 } 00269 00270 template < class NT1, class NT2 > 00271 void operator()( const NT1& x, const NT2& y, 00272 POLY& q, POLY& r ) const { 00273 BOOST_STATIC_ASSERT((::boost::is_same< 00274 typename Coercion_traits< NT1, NT2 >::Type, POLY 00275 >::value)); 00276 00277 typename Coercion_traits< NT1, NT2 >::Cast cast; 00278 operator()( cast(x), cast(y), q, r ); 00279 } 00280 00281 }; 00282 00283 class Div 00284 : public std::binary_function< POLY, POLY, POLY > { 00285 public: 00286 POLY operator()(const POLY& a, const POLY& b) const { 00287 POLY q, r; 00288 Div_mod()(a, b, q, r); 00289 return q; 00290 } 00291 00292 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( POLY ) 00293 }; 00294 00295 class Mod 00296 : public std::binary_function< POLY, POLY, POLY > { 00297 public: 00298 POLY operator () (const POLY& a, const POLY& b) const { 00299 POLY q, r; 00300 Div_mod()(a, b, q, r); 00301 return r; 00302 } 00303 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( POLY ) 00304 }; 00305 00306 }; 00307 00308 // Clone this for a FieldWithSqrt 00309 template< class POLY > 00310 class Polynomial_algebraic_structure_traits_base< POLY, Field_with_sqrt_tag > 00311 : public Polynomial_algebraic_structure_traits_base< POLY, Field_tag > { 00312 // nothing new 00313 }; 00314 00315 // Clone this for a FieldWithKthRoot 00316 template< class POLY > 00317 class Polynomial_algebraic_structure_traits_base< POLY, 00318 Field_with_kth_root_tag > 00319 : public Polynomial_algebraic_structure_traits_base< POLY, 00320 Field_with_sqrt_tag > { 00321 // nothing new 00322 }; 00323 00324 // Clone this for a FieldWithRootOf 00325 template< class POLY > 00326 class Polynomial_algebraic_structure_traits_base< POLY, 00327 Field_with_root_of_tag > 00328 : public Polynomial_algebraic_structure_traits_base< POLY, 00329 Field_with_kth_root_tag > { 00330 // nothing new 00331 }; 00332 00333 // The actual algebraic structure traits class 00334 template< class NT > class Algebraic_structure_traits< Polynomial< NT > > 00335 : public Polynomial_algebraic_structure_traits_base< Polynomial< NT >, 00336 typename Algebraic_structure_traits< NT >::Algebraic_category > { 00337 public: 00338 typedef Polynomial<NT> Algebraic_structure; 00339 typedef typename Algebraic_structure_traits< NT >::Is_exact Is_exact; 00340 }; 00341 00342 CGAL_END_NAMESPACE 00343 #endif // CGAL_POLYNOMIAL_ALGEBRAIC_STRUCTURE_TRAITS_H