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..468c1411dcb 100644 --- a/Filtered_kernel/include/CGAL/Filtered_kernel.h +++ b/Filtered_kernel/include/CGAL/Filtered_kernel.h @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -33,6 +35,7 @@ #include #include +#include // This file contains the definition of a generic kernel filter. // @@ -46,6 +49,28 @@ // 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. @@ -54,11 +79,15 @@ template < typename CK > struct Filtered_kernel_base : public CK { - typedef typename internal::Exact_type_selector::Type Exact_nt; - typedef Simple_cartesian Exact_kernel; - typedef Simple_cartesian Approximate_kernel; - typedef Cartesian_converter C2E; - typedef Cartesian_converter C2F; + // 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; @@ -84,6 +113,10 @@ struct Filtered_kernel_base 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) 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/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 diff --git a/Number_types/include/CGAL/GMP/Gmpzf_type.h b/Number_types/include/CGAL/GMP/Gmpzf_type.h index e2e6e0300d9..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 @@ -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; } diff --git a/Number_types/include/CGAL/Lazy_exact_nt.h b/Number_types/include/CGAL/Lazy_exact_nt.h index e012d36f190..e8a6b6cd45e 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, @@ -1323,6 +1324,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 d5c57e350ff..3f8241ad139 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,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. // 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 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 +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_type_selector > +struct Exact_ring_selector +{ typedef MP_Float Type; }; + +template <> +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_ring_selector +{ typedef Gmpz Type; }; + +template <> +struct Exact_ring_selector +{ typedef Gmpzf Type; }; + +template <> +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_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 +struct Exact_field_selector { typedef leda_rational Type; }; template <> -struct Exact_type_selector +struct Exact_ring_selector +{ typedef leda_integer Type; }; + +template <> +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 > +: 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; }; +template < typename ET > +struct Exact_ring_selector > +: Exact_ring_selector +{}; } } // namespace CGAL::internal 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 16d3b57859c..331ee2b3a8b 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 @@ -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::Type EFT; + typedef typename internal::Exact_field_selector::Type EFT; typedef NT_converter NTC; CGAL_USE_TYPE(NTC); CGAL_triangulation_assertion_code( NTC ntc; )