BWAPI
|
00001 // Copyright (c) 2006-2007 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/Algebraic_foundations/include/CGAL/Algebraic_structure_traits.h $ 00016 // $Id: Algebraic_structure_traits.h 45630 2008-09-18 13:53:47Z hemmer $ 00017 // 00018 // 00019 // Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de> 00020 // 00021 // ============================================================================= 00022 00023 00024 #ifndef CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H 00025 #define CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H 00026 00027 #include <CGAL/number_type_basic.h> 00028 #include <CGAL/type_traits.h> 00029 00030 CGAL_BEGIN_NAMESPACE 00031 00032 // REMARK: Some of the following comments and references are just copy & pasted 00033 // from EXACUS and have to be adapted/removed in the future. 00034 00035 // The tags for Algebra_type corresponding to the number type concepts 00036 // =================================================================== 00037 00039 struct Integral_domain_without_division_tag {}; 00040 00042 struct Integral_domain_tag : public Integral_domain_without_division_tag {}; 00043 00045 struct Unique_factorization_domain_tag : public Integral_domain_tag {}; 00046 00048 struct Euclidean_ring_tag : public Unique_factorization_domain_tag {}; 00049 00051 struct Field_tag : public Integral_domain_tag {}; 00052 00054 struct Field_with_sqrt_tag : public Field_tag {}; 00055 00057 struct Field_with_kth_root_tag : public Field_with_sqrt_tag {}; 00058 00060 struct Field_with_root_of_tag : public Field_with_kth_root_tag {}; 00061 00062 00063 // The algebraic structure traits template 00064 // ========================================================================= 00065 template< class Type_ > 00066 class Algebraic_structure_traits { 00067 public: 00068 typedef Type_ Type; 00069 typedef Null_tag Algebraic_category; 00070 typedef Null_tag Is_exact; 00071 typedef Null_tag Is_numerical_sensitive; 00072 00073 typedef Null_functor Simplify; 00074 typedef Null_functor Unit_part; 00075 typedef Null_functor Integral_division; 00076 typedef Null_functor Is_square; 00077 typedef Null_functor Gcd; 00078 typedef Null_functor Div_mod; 00079 typedef Null_functor Div; 00080 typedef Null_functor Mod; 00081 typedef Null_functor Square; 00082 typedef Null_functor Is_zero; 00083 typedef Null_functor Is_one; 00084 typedef Null_functor Sqrt; 00085 typedef Null_functor Kth_root; 00086 typedef Null_functor Root_of; 00087 typedef Null_functor Divides; 00088 }; 00089 00090 // The algebraic structure traits base class 00091 // ========================================================================= 00092 template< class Type, class Algebra_type > 00093 class Algebraic_structure_traits_base; 00094 00098 template< class Type_ > 00099 class Algebraic_structure_traits_base< Type_, Null_tag > { 00100 public: 00101 typedef Type_ Type; 00102 typedef Null_tag Algebraic_category; 00103 typedef Tag_false Is_exact; 00104 typedef Null_tag Is_numerical_sensitive; 00105 typedef Null_tag Boolean; 00106 00107 // does nothing by default 00108 class Simplify 00109 : public std::unary_function< Type&, void > { 00110 public: 00111 void operator()( Type& ) const {} 00112 }; 00113 00114 typedef Null_functor Unit_part; 00115 typedef Null_functor Integral_division; 00116 typedef Null_functor Is_square; 00117 typedef Null_functor Gcd; 00118 typedef Null_functor Div_mod; 00119 typedef Null_functor Div; 00120 typedef Null_functor Mod; 00121 typedef Null_functor Square; 00122 typedef Null_functor Is_zero; 00123 typedef Null_functor Is_one; 00124 typedef Null_functor Sqrt; 00125 typedef Null_functor Kth_root; 00126 typedef Null_functor Root_of; 00127 typedef Null_functor Divides; 00128 }; 00129 00135 template< class Type_ > 00136 class Algebraic_structure_traits_base< Type_, 00137 Integral_domain_without_division_tag > 00138 : public Algebraic_structure_traits_base< Type_, 00139 Null_tag > { 00140 public: 00141 typedef Type_ Type; 00142 typedef Integral_domain_without_division_tag Algebraic_category; 00143 typedef bool Boolean; 00144 00145 // returns Type(1) by default 00146 class Unit_part 00147 : public std::unary_function< Type, Type > { 00148 public: 00149 Type operator()( const Type& x ) const { 00150 return( x < Type(0)) ? 00151 Type(-1) : Type(1); 00152 } 00153 }; 00154 00155 class Square 00156 : public std::unary_function< Type, Type > { 00157 public: 00158 Type operator()( const Type& x ) const { 00159 return x*x; 00160 } 00161 }; 00162 00163 class Is_zero 00164 : public std::unary_function< Type, bool > { 00165 public: 00166 bool operator()( const Type& x ) const { 00167 return x == Type(0); 00168 } 00169 }; 00170 00171 class Is_one 00172 : public std::unary_function< Type, bool > { 00173 public: 00174 bool operator()( const Type& x ) const { 00175 return x == Type(1); 00176 } 00177 }; 00178 00179 }; 00180 00181 00188 template< class Type_ > 00189 class Algebraic_structure_traits_base< Type_, 00190 Integral_domain_tag > 00191 : public Algebraic_structure_traits_base< Type_, 00192 Integral_domain_without_division_tag > { 00193 public: 00194 typedef Type_ Type; 00195 typedef Integral_domain_tag Algebraic_category; 00196 }; 00197 00198 00205 template< class Type_ > 00206 class Algebraic_structure_traits_base< Type_, 00207 Unique_factorization_domain_tag > 00208 : public Algebraic_structure_traits_base< Type_, 00209 Integral_domain_tag > { 00210 public: 00211 typedef Type_ Type; 00212 typedef Unique_factorization_domain_tag Algebraic_category; 00213 00214 // Default implementation of Divides functor for unique factorization domains 00215 // x divides y if gcd(y,x) equals x up to inverses 00216 class Divides 00217 : public std::binary_function<Type,Type,bool>{ 00218 public: 00219 bool operator()( const Type& x, const Type& y) const { 00220 typedef CGAL::Algebraic_structure_traits<Type> AST; 00221 typename AST::Gcd gcd; 00222 typename AST::Unit_part unit_part; 00223 typename AST::Integral_division idiv; 00224 return gcd(y,x) == idiv(x,unit_part(x)); 00225 } 00226 // second operator computing q = x/y 00227 bool operator()( const Type& x, const Type& y, Type& q) const { 00228 typedef CGAL::Algebraic_structure_traits<Type> AST; 00229 typename AST::Integral_division idiv; 00230 bool result = (*this)(x,y); 00231 if( result == true ) 00232 q = idiv(x,y); 00233 return result; 00234 } 00235 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,bool) 00236 }; 00237 }; 00238 00239 00242 template< class Type_ > 00243 class Algebraic_structure_traits_base< Type_, 00244 Euclidean_ring_tag > 00245 : public Algebraic_structure_traits_base< Type_, 00246 Unique_factorization_domain_tag > { 00247 public: 00248 typedef Type_ Type; 00249 typedef Euclidean_ring_tag Algebraic_category; 00250 00251 // maps to \c Div by default. 00252 class Integral_division 00253 : public std::binary_function< Type, Type, 00254 Type > { 00255 public: 00256 Type operator()( 00257 const Type& x, 00258 const Type& y) const { 00259 typedef Algebraic_structure_traits<Type> AST; 00260 typedef typename AST::Is_exact Is_exact; 00261 typename AST::Div actual_div; 00262 00263 CGAL_precondition_msg( 00264 !Is_exact::value || actual_div( x, y) * y == x, 00265 "'x' must be divisible by 'y' in " 00266 "Algebraic_structure_traits<...>::Integral_div()(x,y)" ); 00267 return actual_div( x, y); 00268 } 00269 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) 00270 }; 00271 00272 // Algorithm from NiX/euclids_algorithm.h 00273 class Gcd 00274 : public std::binary_function< Type, Type, 00275 Type > { 00276 public: 00277 Type operator()( 00278 const Type& x, 00279 const Type& y) const { 00280 typedef Algebraic_structure_traits<Type> AST; 00281 typename AST::Mod mod; 00282 typename AST::Unit_part unit_part; 00283 typename AST::Integral_division integral_div; 00284 // First: the extreme cases and negative sign corrections. 00285 if (x == Type(0)) { 00286 if (y == Type(0)) 00287 return Type(0); 00288 return integral_div( y, unit_part(y) ); 00289 } 00290 if (y == Type(0)) 00291 return integral_div(x, unit_part(x) ); 00292 Type u = integral_div( x, unit_part(x) ); 00293 Type v = integral_div( y, unit_part(y) ); 00294 // Second: assuming mod is the most expensive op here, 00295 // we don't compute it unnecessarily if u < v 00296 if (u < v) { 00297 v = mod(v,u); 00298 // maintain invariant of v > 0 for the loop below 00299 if ( v == Type(0) ) 00300 return u; 00301 } 00302 // Third: generic case of two positive integer values and u >= v. 00303 // The standard loop would be: 00304 // while ( v != 0) { 00305 // int tmp = mod(u,v); 00306 // u = v; 00307 // v = tmp; 00308 // } 00309 // return u; 00310 // 00311 // But we want to save us all the variable assignments and unroll 00312 // the loop. Before that, we transform it into a do {...} while() 00313 // loop to reduce branching statements. 00314 Type w; 00315 do { 00316 w = mod(u,v); 00317 if ( w == Type(0)) 00318 return v; 00319 u = mod(v,w); 00320 if ( u == Type(0)) 00321 return w; 00322 v = mod(w,u); 00323 } while (v != Type(0)); 00324 return u; 00325 } 00326 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) 00327 }; 00328 00329 // based on \c Div and \c Mod. 00330 class Div_mod { 00331 public: 00332 typedef Type first_argument_type; 00333 typedef Type second_argument_type; 00334 typedef Type& third_argument_type; 00335 typedef Type& fourth_argument_type; 00336 typedef void result_type; 00337 void operator()( const Type& x, 00338 const Type& y, 00339 Type& q, Type& r) const { 00340 typedef Algebraic_structure_traits<Type> Traits; 00341 typename Traits::Div actual_div; 00342 typename Traits::Mod actual_mod; 00343 q = actual_div( x, y ); 00344 r = actual_mod( x, y ); 00345 return; 00346 } 00347 00348 template < class NT1, class NT2 > 00349 void operator()( 00350 const NT1& x, 00351 const NT2& y, 00352 Type& q, 00353 Type& r ) const { 00354 typedef Coercion_traits< NT1, NT2 > CT; 00355 typedef typename CT::Type Type; 00356 BOOST_STATIC_ASSERT(( 00357 ::boost::is_same<Type , Type >::value)); 00358 00359 typename Coercion_traits< NT1, NT2 >::Cast cast; 00360 operator()( cast(x), cast(y), q, r ); 00361 } 00362 }; 00363 00364 // based on \c Div_mod. 00365 class Div 00366 : public std::binary_function< Type, Type, 00367 Type > { 00368 public: 00369 Type operator()( const Type& x, 00370 const Type& y) const { 00371 typename Algebraic_structure_traits<Type> 00372 ::Div_mod actual_div_mod; 00373 Type q; 00374 Type r; 00375 actual_div_mod( x, y, q, r ); 00376 return q; 00377 }; 00378 00379 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) 00380 }; 00381 00382 // based on \c Div_mod. 00383 class Mod 00384 : public std::binary_function< Type, Type, 00385 Type > { 00386 public: 00387 Type operator()( const Type& x, 00388 const Type& y) const { 00389 typename Algebraic_structure_traits<Type> 00390 ::Div_mod actual_div_mod; 00391 Type q; 00392 Type r; 00393 actual_div_mod( x, y, q, r ); 00394 return r; 00395 }; 00396 00397 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) 00398 }; 00399 00400 // Divides for Euclidean Ring 00401 class Divides 00402 : public std::binary_function<Type, Type, bool>{ 00403 public: 00404 bool operator()( const Type& x, const Type& y) const { 00405 typedef Algebraic_structure_traits<Type> AST; 00406 typename AST::Mod mod; 00407 CGAL_precondition(typename AST::Is_zero()(x) == false ); 00408 return typename AST::Is_zero()(mod(y,x)); 00409 } 00410 // second operator computing q 00411 bool operator()( const Type& x, const Type& y, Type& q) const { 00412 typedef Algebraic_structure_traits<Type> AST; 00413 typename AST::Div_mod div_mod; 00414 CGAL_precondition(typename AST::Is_zero()(x) == false ); 00415 Type r; 00416 div_mod(y,x,q,r); 00417 return (typename AST::Is_zero()(r)); 00418 } 00419 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,bool) 00420 }; 00421 }; 00422 00423 00431 // 00432 template< class Type_ > 00433 class Algebraic_structure_traits_base< Type_, Field_tag > 00434 : public Algebraic_structure_traits_base< Type_, 00435 Integral_domain_tag > { 00436 public: 00437 typedef Type_ Type; 00438 typedef Field_tag Algebraic_category; 00439 00440 // returns the argument \a a by default 00441 class Unit_part 00442 : public std::unary_function< Type, Type > { 00443 public: 00444 Type operator()( const Type& x ) const { 00445 return( x == Type(0)) ? Type(1) : x; 00446 } 00447 }; 00448 // maps to \c operator/ by default. 00449 class Integral_division 00450 : public std::binary_function< Type, Type, 00451 Type > { 00452 public: 00453 Type operator()( const Type& x, 00454 const Type& y) const { 00455 typedef Algebraic_structure_traits<Type> AST; 00456 typedef typename AST::Is_exact Is_exact; 00457 CGAL_precondition_code( bool ie = Is_exact::value; ) 00458 CGAL_precondition_msg( !ie || (x / y) * y == x, 00459 "'x' must be divisible by 'y' in " 00460 "Algebraic_structure_traits<...>::Integral_div()(x,y)" ); 00461 return x / y; 00462 } 00463 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) 00464 }; 00465 00466 // Default implementation of Divides functor for Field: 00467 // returns always true 00468 // \pre: x != 0 00469 class Divides 00470 : public std::binary_function< Type, Type, bool > { 00471 public: 00472 bool operator()( const Type& CGAL_precondition_code(x), const Type& /* y */) const { 00473 typedef Algebraic_structure_traits<Type> AST; 00474 CGAL_precondition( typename AST::Is_zero()(x) == false ); 00475 return true; 00476 } 00477 // second operator computing q 00478 bool operator()( const Type& x, const Type& y, Type& q) const { 00479 typedef Algebraic_structure_traits<Type> AST; 00480 CGAL_precondition( typename AST::Is_zero()(x) == false ); 00481 q = y/x; 00482 return true; 00483 } 00484 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,bool) 00485 }; 00486 }; 00487 00488 00495 // 00496 template< class Type_ > 00497 class Algebraic_structure_traits_base< Type_, 00498 Field_with_sqrt_tag> 00499 : public Algebraic_structure_traits_base< Type_, 00500 Field_tag> { 00501 public: 00502 typedef Type_ Type; 00503 typedef Field_with_sqrt_tag Algebraic_category; 00504 00505 struct Is_square 00506 :public std::binary_function<Type,Type&,bool> 00507 { 00508 bool operator()(const Type& ) const {return true;} 00509 bool operator()( 00510 const Type& x, 00511 Type & result) const { 00512 typename Algebraic_structure_traits<Type>::Sqrt sqrt; 00513 result = sqrt(x); 00514 return true; 00515 } 00516 }; 00517 }; 00518 00525 // 00526 template< class Type_ > 00527 class Algebraic_structure_traits_base< Type_, 00528 Field_with_kth_root_tag> 00529 : public Algebraic_structure_traits_base< Type_, 00530 Field_with_sqrt_tag> { 00531 00532 00533 00534 public: 00535 typedef Type_ Type; 00536 typedef Field_with_kth_root_tag Algebraic_category; 00537 }; 00538 00539 00540 00541 00548 // 00549 template< class Type_ > 00550 class Algebraic_structure_traits_base< Type_, 00551 Field_with_root_of_tag > 00552 : public Algebraic_structure_traits_base< Type_, 00553 Field_with_kth_root_tag > { 00554 public: 00555 typedef Type_ Type; 00556 typedef Field_with_root_of_tag Algebraic_category; 00557 }; 00558 00559 // Some common functors to be used by AST specializations 00560 namespace INTERN_AST { 00561 template< class Type > 00562 class Div_per_operator 00563 : public std::binary_function< Type, Type, 00564 Type > { 00565 public: 00566 Type operator()( const Type& x, 00567 const Type& y ) const { 00568 return x / y; 00569 } 00570 00571 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) 00572 }; 00573 00574 template< class Type > 00575 class Mod_per_operator 00576 : public std::binary_function< Type, Type, 00577 Type > { 00578 public: 00579 Type operator()( const Type& x, 00580 const Type& y ) const { 00581 return x % y; 00582 } 00583 00584 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) 00585 }; 00586 00587 template< class Type > 00588 class Is_square_per_sqrt 00589 : public std::binary_function< Type, Type&, 00590 bool > { 00591 public: 00592 bool operator()( const Type& x, 00593 Type& y ) const { 00594 typename Algebraic_structure_traits< Type >::Sqrt 00595 actual_sqrt; 00596 y = actual_sqrt( x ); 00597 return y * y == x; 00598 } 00599 bool operator()( const Type& x) const { 00600 Type dummy; 00601 return operator()(x,dummy); 00602 } 00603 }; 00604 } // INTERN_AST 00605 CGAL_END_NAMESPACE 00606 00607 #endif // CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H