BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polynomial/Algebraic_structure_traits.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines