// Copyright (c) 2006-2007 Max-Planck-Institute Saarbruecken (Germany). // All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Algebraic_foundations/include/CGAL/Algebraic_structure_traits.h $ // $Id: Algebraic_structure_traits.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Michael Hemmer // // ============================================================================= #ifndef CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H #define CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H #include #include #include #include #include #include namespace CGAL { // REMARK: Some of the following comments and references are just copy & pasted // from EXACUS and have to be adapted/removed in the future. // The tags for Algebra_type corresponding to the number type concepts // =================================================================== //! corresponds to the \c IntegralDomainWithoutDiv concept. struct Integral_domain_without_division_tag {}; //! corresponds to the \c IntegralDomain concept. struct Integral_domain_tag : public Integral_domain_without_division_tag {}; //! corresponds to the \c UFDomain concept. struct Unique_factorization_domain_tag : public Integral_domain_tag {}; //! corresponds to the \c EuclideanRing concept. struct Euclidean_ring_tag : public Unique_factorization_domain_tag {}; //! corresponds to the \c Field concept. struct Field_tag : public Integral_domain_tag {}; //! corresponds to the \c FieldWithSqrt concept. struct Field_with_sqrt_tag : public Field_tag {}; //! corresponds to the \c FieldWithKthRoot concept struct Field_with_kth_root_tag : public Field_with_sqrt_tag {}; //! corresponds to the \c FieldWithRootOF concept. struct Field_with_root_of_tag : public Field_with_kth_root_tag {}; // The algebraic structure traits template // ========================================================================= template< class Type_ > class Algebraic_structure_traits { public: typedef Type_ Type; typedef Null_tag Algebraic_category; typedef Null_tag Is_exact; typedef Null_tag Is_numerical_sensitive; typedef Null_functor Simplify; typedef Null_functor Unit_part; typedef Null_functor Integral_division; typedef Null_functor Is_square; typedef Null_functor Gcd; typedef Null_functor Div_mod; typedef Null_functor Div; typedef Null_functor Mod; typedef Null_functor Square; typedef Null_functor Is_zero; typedef Null_functor Is_one; typedef Null_functor Sqrt; typedef Null_functor Kth_root; typedef Null_functor Root_of; typedef Null_functor Divides; typedef Null_functor Inverse; }; // The algebraic structure traits base class // ========================================================================= template< class Type, class Algebra_type > class Algebraic_structure_traits_base; //! The template specialization that can be used for types that are not any //! of the number type concepts. All functors are set to \c Null_functor //! or suitable defaults. The \c Simplify functor does nothing by default. template< class Type_ > class Algebraic_structure_traits_base< Type_, Null_tag > { public: typedef Type_ Type; typedef Null_tag Algebraic_category; typedef Tag_false Is_exact; typedef Null_tag Is_numerical_sensitive; typedef Null_tag Boolean; // does nothing by default class Simplify : public CGAL::cpp98::unary_function< Type&, void > { public: void operator()( Type& ) const {} }; typedef Null_functor Unit_part; typedef Null_functor Integral_division; typedef Null_functor Is_square; typedef Null_functor Gcd; typedef Null_functor Div_mod; typedef Null_functor Div; typedef Null_functor Mod; typedef Null_functor Square; typedef Null_functor Is_zero; typedef Null_functor Is_one; typedef Null_functor Sqrt; typedef Null_functor Kth_root; typedef Null_functor Root_of; typedef Null_functor Divides; typedef Null_functor Inverse; }; //! The template specialization that is used if the number type is //! a model of the \c IntegralDomainWithoutDiv concept. The \c Simplify //! does nothing by default and the \c Unit_part is equal to //! \c Type(-1) for negative numbers and //! \c Type(1) otherwise template< class Type_ > class Algebraic_structure_traits_base< Type_, Integral_domain_without_division_tag > : public Algebraic_structure_traits_base< Type_, Null_tag > { public: typedef Type_ Type; typedef Integral_domain_without_division_tag Algebraic_category; typedef bool Boolean; // returns Type(1) by default class Unit_part : public CGAL::cpp98::unary_function< Type, Type > { public: Type operator()( const Type& x ) const { return( x < Type(0)) ? Type(-1) : Type(1); } }; class Square : public CGAL::cpp98::unary_function< Type, Type > { public: Type operator()( const Type& x ) const { return x*x; } }; class Is_zero : public CGAL::cpp98::unary_function< Type, bool > { public: bool operator()( const Type& x ) const { return x == Type(0); } }; class Is_one : public CGAL::cpp98::unary_function< Type, bool > { public: bool operator()( const Type& x ) const { return x == Type(1); } }; }; //! The template specialization that is used if the number type is //! a model of the \c IntegralDomain concept. It is equivalent to the //! specialization //! for the \c IntegralDomainWithoutDiv concept. The additionally required //! \c Integral_division functor needs to be implemented in the //! \c Algebraic_structure_traits itself. template< class Type_ > class Algebraic_structure_traits_base< Type_, Integral_domain_tag > : public Algebraic_structure_traits_base< Type_, Integral_domain_without_division_tag > { public: typedef Type_ Type; typedef Integral_domain_tag Algebraic_category; }; //! The template specialization that is used if the number type is //! a model of the \c UFDomain concept. It is equivalent to the specialization //! for the \c IntegralDomain concept. The additionally required //! \c Integral_div functor //! and \c Gcd functor need to be implemented in the //! \c Algebraic_structure_traits itself. template< class Type_ > class Algebraic_structure_traits_base< Type_, Unique_factorization_domain_tag > : public Algebraic_structure_traits_base< Type_, Integral_domain_tag > { public: typedef Type_ Type; typedef Unique_factorization_domain_tag Algebraic_category; // Default implementation of Divides functor for unique factorization domains // x divides y if gcd(y,x) equals x up to inverses class Divides : public CGAL::cpp98::binary_function{ public: bool operator()( const Type& x, const Type& y) const { typedef CGAL::Algebraic_structure_traits AST; typename AST::Gcd gcd; typename AST::Unit_part unit_part; typename AST::Integral_division idiv; return gcd(y,x) == idiv(x,unit_part(x)); } // second operator computing q = x/y bool operator()( const Type& x, const Type& y, Type& q) const { typedef CGAL::Algebraic_structure_traits AST; typename AST::Integral_division idiv; bool result = (*this)(x,y); if( result == true ) q = idiv(x,y); return result; } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,bool) }; }; //! The template specialization that is used if the number type is //! a model of the \c EuclideanRing concept. template< class Type_ > class Algebraic_structure_traits_base< Type_, Euclidean_ring_tag > : public Algebraic_structure_traits_base< Type_, Unique_factorization_domain_tag > { public: typedef Type_ Type; typedef Euclidean_ring_tag Algebraic_category; // maps to \c Div by default. class Integral_division : public CGAL::cpp98::binary_function< Type, Type, Type > { public: Type operator()( const Type& x, const Type& y) const { typedef Algebraic_structure_traits AST; typedef typename AST::Is_exact Is_exact; CGAL_USE_TYPE(Is_exact); typename AST::Div actual_div; CGAL_precondition_msg( !Is_exact::value || actual_div( x, y) * y == x, "'x' must be divisible by 'y' in " "Algebraic_structure_traits<...>::Integral_div()(x,y)" ); return actual_div( x, y); } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) }; // Algorithm from NiX/euclids_algorithm.h class Gcd : public CGAL::cpp98::binary_function< Type, Type, Type > { public: Type operator()( const Type& x, const Type& y) const { typedef Algebraic_structure_traits AST; typename AST::Mod mod; typename AST::Unit_part unit_part; typename AST::Integral_division integral_div; // First: the extreme cases and negative sign corrections. if (x == Type(0)) { if (y == Type(0)) return Type(0); return integral_div( y, unit_part(y) ); } if (y == Type(0)) return integral_div(x, unit_part(x) ); Type u = integral_div( x, unit_part(x) ); Type v = integral_div( y, unit_part(y) ); // Second: assuming mod is the most expensive op here, // we don't compute it unnecessarily if u < v if (u < v) { v = mod(v,u); // maintain invariant of v > 0 for the loop below if ( v == Type(0) ) return u; } // Third: generic case of two positive integer values and u >= v. // The standard loop would be: // while ( v != 0) { // int tmp = mod(u,v); // u = v; // v = tmp; // } // return u; // // But we want to save us all the variable assignments and unroll // the loop. Before that, we transform it into a do {...} while() // loop to reduce branching statements. Type w; do { w = mod(u,v); if ( w == Type(0)) return v; u = mod(v,w); if ( u == Type(0)) return w; v = mod(w,u); } while (v != Type(0)); return u; } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) }; // based on \c Div and \c Mod. class Div_mod { public: typedef Type first_argument_type; typedef Type second_argument_type; typedef Type& third_argument_type; typedef Type& fourth_argument_type; typedef void result_type; void operator()( const Type& x, const Type& y, Type& q, Type& r) const { typedef Algebraic_structure_traits Traits; typename Traits::Div actual_div; typename Traits::Mod actual_mod; q = actual_div( x, y ); r = actual_mod( x, y ); return; } template < class NT1, class NT2 > void operator()( const NT1& x, const NT2& y, Type& q, Type& r ) const { typedef Coercion_traits< NT1, NT2 > CT; typedef typename CT::Type Coercion_type_NT1_NT2; CGAL_USE_TYPE(Coercion_type_NT1_NT2); CGAL_static_assertion(( ::boost::is_same::value)); typename Coercion_traits< NT1, NT2 >::Cast cast; operator()( cast(x), cast(y), q, r ); } }; // based on \c Div_mod. class Div : public CGAL::cpp98::binary_function< Type, Type, Type > { public: Type operator()( const Type& x, const Type& y) const { typename Algebraic_structure_traits ::Div_mod actual_div_mod; Type q; Type r; actual_div_mod( x, y, q, r ); return q; }; CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) }; // based on \c Div_mod. class Mod : public CGAL::cpp98::binary_function< Type, Type, Type > { public: Type operator()( const Type& x, const Type& y) const { typename Algebraic_structure_traits ::Div_mod actual_div_mod; Type q; Type r; actual_div_mod( x, y, q, r ); return r; }; CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) }; // Divides for Euclidean Ring class Divides : public CGAL::cpp98::binary_function{ public: bool operator()( const Type& x, const Type& y) const { typedef Algebraic_structure_traits AST; typename AST::Mod mod; CGAL_precondition(typename AST::Is_zero()(x) == false ); return typename AST::Is_zero()(mod(y,x)); } // second operator computing q bool operator()( const Type& x, const Type& y, Type& q) const { typedef Algebraic_structure_traits AST; typename AST::Div_mod div_mod; CGAL_precondition(typename AST::Is_zero()(x) == false ); Type r; div_mod(y,x,q,r); return (typename AST::Is_zero()(r)); } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,bool) }; }; //! The template specialization that is used if the number type is //! a model of the \c Field concept. \c Unit_part ()(x) //! returns \c NT(1) if the value \c x is equal to \c NT(0) and //! otherwise the value \c x itself. The \c Integral_div //! maps to the \c operator/. //! See also \link NiX_NT_traits_functors concept NT_traits \endlink . //! \ingroup NiX_NT_traits_bases // template< class Type_ > class Algebraic_structure_traits_base< Type_, Field_tag > : public Algebraic_structure_traits_base< Type_, Integral_domain_tag > { public: typedef Type_ Type; typedef Field_tag Algebraic_category; // returns the argument \a a by default class Unit_part : public CGAL::cpp98::unary_function< Type, Type > { public: Type operator()( const Type& x ) const { return( x == Type(0)) ? Type(1) : x; } }; // maps to \c operator/ by default. class Integral_division : public CGAL::cpp98::binary_function< Type, Type, Type > { public: Type operator()( const Type& x, const Type& y) const { typedef Algebraic_structure_traits AST; typedef typename AST::Is_exact Is_exact; CGAL_USE_TYPE(Is_exact); CGAL_precondition_code( bool ie = Is_exact::value; ) CGAL_precondition_msg( !ie || (x / y) * y == x, "'x' must be divisible by 'y' in " "Algebraic_structure_traits<...>::Integral_div()(x,y)" ); return x / y; } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) }; // maps to \c 1/x by default. class Inverse : public CGAL::cpp98::unary_function< Type, Type > { public: Type operator()( const Type& x ) const { return Type(1)/x; } }; // Default implementation of Divides functor for Field: // returns always true // \pre: x != 0 class Divides : public CGAL::cpp98::binary_function< Type, Type, bool > { public: bool operator()( const Type& CGAL_precondition_code(x), const Type& /* y */) const { CGAL_precondition_code( typedef Algebraic_structure_traits AST); CGAL_precondition( typename AST::Is_zero()(x) == false ); return true; } // second operator computing q bool operator()( const Type& x, const Type& y, Type& q) const { CGAL_precondition_code(typedef Algebraic_structure_traits AST); CGAL_precondition( typename AST::Is_zero()(x) == false ); q = y/x; return true; } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,bool) }; }; //! The template specialization that is used if the number type is a model //! of the \c FieldWithSqrt concept. It is equivalent to the //! specialization for the \c Field concept. The additionally required //! \c NiX::NT_traits::Sqrt functor need to be //! implemented in the \c NT_traits itself. //! \ingroup NiX_NT_traits_bases // template< class Type_ > class Algebraic_structure_traits_base< Type_, Field_with_sqrt_tag> : public Algebraic_structure_traits_base< Type_, Field_tag> { public: typedef Type_ Type; typedef Field_with_sqrt_tag Algebraic_category; struct Is_square :public CGAL::cpp98::binary_function { bool operator()(const Type& ) const {return true;} bool operator()( const Type& x, Type & result) const { typename Algebraic_structure_traits::Sqrt sqrt; result = sqrt(x); return true; } }; }; //! The template specialization that is used if the number type is a model //! of the \c FieldWithKthRoot concept. It is equivalent to the //! specialization for the \c Field concept. The additionally required //! \c NiX::NT_traits::Kth_root functor need to be //! implemented in the \c Algebraic_structure_traits itself. //! \ingroup NiX_NT_traits_bases // template< class Type_ > class Algebraic_structure_traits_base< Type_, Field_with_kth_root_tag> : public Algebraic_structure_traits_base< Type_, Field_with_sqrt_tag> { public: typedef Type_ Type; typedef Field_with_kth_root_tag Algebraic_category; }; //! The template specialization that is used if the number type is a model //! of the \c FieldWithRootOf concept. It is equivalent to the //! specialization for the \c FieldWithKthRoot concept. The additionally //! required \c NiX::NT_traits::Root_of functor need to be //! implemented in the \c NT_traits itself. //! \ingroup NiX_NT_traits_bases // template< class Type_ > class Algebraic_structure_traits_base< Type_, Field_with_root_of_tag > : public Algebraic_structure_traits_base< Type_, Field_with_kth_root_tag > { public: typedef Type_ Type; typedef Field_with_root_of_tag Algebraic_category; }; // Some common functors to be used by AST specializations namespace INTERN_AST { template< class Type > class Div_per_operator : public CGAL::cpp98::binary_function< Type, Type, Type > { public: Type operator()( const Type& x, const Type& y ) const { return x / y; } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) }; template< class Type > class Mod_per_operator : public CGAL::cpp98::binary_function< Type, Type, Type > { public: Type operator()( const Type& x, const Type& y ) const { return x % y; } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( Type ) }; template< class Type > class Is_square_per_sqrt : public CGAL::cpp98::binary_function< Type, Type&, bool > { public: bool operator()( const Type& x, Type& y ) const { typename Algebraic_structure_traits< Type >::Sqrt actual_sqrt; y = actual_sqrt( x ); return y * y == x; } bool operator()( const Type& x) const { Type dummy; return operator()(x,dummy); } }; } // INTERN_AST } //namespace CGAL #endif // CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H