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:
Sébastien Loriot 2013-05-23 11:15:32 +02:00
commit 7baa997ce1
11 changed files with 156 additions and 42 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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,10 +79,14 @@ 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;
// 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, Exact_kernel> C2E;
typedef Cartesian_converter<CK, Approximate_kernel> C2F;
enum { Has_filtered_predicates = true };
@ -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)

View File

@ -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...).

View File

@ -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,
CGAL_Kernel_pred_RT(Orientation_2,
orientation_2_object)
CGAL_Kernel_pred(Orientation_3,
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,
CGAL_Kernel_pred_RT(Side_of_bounded_circle_2,
side_of_bounded_circle_2_object)
CGAL_Kernel_pred(Side_of_bounded_sphere_3,
CGAL_Kernel_pred_RT(Side_of_bounded_sphere_3,
side_of_bounded_sphere_3_object)
CGAL_Kernel_pred(Side_of_oriented_circle_2,
CGAL_Kernel_pred_RT(Side_of_oriented_circle_2,
side_of_oriented_circle_2_object)
CGAL_Kernel_pred(Side_of_oriented_sphere_3,
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

View File

@ -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);
if (zeros != 0) {
mpz_tdiv_q_2exp( man(), man(), zeros); // bit-wise right-shift
e += zeros;
}
} else {
e = 0;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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; )