mirror of https://github.com/CGAL/cgal
Merge branch 'Filtered_kernel-ring-glisse'
This branch adds an additional way to filter predicates that are only doing operations using a ring number type. In case of failure, a RT is used rather than an FT which speeds things up. Successfully tested in CGAL-4.3Ic-37
This commit is contained in:
commit
7baa997ce1
|
|
@ -75,7 +75,7 @@ class Lazy_alpha_nt_2{
|
|||
//NT & kernels
|
||||
typedef CGAL::Interval_nt<mode> NT_approx;
|
||||
//Gmpq or Quotient<MP_float>
|
||||
typedef Exact_type_selector<double>::Type NT_exact;
|
||||
typedef Exact_field_selector<double>::Type NT_exact;
|
||||
typedef CGAL::Simple_cartesian<NT_approx> Kernel_approx;
|
||||
typedef CGAL::Simple_cartesian<NT_exact> Kernel_exact;
|
||||
typedef typename Kernel_traits<typename Input_traits::Point_2>::Kernel Kernel_input;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class Lazy_alpha_nt_3{
|
|||
//NT & kernels
|
||||
typedef CGAL::Interval_nt<mode> NT_approx;
|
||||
//Gmpq or Quotient<MP_float>
|
||||
typedef Exact_type_selector<double>::Type NT_exact;
|
||||
typedef Exact_field_selector<double>::Type NT_exact;
|
||||
typedef CGAL::Simple_cartesian<NT_approx> Kernel_approx;
|
||||
typedef CGAL::Simple_cartesian<NT_exact> Kernel_exact;
|
||||
//Helper class for weighted and non-weighted case
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ public:
|
|||
//and in case of failure, exact arithmetic is used.
|
||||
template <class Kernel>
|
||||
class Is_on_positive_side_of_plane_3<Convex_hull_traits_3<Kernel>,Tag_true>{
|
||||
typedef Simple_cartesian<CGAL::internal::Exact_type_selector<double>::Type> PK;
|
||||
typedef Simple_cartesian<CGAL::internal::Exact_field_selector<double>::Type> PK;
|
||||
typedef Simple_cartesian<Interval_nt_advanced > CK;
|
||||
typedef Convex_hull_traits_3<Kernel> Traits;
|
||||
typedef typename Traits::Point_3 Point_3;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include <CGAL/Filtered_predicate.h>
|
||||
#include <CGAL/Cartesian_converter.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Homogeneous_converter.h>
|
||||
#include <CGAL/Simple_homogeneous.h>
|
||||
#include <CGAL/Kernel/Type_equality_wrapper.h>
|
||||
|
||||
#include <CGAL/MP_Float.h>
|
||||
|
|
@ -33,6 +35,7 @@
|
|||
#include <CGAL/internal/Exact_type_selector.h>
|
||||
|
||||
#include <CGAL/internal/Static_filters/Static_filters.h>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
// This file contains the definition of a generic kernel filter.
|
||||
//
|
||||
|
|
@ -46,6 +49,28 @@
|
|||
// traits-like mechanism ?
|
||||
|
||||
namespace CGAL {
|
||||
namespace Filter {
|
||||
template <class CK, class Rep=typename CK::Rep_tag /* Cartesian_tag */>
|
||||
struct Select_exact_kernel
|
||||
{
|
||||
typedef typename internal::Exact_field_selector<typename CK::RT>::Type Exact_nt;
|
||||
typedef typename internal::Exact_ring_selector <typename CK::RT>::Type Exact_rt;
|
||||
typedef Simple_cartesian<Exact_nt> Exact_kernel;
|
||||
typedef Simple_cartesian<Exact_rt> Exact_kernel_rt;
|
||||
typedef Cartesian_converter<CK, Exact_kernel> C2E;
|
||||
typedef Cartesian_converter<CK, Exact_kernel_rt> C2E_rt;
|
||||
};
|
||||
|
||||
template <class CK>
|
||||
struct Select_exact_kernel <CK, Homogeneous_tag>
|
||||
{
|
||||
typedef typename internal::Exact_ring_selector<typename CK::RT>::Type Exact_nt;
|
||||
typedef Simple_homogeneous<Exact_nt> Exact_kernel;
|
||||
typedef Homogeneous_converter<CK, Exact_kernel> C2E;
|
||||
typedef Exact_kernel Exact_kernel_rt;
|
||||
typedef C2E C2E_rt;
|
||||
};
|
||||
}
|
||||
|
||||
// CK = eventually rebound construction kernel (gets Point_2 from).
|
||||
// Exact_kernel = exact kernel called when needed by the filter.
|
||||
|
|
@ -54,11 +79,15 @@ template < typename CK >
|
|||
struct Filtered_kernel_base
|
||||
: public CK
|
||||
{
|
||||
typedef typename internal::Exact_type_selector<typename CK::RT>::Type Exact_nt;
|
||||
typedef Simple_cartesian<Exact_nt> Exact_kernel;
|
||||
typedef Simple_cartesian<Interval_nt_advanced> Approximate_kernel;
|
||||
typedef Cartesian_converter<CK, Exact_kernel> C2E;
|
||||
typedef Cartesian_converter<CK, Approximate_kernel> C2F;
|
||||
// Use Select_exact_kernel as a base class?
|
||||
typedef typename Filter::Select_exact_kernel<CK>::Exact_nt Exact_nt;
|
||||
typedef typename Filter::Select_exact_kernel<CK>::Exact_kernel Exact_kernel;
|
||||
typedef typename Filter::Select_exact_kernel<CK>::Exact_kernel_rt Exact_kernel_rt;
|
||||
typedef typename Filter::Select_exact_kernel<CK>::C2E C2E;
|
||||
typedef typename Filter::Select_exact_kernel<CK>::C2E_rt C2E_rt;
|
||||
|
||||
typedef Simple_cartesian<Interval_nt_advanced> Approximate_kernel;
|
||||
typedef Cartesian_converter<CK, Approximate_kernel> C2F;
|
||||
|
||||
enum { Has_filtered_predicates = true };
|
||||
typedef Boolean_tag<Has_filtered_predicates> Has_filtered_predicates_tag;
|
||||
|
|
@ -84,6 +113,10 @@ struct Filtered_kernel_base
|
|||
typedef Filtered_predicate<typename Exact_kernel::P, typename Approximate_kernel::P, C2E, C2F> P; \
|
||||
P Pf() const { return P(); }
|
||||
|
||||
#define CGAL_Kernel_pred_RT(P, Pf) \
|
||||
typedef Filtered_predicate<typename Exact_kernel_rt::P, typename Approximate_kernel::P, C2E_rt, C2F> P; \
|
||||
P Pf() const { return P(); }
|
||||
|
||||
// We don't touch the constructions.
|
||||
#define CGAL_Kernel_cons(Y,Z)
|
||||
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
// Epeck_ft is either Gmpq of Quotient<MP_float>
|
||||
typedef internal::Exact_type_selector<double>::Type Epeck_ft;
|
||||
// Epeck_ft is either Gmpq or Quotient<MP_float>
|
||||
typedef internal::Exact_field_selector<double>::Type Epeck_ft;
|
||||
|
||||
// The following are redefined kernels instead of simple typedefs in order to shorten
|
||||
// template name length (for error messages, mangling...).
|
||||
|
|
|
|||
|
|
@ -34,6 +34,12 @@
|
|||
# define CGAL_Kernel_pred(X, Y)
|
||||
#endif
|
||||
|
||||
// Those predicates for which Simple_cartesian is guaranteed not to use
|
||||
// any division.
|
||||
#ifndef CGAL_Kernel_pred_RT
|
||||
# define CGAL_Kernel_pred_RT(X, Y) CGAL_Kernel_pred(X, Y)
|
||||
#endif
|
||||
|
||||
#ifndef CGAL_Kernel_cons
|
||||
# define CGAL_Kernel_cons(X, Y)
|
||||
#endif
|
||||
|
|
@ -534,23 +540,24 @@ CGAL_Kernel_pred(Less_y_3,
|
|||
less_y_3_object)
|
||||
CGAL_Kernel_pred(Less_z_3,
|
||||
less_z_3_object)
|
||||
CGAL_Kernel_pred(Orientation_2,
|
||||
orientation_2_object)
|
||||
CGAL_Kernel_pred(Orientation_3,
|
||||
orientation_3_object)
|
||||
CGAL_Kernel_pred_RT(Orientation_2,
|
||||
orientation_2_object)
|
||||
CGAL_Kernel_pred_RT(Orientation_3,
|
||||
orientation_3_object)
|
||||
CGAL_Kernel_pred(Oriented_side_2,
|
||||
oriented_side_2_object)
|
||||
CGAL_Kernel_pred(Oriented_side_3,
|
||||
oriented_side_3_object)
|
||||
CGAL_Kernel_pred(Side_of_bounded_circle_2,
|
||||
side_of_bounded_circle_2_object)
|
||||
CGAL_Kernel_pred(Side_of_bounded_sphere_3,
|
||||
side_of_bounded_sphere_3_object)
|
||||
CGAL_Kernel_pred(Side_of_oriented_circle_2,
|
||||
side_of_oriented_circle_2_object)
|
||||
CGAL_Kernel_pred(Side_of_oriented_sphere_3,
|
||||
side_of_oriented_sphere_3_object)
|
||||
CGAL_Kernel_pred_RT(Side_of_bounded_circle_2,
|
||||
side_of_bounded_circle_2_object)
|
||||
CGAL_Kernel_pred_RT(Side_of_bounded_sphere_3,
|
||||
side_of_bounded_sphere_3_object)
|
||||
CGAL_Kernel_pred_RT(Side_of_oriented_circle_2,
|
||||
side_of_oriented_circle_2_object)
|
||||
CGAL_Kernel_pred_RT(Side_of_oriented_sphere_3,
|
||||
side_of_oriented_sphere_3_object)
|
||||
|
||||
#undef CGAL_Kernel_pred_RT
|
||||
#undef CGAL_Kernel_pred
|
||||
#undef CGAL_Kernel_cons
|
||||
#undef CGAL_Kernel_obj
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ public:
|
|||
e = 0;
|
||||
return;
|
||||
}
|
||||
static int p = std::numeric_limits<double>::digits;
|
||||
const int p = std::numeric_limits<double>::digits;
|
||||
CGAL_assertion(CGAL_NTS is_finite(d) & is_valid(d));
|
||||
int exp;
|
||||
double x = std::frexp(d, &exp); // x in [1/2, 1], x*2^exp = d
|
||||
|
|
@ -274,7 +274,8 @@ Gmpzf& Gmpzf::operator*=( const Gmpzf& b)
|
|||
mpz_mul(result.man(), man(), b.man());
|
||||
e += b.exp();
|
||||
swap (result);
|
||||
canonicalize();
|
||||
if(is_zero()) e=0; // product is 0 or odd, so we can skip canonicalize()
|
||||
CGAL_postcondition(is_canonical());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -456,8 +457,10 @@ void Gmpzf::canonicalize()
|
|||
if (!is_zero()) {
|
||||
// chop off trailing zeros in m
|
||||
unsigned long zeros = mpz_scan1(man(), 0);
|
||||
mpz_tdiv_q_2exp( man(), man(), zeros); // bit-wise right-shift
|
||||
e += zeros;
|
||||
if (zeros != 0) {
|
||||
mpz_tdiv_q_2exp( man(), man(), zeros); // bit-wise right-shift
|
||||
e += zeros;
|
||||
}
|
||||
} else {
|
||||
e = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include <CGAL/Lazy.h>
|
||||
|
||||
#include <CGAL/Sqrt_extension_fwd.h>
|
||||
#include <CGAL/Kernel/mpl.h>
|
||||
|
||||
/*
|
||||
* This file contains the definition of the number type Lazy_exact_nt<ET>,
|
||||
|
|
@ -1323,6 +1324,35 @@ struct NT_converter < Lazy_exact_nt<ET>, ET >
|
|||
{ return a.exact(); }
|
||||
};
|
||||
|
||||
// Forward declaration to break inclusion cycle
|
||||
namespace internal {
|
||||
template<class>struct Exact_field_selector;
|
||||
template<class>struct Exact_ring_selector;
|
||||
}
|
||||
// Compiler can deduce ET from the first argument.
|
||||
template < typename ET >
|
||||
struct NT_converter < Lazy_exact_nt<ET>,
|
||||
typename First_if_different<
|
||||
typename internal::Exact_field_selector<ET>::Type,
|
||||
ET>::Type>
|
||||
{
|
||||
typename internal::Exact_field_selector<ET>::Type
|
||||
operator()(const Lazy_exact_nt<ET> &a) const
|
||||
{ return NT_converter<ET,typename internal::Exact_field_selector<ET>::Type>()(a.exact()); }
|
||||
};
|
||||
|
||||
template < typename ET >
|
||||
struct NT_converter < Lazy_exact_nt<ET>,
|
||||
typename First_if_different<
|
||||
typename First_if_different<
|
||||
typename internal::Exact_ring_selector<ET>::Type,
|
||||
ET>::Type,
|
||||
typename internal::Exact_field_selector<ET>::Type>::Type>
|
||||
{
|
||||
typename internal::Exact_ring_selector<ET>::Type operator()(const Lazy_exact_nt<ET> &a) const
|
||||
{ return NT_converter<ET,typename internal::Exact_ring_selector<ET>::Type>()(a.exact()); }
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
// Returns true if the value is representable by a double and to_double()
|
||||
// would return it. False means "don't know" (the exact number type is not
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#ifdef CGAL_USE_GMP
|
||||
# include <CGAL/Gmpz.h>
|
||||
# include <CGAL/Gmpq.h>
|
||||
# include <CGAL/Gmpzf.h>
|
||||
#endif
|
||||
#ifdef CGAL_USE_GMPXX
|
||||
# include <CGAL/gmpxx.h>
|
||||
|
|
@ -53,76 +54,116 @@ class Expr;
|
|||
|
||||
namespace CGAL { namespace internal {
|
||||
|
||||
// A class which tells the prefered "exact number type" corresponding to a type.
|
||||
// Two classes which tell the prefered "exact number types" corresponding to a type.
|
||||
|
||||
// The default template chooses Gmpq or Quotient<MP_Float>.
|
||||
// It should support the built-in types.
|
||||
template < typename >
|
||||
struct Exact_type_selector
|
||||
struct Exact_field_selector
|
||||
#ifdef CGAL_USE_GMP
|
||||
{ typedef Gmpq Type; };
|
||||
#else
|
||||
{ typedef Quotient<MP_Float> Type; };
|
||||
#endif
|
||||
|
||||
// By default, a field is a safe choice of ring.
|
||||
template < typename T >
|
||||
struct Exact_ring_selector : Exact_field_selector < T > { };
|
||||
|
||||
template <>
|
||||
struct Exact_type_selector<MP_Float>
|
||||
struct Exact_ring_selector<double>
|
||||
#if defined(CGAL_HAS_THREADS) || !defined(CGAL_USE_GMP)
|
||||
{ typedef MP_Float Type; };
|
||||
#else
|
||||
{ typedef Gmpzf Type; };
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct Exact_ring_selector<float> : Exact_ring_selector<double> { };
|
||||
|
||||
template <>
|
||||
struct Exact_field_selector<MP_Float>
|
||||
{ typedef Quotient<MP_Float> Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_type_selector<Quotient<MP_Float> >
|
||||
struct Exact_ring_selector<MP_Float>
|
||||
{ typedef MP_Float Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_field_selector<Quotient<MP_Float> >
|
||||
{ typedef Quotient<MP_Float> Type; };
|
||||
|
||||
// And we specialize for the following types :
|
||||
#ifdef CGAL_USE_GMP
|
||||
template <>
|
||||
struct Exact_type_selector<Gmpz>
|
||||
struct Exact_field_selector<Gmpz>
|
||||
{ typedef Gmpq Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_type_selector<Gmpq>
|
||||
struct Exact_ring_selector<Gmpz>
|
||||
{ typedef Gmpz Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_ring_selector<Gmpzf>
|
||||
{ typedef Gmpzf Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_field_selector<Gmpq>
|
||||
{ typedef Gmpq Type; };
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_USE_GMPXX
|
||||
template <>
|
||||
struct Exact_type_selector< ::mpz_class>
|
||||
struct Exact_field_selector< ::mpz_class>
|
||||
{ typedef ::mpq_class Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_type_selector< ::mpq_class>
|
||||
struct Exact_ring_selector< ::mpz_class>
|
||||
{ typedef ::mpz_class Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_field_selector< ::mpq_class>
|
||||
{ typedef ::mpq_class Type; };
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_USE_LEDA
|
||||
template <>
|
||||
struct Exact_type_selector<leda_integer>
|
||||
struct Exact_field_selector<leda_integer>
|
||||
{ typedef leda_rational Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_type_selector<leda_rational>
|
||||
struct Exact_ring_selector<leda_integer>
|
||||
{ typedef leda_integer Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_field_selector<leda_rational>
|
||||
{ typedef leda_rational Type; };
|
||||
|
||||
template <>
|
||||
struct Exact_type_selector<leda_real>
|
||||
struct Exact_field_selector<leda_real>
|
||||
{ typedef leda_real Type; };
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_USE_CORE
|
||||
template <>
|
||||
struct Exact_type_selector<CORE::Expr>
|
||||
struct Exact_field_selector<CORE::Expr>
|
||||
{ typedef CORE::Expr Type; };
|
||||
#endif
|
||||
|
||||
template < typename ET >
|
||||
struct Exact_type_selector<Lazy_exact_nt<ET> >
|
||||
struct Exact_field_selector<Lazy_exact_nt<ET> >
|
||||
: Exact_field_selector<ET>
|
||||
{
|
||||
// We have a choice here :
|
||||
// - using ET gets rid of the DAG computation as well as redoing the interval
|
||||
// - using Lazy_exact_nt<ET> might use sharper intervals.
|
||||
typedef ET Type;
|
||||
// typedef ET Type;
|
||||
// typedef Lazy_exact_nt<ET> Type;
|
||||
};
|
||||
template < typename ET >
|
||||
struct Exact_ring_selector<Lazy_exact_nt<ET> >
|
||||
: Exact_ring_selector<ET>
|
||||
{};
|
||||
|
||||
} } // namespace CGAL::internal
|
||||
|
||||
|
|
|
|||
|
|
@ -732,7 +732,7 @@ void sqrt_extension_test(){
|
|||
#include <CGAL/internal/Exact_type_selector.h>
|
||||
void test_nt_converter()
|
||||
{
|
||||
typedef CGAL::internal::Exact_type_selector<int>::Type NT;
|
||||
typedef CGAL::internal::Exact_field_selector<int>::Type NT;
|
||||
typedef CGAL::Sqrt_extension<double,double> Source;
|
||||
typedef CGAL::Sqrt_extension<NT,NT> Target;
|
||||
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ public:
|
|||
const Geometric_traits & gt = Geometric_traits())
|
||||
: _gt(gt), _tds(), _domain(domain), too_long_edge_counter(0) {
|
||||
_gt.set_domain(_domain);
|
||||
typedef typename internal::Exact_type_selector<FT>::Type EFT;
|
||||
typedef typename internal::Exact_field_selector<FT>::Type EFT;
|
||||
typedef NT_converter<FT,EFT> NTC;
|
||||
CGAL_USE_TYPE(NTC);
|
||||
CGAL_triangulation_assertion_code( NTC ntc; )
|
||||
|
|
|
|||
Loading…
Reference in New Issue