// Copyright (c) 2005,2006 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ // // // Author(s) : Andreas Fabri, Sylvain Pion #ifndef CGAL_LAZY_KERNEL_H #define CGAL_LAZY_KERNEL_H #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable:4348) // redefinition of default parameter in nested template class #endif namespace CGAL { namespace internal { // SFINAE way to detect result_type typedefs. template class Has_result_type_helper { typedef char one; typedef struct { char arr[2]; } two; template struct Wrapper {}; template static one test(Wrapper*); template static two test(...); public: static const bool value = sizeof(test(0)) == 1; }; template struct Has_result_type : boost::integral_constant< bool, Has_result_type_helper< typename boost::remove_cv::type>::value> {}; template struct Get_result_type { typedef typename T::result_type type; }; template struct Lazy_result_type : boost::mpl::eval_if< Has_result_type, Get_result_type, boost::mpl::identity > {}; class Enum_holder { protected: enum { NONE, NT, VARIANT, OBJECT, BBOX }; }; } // internal // Exact_kernel = exact kernel that will be made lazy // Kernel = lazy kernel // the Generic base simplies applies the generic magic functor stupidly. // then the real base fixes up a few special cases. template < typename EK_, typename AK_, typename E2A_, typename Kernel_ > class Lazy_kernel_generic_base : protected internal::Enum_holder // : public Filtered_kernel_base // TODO : Static_filters_base too ? Check performance { public: typedef AK_ Approximate_kernel; typedef EK_ Exact_kernel; typedef E2A_ E2A; typedef Kernel_ Kernel; typedef Lazy_kernel_generic_base Self; // synonym identical to Filtered_kernel typedef AK_ FK; // Note: Approx_converter and Exact_converter are defined in typedef Approx_converter C2F; typedef Exact_converter C2E; template < typename Kernel2 > struct Base { typedef Lazy_kernel_generic_base Type; }; template < typename T > struct Ambient_dimension { typedef typename T::Ambient_dimension type; }; template < typename T > struct Feature_dimension { typedef typename T::Feature_dimension type; }; typedef typename Exact_kernel::Kernel_tag Kernel_tag; typedef typename Exact_kernel::Rep_tag Rep_tag; enum { Has_filtered_predicates = true }; enum { Has_static_filters = false }; typedef Boolean_tag Has_filtered_predicates_tag; // Types typedef CGAL::Lazy_exact_nt FT; typedef FT RT; typedef typename Same_uncertainty_nt::type Boolean; typedef typename Same_uncertainty_nt::type Sign; typedef typename Same_uncertainty_nt::type Comparison_result; typedef typename Same_uncertainty_nt::type Orientation; typedef typename Same_uncertainty_nt::type Oriented_side; typedef typename Same_uncertainty_nt::type Bounded_side; typedef typename Same_uncertainty_nt::type Angle; typedef CGAL::Object Object_2; typedef CGAL::Object Object_3; #define CGAL_Kernel_obj(X) \ typedef Lazy X; CGAL_Kernel_obj(Data_accessor_2) CGAL_Kernel_obj(Conic_2) typedef Cartesian_coordinate_iterator_2 Cartesian_const_iterator_2; typedef Cartesian_coordinate_iterator_3 Cartesian_const_iterator_3; // Aff_transformation_2/3 operations are not functorized, so treat it as // an exterior object for now. // CGAL_Kernel_obj(Aff_transformation_2) // CGAL_Kernel_obj(Aff_transformation_3) typedef CGAL::Aff_transformationC2 Aff_transformation_2; typedef CGAL::Aff_transformationC3 Aff_transformation_3; private: // We use a combination of partial and logic to extract the right // construction. Constructions without a result_type always have to // be done through specializations. // // The case distinction goes as follows: // result_type == FT => NT // result_type == Object => Object // result_type == Bbox_2 || result_type == Bbox_3 => BBOX // default => NONE // no result_type => NONE // // // we require a Dummy because we cannot have complete // specializations inside a non-namespace scope. // The default implementation does some default handling, // the special cases are filtered by partial specializations. template struct Lazy_wrapper_traits : boost::mpl::eval_if< internal::Has_result_type, boost::mpl::eval_if< boost::is_same< typename boost::remove_cv< typename boost::remove_reference< typename internal::Lazy_result_type::type >::type >::type, typename Approximate_kernel::FT>, boost::mpl::int_, boost::mpl::eval_if< boost::is_same< typename internal::Lazy_result_type::type, CGAL::Object >, boost::mpl::int_, boost::mpl::eval_if< boost::mpl::or_< boost::is_same< typename internal::Lazy_result_type::type, CGAL::Bbox_2 >, boost::is_same< typename internal::Lazy_result_type::type, CGAL::Bbox_3 > >, boost::mpl::int_, boost::mpl::int_ > > >, boost::mpl::int_ >::type {}; #define CGAL_WRAPPER_TRAIT(NAME, WRAPPER) \ template \ struct Lazy_wrapper_traits \ : boost::mpl::int_ {}; #if CGAL_INTERSECTION_VERSION > 1 CGAL_WRAPPER_TRAIT(Intersect_2, VARIANT) CGAL_WRAPPER_TRAIT(Intersect_3, VARIANT) #else CGAL_WRAPPER_TRAIT(Intersect_2, OBJECT) CGAL_WRAPPER_TRAIT(Intersect_3, OBJECT) #endif CGAL_WRAPPER_TRAIT(Compute_squared_radius_2, NT) CGAL_WRAPPER_TRAIT(Compute_x_3, NT) CGAL_WRAPPER_TRAIT(Compute_y_3, NT) CGAL_WRAPPER_TRAIT(Compute_z_3, NT) #undef CGAL_WRAPPER_TRAIT template ::value> struct Select_wrapper_impl; template struct Select_wrapper_impl { template struct apply { typedef Lazy_construction type; }; }; template struct Select_wrapper_impl { template struct apply { typedef Lazy_construction_nt type; }; }; template struct Select_wrapper_impl { template struct apply { typedef Lazy_construction_variant type; }; }; template struct Select_wrapper_impl { template struct apply { typedef Lazy_construction_object type; }; }; template struct Select_wrapper_impl { template struct apply { typedef Lazy_construction_bbox type; }; }; template struct Select_wrapper : Select_wrapper_impl {}; public: #ifdef CGAL_NO_STATIC_FILTERS_FOR_LAZY_KERNEL #define CGAL_Kernel_pred(P, Pf) \ typedef Filtered_predicate P; \ P Pf() const { return P(); } #else #define CGAL_Kernel_pred(P, Pf) \ typedef Static_filtered_predicate, Exact_predicates_inexact_constructions_kernel::P> P; \ P Pf() const { return P(); } #endif #define CGAL_Kernel_cons(C, Cf) \ typedef typename Select_wrapper::template apply::type C; \ C Cf() const { return C(); } #include }; template < typename EK_, typename AK_, typename E2A_, typename Kernel_ > class Lazy_kernel_base : public Lazy_kernel_generic_base { public: typedef Kernel_ Kernel; typedef AK_ Approximate_kernel; typedef EK_ Exact_kernel; typedef E2A_ E2A; typedef Lazy_kernel_generic_base BaseClass; template < typename Kernel2 > struct Base { typedef Lazy_kernel_base Type; }; typedef CommonKernelFunctors::Assign_2 Assign_2; typedef CommonKernelFunctors::Assign_3 Assign_3; typedef Lazy_construction_bbox Construct_bbox_2; typedef Lazy_construction_bbox Construct_bbox_3; typedef Lazy_cartesian_const_iterator_2 Construct_cartesian_const_iterator_2; typedef Lazy_cartesian_const_iterator_3 Construct_cartesian_const_iterator_3; typedef CGAL::CartesianKernelFunctors::Compute_approximate_squared_length_3 Compute_approximate_squared_length_3; typedef CGAL::CartesianKernelFunctors::Compute_approximate_area_3 Compute_approximate_area_3; // typedef void Compute_z_3; // to detect where .z() is called // typedef void Construct_point_3; // to detect where the ctor is called struct Compute_weight_2 : public BaseClass::Compute_weight_2 { typedef typename Kernel_::FT FT; typedef typename Kernel_::Point_2 Point_2; typedef typename Kernel_::Weighted_point_2 Weighted_point_2; FT operator()(const Weighted_point_2& p) const { typedef Lazy_rep_3 LR; LR * lr = dynamic_cast(p.ptr()); if(lr && (! lr->et)){ return lr->l2; } return BaseClass().compute_weight_2_object()(p); } }; struct Compute_weight_3 : public BaseClass::Compute_weight_3 { typedef typename Kernel_::FT FT; typedef typename Kernel_::Point_3 Point_3; typedef typename Kernel_::Weighted_point_3 Weighted_point_3; FT operator()(const Weighted_point_3& p) const { typedef Lazy_rep_3 LR; LR * lr = dynamic_cast(p.ptr()); if(lr && (! lr->et)){ return lr->l2; } return BaseClass().compute_weight_3_object()(p); } }; struct Construct_point_2 : public BaseClass::Construct_point_2 { typedef typename Kernel_::FT FT; typedef typename Kernel_::Point_2 Point_2; typedef typename Kernel_::Weighted_point_2 Weighted_point_2; #ifndef CGAL_CFG_MATCHING_BUG_6 using BaseClass::Construct_point_2::operator(); #else // CGAL_CFG_MATCHING_BUG_6 template Point_2 operator()(const T& ...t) const { return BaseClass().construct_point_2_object()(t...); } #endif // CGAL_CFG_MATCHING_BUG_6 const Point_2& operator()(const Point_2& p) const { return p; } Point_2 operator()(const Weighted_point_2& p) const { typedef Lazy_rep_3 LR; typedef Lazy_rep_3 LRint; LR * lr = dynamic_cast(p.ptr()); if(lr && (! lr->et)){ return lr->l1; } else { LRint* lrint = dynamic_cast(p.ptr()); if(lrint && (! lrint->et)){ return lrint->l1; } } return BaseClass().construct_point_2_object()(p); } }; struct Construct_point_3 : public BaseClass::Construct_point_3 { typedef typename Kernel_::FT FT; typedef typename Kernel_::Point_3 Point_3; typedef typename Kernel_::Weighted_point_3 Weighted_point_3; #ifndef CGAL_CFG_MATCHING_BUG_6 using BaseClass::Construct_point_3::operator(); #else // CGAL_CFG_MATCHING_BUG_6 template Point_3 operator()(const T& ...t) const { return BaseClass().construct_point_3_object()(t...); } #endif // CGAL_CFG_MATCHING_BUG_6 const Point_3& operator()(const Point_3& p) const { return p; } Point_3 operator()(const Weighted_point_3& p) const { typedef Lazy_rep_3 LR; typedef Lazy_rep_3 LRint; LR * lr = dynamic_cast(p.ptr()); if(lr && (! lr->et)){ return lr->l1; }else{ LRint* lrint = dynamic_cast(p.ptr()); if(lrint && (! lrint->et)){ return lrint->l1; } } return BaseClass().construct_point_3_object()(p); } }; Construct_point_2 construct_point_2_object() const { return Construct_point_2(); } Construct_point_3 construct_point_3_object() const { return Construct_point_3(); } Compute_weight_2 compute_weight_2_object() const { return Compute_weight_2(); } Compute_weight_3 compute_weight_3_object() const { return Compute_weight_3(); } Assign_2 assign_2_object() const { return Assign_2(); } Assign_3 assign_3_object() const { return Assign_3(); } Construct_bbox_2 construct_bbox_2_object() const { return Construct_bbox_2(); } Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); } Construct_cartesian_const_iterator_2 construct_cartesian_const_iterator_2_object() const { return Construct_cartesian_const_iterator_2(); } Construct_cartesian_const_iterator_3 construct_cartesian_const_iterator_3_object() const { return Construct_cartesian_const_iterator_3(); } Compute_approximate_squared_length_3 compute_approximate_squared_length_3_object() const { return Compute_approximate_squared_length_3(); } Compute_approximate_area_3 compute_approximate_area_3_object() const { return Compute_approximate_area_3(); } }; // end class Lazy_kernel_base template struct Lazy_kernel_without_type_equality : public Lazy_kernel_base< Exact_kernel, Approximate_kernel, E2A, Lazy_kernel_without_type_equality > {}; template , class E2A = Cartesian_converter > struct Lazy_kernel : public Type_equality_wrapper< Lazy_kernel_base< Exact_kernel, Approximate_kernel, E2A, Lazy_kernel >, Lazy_kernel > { // WARNING: If you change the definition of Lazy_kernel, then you need to // change also the definition of Epeck in // . }; } //namespace CGAL #if defined(BOOST_MSVC) # pragma warning(pop) #endif #endif // CGAL_LAZY_KERNEL_H