dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/Algebraic_structure_traits.h

619 lines
21 KiB
C++

// 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 <hemmer@mpi-inf.mpg.de>
//
// =============================================================================
#ifndef CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H
#define CGAL_ALGEBRAIC_STRUCTURE_TRAITS_H
#include <functional>
#include <CGAL/tags.h>
#include <CGAL/type_traits.h>
#include <CGAL/Coercion_traits.h>
#include <CGAL/assertions.h>
#include <CGAL/use.h>
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<Type,Type,bool>{
public:
bool operator()( const Type& x, const Type& y) const {
typedef CGAL::Algebraic_structure_traits<Type> 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<Type> 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<Type> 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<Type> 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<Type> 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<Coercion_type_NT1_NT2 , Type >::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<Type>
::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<Type>
::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<Type, Type, bool>{
public:
bool operator()( const Type& x, const Type& y) const {
typedef Algebraic_structure_traits<Type> 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<Type> 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<Type> 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<Type> 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<Type> 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<Type,Type&,bool>
{
bool operator()(const Type& ) const {return true;}
bool operator()(
const Type& x,
Type & result) const {
typename Algebraic_structure_traits<Type>::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