From 571f370e28499d0a4a2c3b405c42faba031d8b2b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 24 Dec 2012 12:20:13 +0100 Subject: [PATCH 01/10] Rename Exact_type_selector to Exact_field_selector. --- .../include/CGAL/internal/Lazy_alpha_nt_2.h | 2 +- .../include/CGAL/internal/Lazy_alpha_nt_3.h | 2 +- Convex_hull_3/include/CGAL/convex_hull_3.h | 2 +- .../include/CGAL/Filtered_kernel.h | 2 +- ...ct_predicates_exact_constructions_kernel.h | 4 ++-- .../CGAL/internal/Exact_type_selector.h | 24 +++++++++---------- .../test/Number_types/Sqrt_extension.cpp | 2 +- .../include/CGAL/Periodic_3_triangulation_3.h | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Alpha_shapes_2/include/CGAL/internal/Lazy_alpha_nt_2.h b/Alpha_shapes_2/include/CGAL/internal/Lazy_alpha_nt_2.h index fa811c49222..07504bb2a2e 100644 --- a/Alpha_shapes_2/include/CGAL/internal/Lazy_alpha_nt_2.h +++ b/Alpha_shapes_2/include/CGAL/internal/Lazy_alpha_nt_2.h @@ -75,7 +75,7 @@ class Lazy_alpha_nt_2{ //NT & kernels typedef CGAL::Interval_nt NT_approx; //Gmpq or Quotient - typedef Exact_type_selector::Type NT_exact; + typedef Exact_field_selector::Type NT_exact; typedef CGAL::Simple_cartesian Kernel_approx; typedef CGAL::Simple_cartesian Kernel_exact; typedef typename Kernel_traits::Kernel Kernel_input; diff --git a/Alpha_shapes_3/include/CGAL/internal/Lazy_alpha_nt_3.h b/Alpha_shapes_3/include/CGAL/internal/Lazy_alpha_nt_3.h index 634342de55c..7ded7ec6ef0 100644 --- a/Alpha_shapes_3/include/CGAL/internal/Lazy_alpha_nt_3.h +++ b/Alpha_shapes_3/include/CGAL/internal/Lazy_alpha_nt_3.h @@ -74,7 +74,7 @@ class Lazy_alpha_nt_3{ //NT & kernels typedef CGAL::Interval_nt NT_approx; //Gmpq or Quotient - typedef Exact_type_selector::Type NT_exact; + typedef Exact_field_selector::Type NT_exact; typedef CGAL::Simple_cartesian Kernel_approx; typedef CGAL::Simple_cartesian Kernel_exact; //Helper class for weighted and non-weighted case diff --git a/Convex_hull_3/include/CGAL/convex_hull_3.h b/Convex_hull_3/include/CGAL/convex_hull_3.h index bd26b6d9b1b..3bd79501c0e 100644 --- a/Convex_hull_3/include/CGAL/convex_hull_3.h +++ b/Convex_hull_3/include/CGAL/convex_hull_3.h @@ -123,7 +123,7 @@ public: //and in case of failure, exact arithmetic is used. template class Is_on_positive_side_of_plane_3,Tag_true>{ - typedef Simple_cartesian::Type> PK; + typedef Simple_cartesian::Type> PK; typedef Simple_cartesian CK; typedef Convex_hull_traits_3 Traits; typedef typename Traits::Point_3 Point_3; diff --git a/Filtered_kernel/include/CGAL/Filtered_kernel.h b/Filtered_kernel/include/CGAL/Filtered_kernel.h index 992ba9db30e..5fe15176be1 100644 --- a/Filtered_kernel/include/CGAL/Filtered_kernel.h +++ b/Filtered_kernel/include/CGAL/Filtered_kernel.h @@ -54,7 +54,7 @@ template < typename CK > struct Filtered_kernel_base : public CK { - typedef typename internal::Exact_type_selector::Type Exact_nt; + typedef typename internal::Exact_field_selector::Type Exact_nt; typedef Simple_cartesian Exact_kernel; typedef Simple_cartesian Approximate_kernel; typedef Cartesian_converter C2E; diff --git a/Kernel_23/include/CGAL/Exact_predicates_exact_constructions_kernel.h b/Kernel_23/include/CGAL/Exact_predicates_exact_constructions_kernel.h index 87208dbe19b..b29b5505076 100644 --- a/Kernel_23/include/CGAL/Exact_predicates_exact_constructions_kernel.h +++ b/Kernel_23/include/CGAL/Exact_predicates_exact_constructions_kernel.h @@ -37,8 +37,8 @@ namespace CGAL { -// Epeck_ft is either Gmpq of Quotient -typedef internal::Exact_type_selector::Type Epeck_ft; +// Epeck_ft is either Gmpq or Quotient +typedef internal::Exact_field_selector::Type Epeck_ft; // The following are redefined kernels instead of simple typedefs in order to shorten // template name length (for error messages, mangling...). diff --git a/Number_types/include/CGAL/internal/Exact_type_selector.h b/Number_types/include/CGAL/internal/Exact_type_selector.h index d5c57e350ff..05f873fa94b 100644 --- a/Number_types/include/CGAL/internal/Exact_type_selector.h +++ b/Number_types/include/CGAL/internal/Exact_type_selector.h @@ -58,7 +58,7 @@ namespace CGAL { namespace internal { // The default template chooses Gmpq or Quotient. // 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 @@ -66,56 +66,56 @@ struct Exact_type_selector #endif template <> -struct Exact_type_selector +struct Exact_field_selector { typedef Quotient Type; }; template <> -struct Exact_type_selector > +struct Exact_field_selector > { typedef Quotient Type; }; // And we specialize for the following types : #ifdef CGAL_USE_GMP template <> -struct Exact_type_selector +struct Exact_field_selector { typedef Gmpq Type; }; template <> -struct Exact_type_selector +struct Exact_field_selector { 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_field_selector< ::mpq_class> { typedef ::mpq_class Type; }; #endif #ifdef CGAL_USE_LEDA template <> -struct Exact_type_selector +struct Exact_field_selector { typedef leda_rational Type; }; template <> -struct Exact_type_selector +struct Exact_field_selector { typedef leda_rational Type; }; template <> -struct Exact_type_selector +struct Exact_field_selector { typedef leda_real Type; }; #endif #ifdef CGAL_USE_CORE template <> -struct Exact_type_selector +struct Exact_field_selector { typedef CORE::Expr Type; }; #endif template < typename ET > -struct Exact_type_selector > +struct Exact_field_selector > { // We have a choice here : // - using ET gets rid of the DAG computation as well as redoing the interval diff --git a/Number_types/test/Number_types/Sqrt_extension.cpp b/Number_types/test/Number_types/Sqrt_extension.cpp index 52696fc389c..c67f9235b75 100644 --- a/Number_types/test/Number_types/Sqrt_extension.cpp +++ b/Number_types/test/Number_types/Sqrt_extension.cpp @@ -732,7 +732,7 @@ void sqrt_extension_test(){ #include void test_nt_converter() { - typedef CGAL::internal::Exact_type_selector::Type NT; + typedef CGAL::internal::Exact_field_selector::Type NT; typedef CGAL::Sqrt_extension Source; typedef CGAL::Sqrt_extension Target; diff --git a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3.h b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3.h index a9af1f4fff5..affeb39c2df 100644 --- a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3.h +++ b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3.h @@ -215,7 +215,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::Type EFT; + typedef typename internal::Exact_field_selector::Type EFT; typedef NT_converter NTC; CGAL_triangulation_assertion_code( NTC ntc; ) CGAL_triangulation_precondition(ntc(_domain.xmax())-ntc(_domain.xmin()) From c3a4b15686c53cea9fc3d3b5f01a791425f70568 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 24 Dec 2012 12:33:24 +0100 Subject: [PATCH 02/10] Introduce new Exact_ring_selector, not used yet. --- .../CGAL/internal/Exact_type_selector.h | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/Number_types/include/CGAL/internal/Exact_type_selector.h b/Number_types/include/CGAL/internal/Exact_type_selector.h index 05f873fa94b..1d79660538b 100644 --- a/Number_types/include/CGAL/internal/Exact_type_selector.h +++ b/Number_types/include/CGAL/internal/Exact_type_selector.h @@ -35,6 +35,7 @@ #ifdef CGAL_USE_GMP # include # include +# include #endif #ifdef CGAL_USE_GMPXX # include @@ -53,7 +54,7 @@ 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. // It should support the built-in types. @@ -65,10 +66,29 @@ struct Exact_field_selector { typedef Quotient 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_ring_selector +#if defined(CGAL_HAS_THREADS) || !defined(CGAL_USE_GMP) +{ typedef MP_Float Type; }; +#else +{ typedef Gmpzf Type; }; +#endif + +template <> +struct Exact_ring_selector : Exact_ring_selector { }; + template <> struct Exact_field_selector { typedef Quotient Type; }; +template <> +struct Exact_ring_selector +{ typedef MP_Float Type; }; + template <> struct Exact_field_selector > { typedef Quotient Type; }; @@ -79,6 +99,14 @@ template <> struct Exact_field_selector { typedef Gmpq Type; }; +template <> +struct Exact_ring_selector +{ typedef Gmpz Type; }; + +template <> +struct Exact_ring_selector +{ typedef Gmpzf Type; }; + template <> struct Exact_field_selector { typedef Gmpq Type; }; @@ -89,6 +117,10 @@ template <> struct Exact_field_selector< ::mpz_class> { typedef ::mpq_class Type; }; +template <> +struct Exact_ring_selector< ::mpz_class> +{ typedef ::mpz_class Type; }; + template <> struct Exact_field_selector< ::mpq_class> { typedef ::mpq_class Type; }; @@ -99,6 +131,10 @@ template <> struct Exact_field_selector { typedef leda_rational Type; }; +template <> +struct Exact_ring_selector +{ typedef leda_integer Type; }; + template <> struct Exact_field_selector { typedef leda_rational Type; }; @@ -122,6 +158,8 @@ struct Exact_field_selector > // - using Lazy_exact_nt might use sharper intervals. typedef ET Type; // typedef Lazy_exact_nt Type; + + // Should this forward to Exact_field_selector ? -- Marc Glisse, 2012-12. }; } } // namespace CGAL::internal From 844e285f32669aba4952f1491cd61e9f809856f1 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 24 Dec 2012 14:16:39 +0100 Subject: [PATCH 03/10] For a hardcoded list of "safe" predicates, use a ring type as the exact type in Filtered_kernel_base. --- .../include/CGAL/Filtered_kernel.h | 61 +++++++++++++++---- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/Filtered_kernel/include/CGAL/Filtered_kernel.h b/Filtered_kernel/include/CGAL/Filtered_kernel.h index 5fe15176be1..d96d16dcb6d 100644 --- a/Filtered_kernel/include/CGAL/Filtered_kernel.h +++ b/Filtered_kernel/include/CGAL/Filtered_kernel.h @@ -51,7 +51,7 @@ namespace CGAL { // Exact_kernel = exact kernel called when needed by the filter. // Approximate_kernel = filtering "interval" kernel template < typename CK > -struct Filtered_kernel_base +struct Filtered_kernel_base_FT : public CK { typedef typename internal::Exact_field_selector::Type Exact_nt; @@ -60,6 +60,54 @@ struct Filtered_kernel_base typedef Cartesian_converter C2E; typedef Cartesian_converter C2F; + // We change the predicates. +#define CGAL_Kernel_pred(P, Pf) \ + typedef Filtered_predicate P; \ + P Pf() const { return P(); } + + // We don't touch the constructions. +#define CGAL_Kernel_cons(Y,Z) + +#include + +}; + +template < typename CK > +struct Filtered_kernel_base_RT + : public CK +{ + typedef typename internal::Exact_ring_selector::Type Exact_rt; + typedef Simple_cartesian EK_rt; + typedef Simple_cartesian AK_rt; + typedef Cartesian_converter C2E_rt; + typedef Cartesian_converter C2F_rt; + +// Change the predicates for which we know the Simple_cartesian implementation +// does not use divisions. +#define CGAL_Kernel_pred(P, Pf) \ + typedef Filtered_predicate P; \ + P Pf() const { return P(); } + +CGAL_Kernel_pred(Orientation_2, + orientation_2_object) +CGAL_Kernel_pred(Orientation_3, + orientation_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) + +#undef CGAL_Kernel_pred +}; + +template < typename CK > +struct Filtered_kernel_base + : public Filtered_kernel_base_RT < Filtered_kernel_base_FT < CK > > +{ enum { Has_filtered_predicates = true }; typedef Boolean_tag Has_filtered_predicates_tag; @@ -78,17 +126,6 @@ struct Filtered_kernel_base struct Feature_dimension { typedef typename T::Feature_dimension type; // maybe not the right way... }; - - // We change the predicates. -#define CGAL_Kernel_pred(P, Pf) \ - typedef Filtered_predicate P; \ - P Pf() const { return P(); } - - // We don't touch the constructions. -#define CGAL_Kernel_cons(Y,Z) - -#include - }; template < typename CK > From 215ceca0fbd3fc1162aded16226bc23caab0a9b2 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 24 Dec 2012 15:53:00 +0100 Subject: [PATCH 04/10] Reminder that this currently breaks homogeneous kernels and needs to be fixed. --- Filtered_kernel/include/CGAL/Filtered_kernel.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Filtered_kernel/include/CGAL/Filtered_kernel.h b/Filtered_kernel/include/CGAL/Filtered_kernel.h index d96d16dcb6d..10856bab48c 100644 --- a/Filtered_kernel/include/CGAL/Filtered_kernel.h +++ b/Filtered_kernel/include/CGAL/Filtered_kernel.h @@ -76,6 +76,7 @@ template < typename CK > struct Filtered_kernel_base_RT : public CK { + // FIXME: This does not work for homogeneous kernels. Use CK::Rep_tag to dispatch, and for homogeneous use Simple_homogeneous for all predicates? typedef typename internal::Exact_ring_selector::Type Exact_rt; typedef Simple_cartesian EK_rt; typedef Simple_cartesian AK_rt; From a78d419ba800a2e0baabadb8f0427ced1ecfa3ac Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 24 Dec 2012 23:37:59 +0100 Subject: [PATCH 05/10] Fix the homogeneous case. --- .../include/CGAL/Filtered_kernel.h | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/Filtered_kernel/include/CGAL/Filtered_kernel.h b/Filtered_kernel/include/CGAL/Filtered_kernel.h index 10856bab48c..859781855ce 100644 --- a/Filtered_kernel/include/CGAL/Filtered_kernel.h +++ b/Filtered_kernel/include/CGAL/Filtered_kernel.h @@ -26,6 +26,10 @@ #include #include #include +// We need a simple forward declaration to avoid including the whole +// homogeneous kernel here. +#include +#include #include #include @@ -76,7 +80,6 @@ template < typename CK > struct Filtered_kernel_base_RT : public CK { - // FIXME: This does not work for homogeneous kernels. Use CK::Rep_tag to dispatch, and for homogeneous use Simple_homogeneous for all predicates? typedef typename internal::Exact_ring_selector::Type Exact_rt; typedef Simple_cartesian EK_rt; typedef Simple_cartesian AK_rt; @@ -84,7 +87,8 @@ struct Filtered_kernel_base_RT typedef Cartesian_converter C2F_rt; // Change the predicates for which we know the Simple_cartesian implementation -// does not use divisions. +// does not use divisions. Use a different macro in interface_macros to +// distinguish those predicates? #define CGAL_Kernel_pred(P, Pf) \ typedef Filtered_predicate P; \ P Pf() const { return P(); } @@ -106,8 +110,43 @@ CGAL_Kernel_pred(Side_of_oriented_sphere_3, }; template < typename CK > -struct Filtered_kernel_base +struct Filtered_kernel_base_hom + : public CK +{ + typedef typename internal::Exact_ring_selector::Type Exact_nt; + typedef Simple_homogeneous Exact_kernel; + typedef Simple_cartesian Approximate_kernel; + typedef Homogeneous_converter C2E; + typedef Cartesian_converter C2F; + // Note that the converter will call point.x() and point.y() and convert + // those to intervals; it could instead call point.hx(), point.hy() and + // point.hz(), convert them to intervals and then divide to get x and y. + + // We change the predicates. +#define CGAL_Kernel_pred(P, Pf) \ + typedef Filtered_predicate P; \ + P Pf() const { return P(); } + + // We don't touch the constructions. +#define CGAL_Kernel_cons(Y,Z) + +#include + +}; + +template < typename CK, typename = typename CK::Rep_tag /* Cartesian_tag */> +struct Filtered_kernel_base_impl : public Filtered_kernel_base_RT < Filtered_kernel_base_FT < CK > > +{}; + +template < typename CK > +struct Filtered_kernel_base_impl < CK, Homogeneous_tag > + : public Filtered_kernel_base_hom < CK > +{}; + +template < typename CK > +struct Filtered_kernel_base + : public Filtered_kernel_base_impl < CK > { enum { Has_filtered_predicates = true }; typedef Boolean_tag Has_filtered_predicates_tag; From e1b8d79f6d379f8376b9b9470a4c971501815a33 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 25 Dec 2012 16:03:03 +0100 Subject: [PATCH 06/10] Couple simple optimizations in Gmpzf, just enough to move it from barely slower than MP_Float to barely faster in my test. --- Number_types/include/CGAL/GMP/Gmpzf_type.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Number_types/include/CGAL/GMP/Gmpzf_type.h b/Number_types/include/CGAL/GMP/Gmpzf_type.h index e2e6e0300d9..d56d8a9f89e 100644 --- a/Number_types/include/CGAL/GMP/Gmpzf_type.h +++ b/Number_types/include/CGAL/GMP/Gmpzf_type.h @@ -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; } From b9d1dd2ff3d5d2c637e3b49d029079d03e3dfbac Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 25 Dec 2012 16:20:04 +0100 Subject: [PATCH 07/10] No point using a static variable for this constant. --- Number_types/include/CGAL/GMP/Gmpzf_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Number_types/include/CGAL/GMP/Gmpzf_type.h b/Number_types/include/CGAL/GMP/Gmpzf_type.h index d56d8a9f89e..4fdadcc227f 100644 --- a/Number_types/include/CGAL/GMP/Gmpzf_type.h +++ b/Number_types/include/CGAL/GMP/Gmpzf_type.h @@ -163,7 +163,7 @@ public: e = 0; return; } - static int p = std::numeric_limits::digits; + const int p = std::numeric_limits::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 From bf7823fe30ba3efda204ce29da6419e75b54600b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 14 Jan 2013 13:39:43 +0100 Subject: [PATCH 08/10] Let Exact_(field|ring)_selector> select a type based on ET, instead of directly returning ET. Teach NT_converter about these conversions. --- Number_types/include/CGAL/Lazy_exact_nt.h | 30 +++++++++++++++++++ .../CGAL/internal/Exact_type_selector.h | 9 ++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Number_types/include/CGAL/Lazy_exact_nt.h b/Number_types/include/CGAL/Lazy_exact_nt.h index 9526f57d7b2..70c838aa7d3 100644 --- a/Number_types/include/CGAL/Lazy_exact_nt.h +++ b/Number_types/include/CGAL/Lazy_exact_nt.h @@ -46,6 +46,7 @@ #include #include +#include /* * This file contains the definition of the number type Lazy_exact_nt, @@ -1313,6 +1314,35 @@ struct NT_converter < Lazy_exact_nt, ET > { return a.exact(); } }; +// Forward declaration to break inclusion cycle +namespace internal { +templatestruct Exact_field_selector; +templatestruct Exact_ring_selector; +} +// Compiler can deduce ET from the first argument. +template < typename ET > +struct NT_converter < Lazy_exact_nt, + typename First_if_different< + typename internal::Exact_field_selector::Type, + ET>::Type> +{ + typename internal::Exact_field_selector::Type + operator()(const Lazy_exact_nt &a) const + { return NT_converter::Type>()(a.exact()); } +}; + +template < typename ET > +struct NT_converter < Lazy_exact_nt, + typename First_if_different< + typename First_if_different< + typename internal::Exact_ring_selector::Type, + ET>::Type, + typename internal::Exact_field_selector::Type>::Type> +{ + typename internal::Exact_ring_selector::Type operator()(const Lazy_exact_nt &a) const + { return NT_converter::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 diff --git a/Number_types/include/CGAL/internal/Exact_type_selector.h b/Number_types/include/CGAL/internal/Exact_type_selector.h index 1d79660538b..3f8241ad139 100644 --- a/Number_types/include/CGAL/internal/Exact_type_selector.h +++ b/Number_types/include/CGAL/internal/Exact_type_selector.h @@ -152,15 +152,18 @@ struct Exact_field_selector template < typename ET > struct Exact_field_selector > +: Exact_field_selector { // We have a choice here : // - using ET gets rid of the DAG computation as well as redoing the interval // - using Lazy_exact_nt might use sharper intervals. - typedef ET Type; + // typedef ET Type; // typedef Lazy_exact_nt Type; - - // Should this forward to Exact_field_selector ? -- Marc Glisse, 2012-12. }; +template < typename ET > +struct Exact_ring_selector > +: Exact_ring_selector +{}; } } // namespace CGAL::internal From 5373cff1b37aecf2c2ae298d998b88155171f9c7 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 14 Jan 2013 14:19:51 +0100 Subject: [PATCH 09/10] Split some predicates into CGAL_Kernel_pred_RT. --- .../include/CGAL/Kernel/interface_macros.h | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Kernel_23/include/CGAL/Kernel/interface_macros.h b/Kernel_23/include/CGAL/Kernel/interface_macros.h index 98936757b6f..2a4587e24bb 100644 --- a/Kernel_23/include/CGAL/Kernel/interface_macros.h +++ b/Kernel_23/include/CGAL/Kernel/interface_macros.h @@ -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 From 2ba8c67ba3871dddd1a1ff502998f78f804572cc Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 14 Jan 2013 15:20:34 +0100 Subject: [PATCH 10/10] Re-implement ring filtering based on CGAL_Kernel_pred_RT. --- .../include/CGAL/Filtered_kernel.h | 142 ++++++------------ 1 file changed, 49 insertions(+), 93 deletions(-) diff --git a/Filtered_kernel/include/CGAL/Filtered_kernel.h b/Filtered_kernel/include/CGAL/Filtered_kernel.h index 859781855ce..468c1411dcb 100644 --- a/Filtered_kernel/include/CGAL/Filtered_kernel.h +++ b/Filtered_kernel/include/CGAL/Filtered_kernel.h @@ -26,8 +26,6 @@ #include #include #include -// We need a simple forward declaration to avoid including the whole -// homogeneous kernel here. #include #include #include @@ -37,6 +35,7 @@ #include #include +#include // This file contains the definition of a generic kernel filter. // @@ -50,104 +49,46 @@ // traits-like mechanism ? namespace CGAL { +namespace Filter { +template +struct Select_exact_kernel +{ + typedef typename internal::Exact_field_selector::Type Exact_nt; + typedef typename internal::Exact_ring_selector ::Type Exact_rt; + typedef Simple_cartesian Exact_kernel; + typedef Simple_cartesian Exact_kernel_rt; + typedef Cartesian_converter C2E; + typedef Cartesian_converter C2E_rt; +}; + +template +struct Select_exact_kernel +{ + typedef typename internal::Exact_ring_selector::Type Exact_nt; + typedef Simple_homogeneous Exact_kernel; + typedef Homogeneous_converter 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. // Approximate_kernel = filtering "interval" kernel -template < typename CK > -struct Filtered_kernel_base_FT - : public CK -{ - typedef typename internal::Exact_field_selector::Type Exact_nt; - typedef Simple_cartesian Exact_kernel; - typedef Simple_cartesian Approximate_kernel; - typedef Cartesian_converter C2E; - typedef Cartesian_converter C2F; - - // We change the predicates. -#define CGAL_Kernel_pred(P, Pf) \ - typedef Filtered_predicate P; \ - P Pf() const { return P(); } - - // We don't touch the constructions. -#define CGAL_Kernel_cons(Y,Z) - -#include - -}; - -template < typename CK > -struct Filtered_kernel_base_RT - : public CK -{ - typedef typename internal::Exact_ring_selector::Type Exact_rt; - typedef Simple_cartesian EK_rt; - typedef Simple_cartesian AK_rt; - typedef Cartesian_converter C2E_rt; - typedef Cartesian_converter C2F_rt; - -// Change the predicates for which we know the Simple_cartesian implementation -// does not use divisions. Use a different macro in interface_macros to -// distinguish those predicates? -#define CGAL_Kernel_pred(P, Pf) \ - typedef Filtered_predicate P; \ - P Pf() const { return P(); } - -CGAL_Kernel_pred(Orientation_2, - orientation_2_object) -CGAL_Kernel_pred(Orientation_3, - orientation_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) - -#undef CGAL_Kernel_pred -}; - -template < typename CK > -struct Filtered_kernel_base_hom - : public CK -{ - typedef typename internal::Exact_ring_selector::Type Exact_nt; - typedef Simple_homogeneous Exact_kernel; - typedef Simple_cartesian Approximate_kernel; - typedef Homogeneous_converter C2E; - typedef Cartesian_converter C2F; - // Note that the converter will call point.x() and point.y() and convert - // those to intervals; it could instead call point.hx(), point.hy() and - // point.hz(), convert them to intervals and then divide to get x and y. - - // We change the predicates. -#define CGAL_Kernel_pred(P, Pf) \ - typedef Filtered_predicate P; \ - P Pf() const { return P(); } - - // We don't touch the constructions. -#define CGAL_Kernel_cons(Y,Z) - -#include - -}; - -template < typename CK, typename = typename CK::Rep_tag /* Cartesian_tag */> -struct Filtered_kernel_base_impl - : public Filtered_kernel_base_RT < Filtered_kernel_base_FT < CK > > -{}; - -template < typename CK > -struct Filtered_kernel_base_impl < CK, Homogeneous_tag > - : public Filtered_kernel_base_hom < CK > -{}; - template < typename CK > struct Filtered_kernel_base - : public Filtered_kernel_base_impl < CK > + : public CK { + // Use Select_exact_kernel as a base class? + typedef typename Filter::Select_exact_kernel::Exact_nt Exact_nt; + typedef typename Filter::Select_exact_kernel::Exact_kernel Exact_kernel; + typedef typename Filter::Select_exact_kernel::Exact_kernel_rt Exact_kernel_rt; + typedef typename Filter::Select_exact_kernel::C2E C2E; + typedef typename Filter::Select_exact_kernel::C2E_rt C2E_rt; + + typedef Simple_cartesian Approximate_kernel; + typedef Cartesian_converter C2F; + enum { Has_filtered_predicates = true }; typedef Boolean_tag Has_filtered_predicates_tag; @@ -166,6 +107,21 @@ struct Filtered_kernel_base struct Feature_dimension { typedef typename T::Feature_dimension type; // maybe not the right way... }; + + // We change the predicates. +#define CGAL_Kernel_pred(P, Pf) \ + typedef Filtered_predicate P; \ + P Pf() const { return P(); } + +#define CGAL_Kernel_pred_RT(P, Pf) \ + typedef Filtered_predicate P; \ + P Pf() const { return P(); } + + // We don't touch the constructions. +#define CGAL_Kernel_cons(Y,Z) + +#include + }; template < typename CK >