// Copyright (c) 2008 Max-Planck-Institute Saarbruecken (Germany) // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ // // // Author(s) : Arno Eigenwillig // Michael Hemmer // // ============================================================================ // TODO: The comments are all original EXACUS comments and aren't adapted. So // they may be wrong now. #ifndef CGAL_POLYNOMIAL_ALGEBRAIC_STRUCTURE_TRAITS_H #define CGAL_POLYNOMIAL_ALGEBRAIC_STRUCTURE_TRAITS_H #include #include #include namespace CGAL { // Extend to a UFDomain as coefficient range // Forward declaration for for NT_traits::Gcd namespace internal { template inline Polynomial gcd_(const Polynomial&, const Polynomial&); } // namespace internal // Now we wrap up all of this in the actual NT_traits // specialization for Polynomial /*! \ingroup NiX_Polynomial \brief \c NiX::NT_traits < \c NiX::Polynomial > * * If \c NT is a model of a number type concept, then so is * \c Polynomial. A specialization of \c NiX::NT_traits * is provided automatically by NiX/Polynomial.h. * * The number type concepts for the coefficient domain NT are * mapped to those for the polynomials as follows: *
    IntegralDomainWithoutDiv --> IntegralDomainWithoutDiv
    IntegralDomain           --> IntegralDomain
    UFDomain       --> UFDomain
    EuclideanRing  --> UFDomain
    Field          --> EuclideanRing
    FieldWithSqrt  --> EuclideanRing
    
* * \c Polynomial is \c RealComparable iff \c NT is. * The ordering is determined by the \c sign() of differences, see ibid. * * \c Polynomial offers a non-Null_tag \c To_double * iff \c NT does. If non-Null_tag, it returns a coefficient-wise * \c double approximation of the polynomial. */ // Algebraic structure traits template< class POLY, class Algebraic_type > class Polynomial_algebraic_structure_traits_base; // The most basic suite of algebraic operations, suitable for the // most basic kind of coefficient range, viz. a IntegralDomainWithoutDiv. template< class POLY > class Polynomial_algebraic_structure_traits_base< POLY, Integral_domain_without_division_tag > : public Algebraic_structure_traits_base< POLY, Integral_domain_without_division_tag > { public: typedef Integral_domain_without_division_tag Algebraic_category; class Simplify : public CGAL::cpp98::unary_function< POLY&, void > { public: void operator()( POLY& p ) const { p.simplify_coefficients(); } }; class Unit_part : public CGAL::cpp98::unary_function< POLY, POLY > { public: POLY operator()( const POLY& x ) const { return POLY( x.unit_part() ); } }; class Is_zero : public CGAL::cpp98::unary_function< POLY, bool > { public: bool operator()( const POLY& x ) const { return x.is_zero(); } }; }; // Extend to the case that the coefficient range is a IntegralDomain (with div) template< class POLY > class Polynomial_algebraic_structure_traits_base< POLY, Integral_domain_tag > : public Polynomial_algebraic_structure_traits_base< POLY, Integral_domain_without_division_tag > { public: typedef Integral_domain_tag Algebraic_category; class Integral_division : public CGAL::cpp98::binary_function< POLY, POLY, POLY > { public: POLY operator()( const POLY& x, const POLY& y ) const { return x / y; } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( POLY ) }; private: typedef typename POLY::NT COEFF; typedef Algebraic_structure_traits AST_COEFF; typedef typename AST_COEFF::Divides Divides_coeff; typedef typename Divides_coeff::result_type BOOL; public: class Divides : public CGAL::cpp98::binary_function{ public: BOOL operator()( const POLY& p1, const POLY& p2) const { POLY q; return (*this)(p1,p2,q); } BOOL operator()( const POLY& p1, const POLY& p2, POLY& q) const { Divides_coeff divides_coeff; q=POLY(0); COEFF q1; BOOL result; if (p2.is_zero()) { q=POLY(0); return true; } int d1 = p1.degree(); int d2 = p2.degree(); if ( d2 < d1 ) { q = POLY(0); return false; } typedef std::vector Vector; Vector V_R, V_Q; V_Q.reserve(d2); if(d1==0){ for(int i=d2;i>=0;--i){ result=divides_coeff(p1[0],p2[i],q1); if(!result) return false; V_Q.push_back(q1); } V_R.push_back(COEFF(0)); } else{ V_R.reserve(d2); V_R=Vector(p2.begin(),p2.end()); Vector tmp1; tmp1.reserve(d1); for(int k=0; k<=d2-d1; ++k){ result=divides_coeff(p1[d1],V_R[d2-k],q1); if(!result) return false; V_Q.push_back(q1); for(int j=0;j class Polynomial_algebraic_structure_traits_base< POLY, Unique_factorization_domain_tag > : public Polynomial_algebraic_structure_traits_base< POLY, Integral_domain_tag > { public: typedef Unique_factorization_domain_tag Algebraic_category; class Gcd : public CGAL::cpp98::binary_function< POLY, POLY, POLY > { typedef typename Polynomial_traits_d::Multivariate_content Mcontent; typedef typename Mcontent::result_type ICoeff; ICoeff gcd_help(const ICoeff& , const ICoeff& , Field_tag) const { return ICoeff(1); } ICoeff gcd_help(const ICoeff& x, const ICoeff& y, Unique_factorization_domain_tag) const { return CGAL::gcd(x,y); } public: POLY operator()( const POLY& x, const POLY& y ) const { if(x==y) return x; typedef Algebraic_structure_traits AST; typename AST::Integral_division idiv; typename AST::Unit_part upart; // First: the extreme cases and negative sign corrections. if (CGAL::is_zero(x)) { if (CGAL::is_zero(y)) return POLY(0); return idiv(y,upart(y)); } if (CGAL::is_zero(y)) return idiv(x,upart(x)); if (internal::may_have_common_factor(x,y)) return CGAL::internal::gcd_(x,y); else{ typename Algebraic_structure_traits::Algebraic_category category; return POLY(gcd_help(Mcontent()(x),Mcontent()(y), category)); } } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( POLY ) }; }; // Clone this for a EuclideanRing template< class POLY > class Polynomial_algebraic_structure_traits_base< POLY, Euclidean_ring_tag > : public Polynomial_algebraic_structure_traits_base< POLY, Unique_factorization_domain_tag > { // nothing new }; // Extend to a field as coefficient range template< class POLY > class Polynomial_algebraic_structure_traits_base< POLY, Field_tag > : public Polynomial_algebraic_structure_traits_base< POLY, Unique_factorization_domain_tag > { public: typedef Euclidean_ring_tag Algebraic_category; class Div_mod { public: typedef POLY first_argument_type; typedef POLY second_argument_type; typedef POLY& third_argument_type; typedef POLY& fourth_argument_type; typedef void result_type; void operator()( const POLY& x, const POLY& y, POLY& q, POLY& r ) const { POLY::euclidean_division( x, y, q, r ); } template < class NT1, class NT2 > void operator()( const NT1& x, const NT2& y, POLY& q, POLY& r ) const { CGAL_static_assertion((::boost::is_same< typename Coercion_traits< NT1, NT2 >::Type, POLY >::value)); typename Coercion_traits< NT1, NT2 >::Cast cast; operator()( cast(x), cast(y), q, r ); } }; class Div : public CGAL::cpp98::binary_function< POLY, POLY, POLY > { public: POLY operator()(const POLY& a, const POLY& b) const { POLY q, r; Div_mod()(a, b, q, r); return q; } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( POLY ) }; class Mod : public CGAL::cpp98::binary_function< POLY, POLY, POLY > { public: POLY operator () (const POLY& a, const POLY& b) const { POLY q, r; Div_mod()(a, b, q, r); return r; } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( POLY ) }; }; // Clone this for a FieldWithSqrt template< class POLY > class Polynomial_algebraic_structure_traits_base< POLY, Field_with_sqrt_tag > : public Polynomial_algebraic_structure_traits_base< POLY, Field_tag > { // nothing new }; // Clone this for a FieldWithKthRoot template< class POLY > class Polynomial_algebraic_structure_traits_base< POLY, Field_with_kth_root_tag > : public Polynomial_algebraic_structure_traits_base< POLY, Field_with_sqrt_tag > { // nothing new }; // Clone this for a FieldWithRootOf template< class POLY > class Polynomial_algebraic_structure_traits_base< POLY, Field_with_root_of_tag > : public Polynomial_algebraic_structure_traits_base< POLY, Field_with_kth_root_tag > { // nothing new }; // The actual algebraic structure traits class template< class NT > class Algebraic_structure_traits< Polynomial< NT > > : public Polynomial_algebraic_structure_traits_base< Polynomial< NT >, typename Algebraic_structure_traits< NT >::Algebraic_category > { public: typedef Polynomial Algebraic_structure; typedef typename Algebraic_structure_traits< NT >::Is_exact Is_exact; }; } //namespace CGAL #endif // CGAL_POLYNOMIAL_ALGEBRAIC_STRUCTURE_TRAITS_H