diff --git a/Filtered_kernel/include/CGAL/Lazy.h b/Filtered_kernel/include/CGAL/Lazy.h index 09588df9988..58a6c67f42e 100644 --- a/Filtered_kernel/include/CGAL/Lazy.h +++ b/Filtered_kernel/include/CGAL/Lazy.h @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -107,27 +109,27 @@ depth(const Lazy& l) inline const T & exact (const T& d) { return d; } \ inline unsigned depth (const T& ) { return 0; } - -CGAL_LAZY_FORWARD(long double) -CGAL_LAZY_FORWARD(double) -CGAL_LAZY_FORWARD(float) -CGAL_LAZY_FORWARD(int) -CGAL_LAZY_FORWARD(unsigned int) -CGAL_LAZY_FORWARD(long) -CGAL_LAZY_FORWARD(unsigned long) -#ifdef CGAL_USE_LONG_LONG -CGAL_LAZY_FORWARD(long long) -CGAL_LAZY_FORWARD(unsigned long long) -#endif -CGAL_LAZY_FORWARD(Return_base_tag) -CGAL_LAZY_FORWARD(Null_vector) -CGAL_LAZY_FORWARD(Origin) -CGAL_LAZY_FORWARD(Orientation) CGAL_LAZY_FORWARD(Bbox_2) CGAL_LAZY_FORWARD(Bbox_3) - #undef CGAL_LAZY_FORWARD +templateinline std::enable_if_t::value||std::is_enum::value, T> approx(T d){return d;} +templateinline std::enable_if_t::value||std::is_enum::value, T> exact (T d){return d;} +templateinline std::enable_if_t::value||std::is_enum::value, unsigned> depth(T){return 0;} + +// For tag classes: Return_base_tag, Homogeneous_tag, Null_vector, Origin +templateinline std::enable_if_t::value, T> exact(T){return {};} +templateinline std::enable_if_t::value, T> approx(T){return {};} +templateinline std::enable_if_t::value, unsigned> depth(T){return 0;} + +// For an iterator, exact/approx applies to the objects it points to +template ::value>> +auto exact(T const& t) {return make_transforming_iterator(t,[](auto const&u){return CGAL::exact(u);});} +template ::value>> +auto approx(T const& t) {return make_transforming_iterator(t,[](auto const&u){return CGAL::approx(u);});} +template ::value>> +unsigned depth(T const& t) {return 1;} // FIXME: depth(*t) would be better when t is valid, but not for end iterators, and the true answer would iterate on the range, but we can't do that with only one iterator... We need to replace iterators with ranges to solve that. + #ifdef CGAL_LAZY_KERNEL_DEBUG template void @@ -311,6 +313,51 @@ public: }; +template +class Lazy_rep_n : + public Lazy_rep< AT, ET, E2A >, private EC +{ + // Lazy_rep_0 does not inherit from EC or take a parameter AC. It has different constructors. + static_assert(sizeof...(L)>0, "Use Lazy_rep_0 instead"); + template friend class Lazy_kernel_base; + mutable std::tuple l; // L...l; is not yet allowed. + const EC& ec() const { return *this; } + template + void update_exact_helper(std::index_sequence) const { + this->et = new ET(ec()( CGAL::exact( std::get(l) ) ... ) ); + this->at = E2A()(*(this->et)); + l = std::tuple{}; + } + public: + void update_exact() const { + update_exact_helper(std::make_index_sequence{}); + } + Lazy_rep_n(const AC& ac, const EC& ec, L const&...ll) : + Lazy_rep(ac(CGAL::approx(ll)...)), EC(ec), l(ll...) + { + this->set_depth(std::max({ -1, (int)CGAL::depth(ll)...}) + 1); + } +#ifdef CGAL_LAZY_KERNEL_DEBUG + private: + template + void print_dag_helper(std::ostream& os, int level, std::index_sequence) const { + this->print_at_et(os, level); + if(this->is_lazy()){ +# ifdef CGAL_LAZY_KERNEL_DEBUG_SHOW_TYPEID + CGAL::msg(os, level, typeid(AC).name()); +# endif + CGAL::msg(os, level, "DAG with " "3" " child nodes:"); + using expander = int[]; + expander{0,(CGAL::print_dag(std::get(l), os, level+1),0)...}; + } + } + public: + void print_dag(std::ostream& os, int level) const { + print_dag_helper(os, level, std::make_index_sequence{}); + } +#endif +}; + //____________________________________________________________ // The rep for the leaf node @@ -352,116 +399,6 @@ public: #define CGAL_LEXACT(z,n,t) CGAL::exact( l##n ) #define CGAL_LARGS(z, n, t) L##n const& l##n -#define CGAL_TMAP(z, n, d) typename Type_mapper< L##n, d##K, LK >::type -#define CGAL_PRUNE_TREE(z, n, d) l##n = L##n (); -#define CGAL_LINIT(z, n, d) l##n(l##n) -#define CGAL_LN(z, n, d) d(l##n) -#define CGAL_MLIST(z, n, d) mutable L##n l##n; - -//____________________________________________________________ - -template -class Lazy_rep_1 - : public Lazy_rep - , private EC -{ - typedef Lazy_rep Base; - - mutable L1 l1_; - - const EC& ec() const { return *this; } - -public: - - void - update_exact() const - { - this->et = new ET(ec()(CGAL::exact(l1_))); - this->at = E2A()(*(this->et)); - // Prune lazy tree - l1_ = L1(); - } - - Lazy_rep_1(const AC& ac, const EC& ec, const L1& l1) - : Lazy_rep(ac(CGAL::approx(l1))), EC(ec), l1_(l1) - { - this->set_depth(CGAL::depth(l1_) + 1); - } - -#ifdef CGAL_LAZY_KERNEL_DEBUG_SHOW_TYPEID -# define CGAL_LAZY_PRINT_TYPEID CGAL::msg(os, level, typeid(AC).name()); -#else // not CGAL_LAZY_KERNEL_DEBUG_SHOW_TYPEID -# define CGAL_LAZY_PRINT_TYPEID -#endif // not CGAL_LAZY_KERNEL_DEBUG_SHOW_TYPEID - -#ifdef CGAL_LAZY_KERNEL_DEBUG - void - print_dag(std::ostream& os, int level) const - { - this->print_at_et(os, level); - if(this->is_lazy()){ - CGAL_LAZY_PRINT_TYPEID - CGAL::msg(os, level, "DAG with one child node:"); - CGAL::print_dag(l1_, os, level+1); - } - } -#endif -}; - -#ifdef CGAL_LAZY_KERNEL_DEBUG -# define CGAL_PRINT_DAG_LN(z, n, d) \ - CGAL::print_dag(l##n, os, level+1); -# define CGAL_LAZY_REP_PRINT_DAG(n) \ - void print_dag(std::ostream& os, int level) const { \ - this->print_at_et(os, level); \ - if(this->is_lazy()){ \ - CGAL_LAZY_PRINT_TYPEID \ - CGAL::msg(os, level, "DAG with " #n " child nodes:"); \ - BOOST_PP_REPEAT(n, CGAL_PRINT_DAG_LN, _) \ - } \ - } -#else // not CGAL_LAZY_KERNEL_DEBUG -# define CGAL_LAZY_REP_PRINT_DAG(n) -#endif // not CGAL_LAZY_KERNEL_DEBUG - -#define CGAL_LAZY_REP(z, n, d) \ - template< typename AT, typename ET, typename AC, typename EC, typename E2A, BOOST_PP_ENUM_PARAMS(n, typename L)> \ -class Lazy_rep_##n :public Lazy_rep< AT, \ - ET, \ - E2A >, \ - private EC \ -{ \ - \ - template \ - friend class Lazy_kernel_base; \ - BOOST_PP_REPEAT(n, CGAL_MLIST, _) \ - const EC& ec() const { return *this; } \ -public: \ - void update_exact() const { \ - this->et = new ET(ec()( BOOST_PP_ENUM(n, CGAL_LEXACT, _) ) ); \ - this->at = E2A()(*(this->et)); \ - BOOST_PP_REPEAT(n, CGAL_PRUNE_TREE, _) \ - } \ - Lazy_rep_##n(const AC& ac, const EC&, BOOST_PP_ENUM(n, CGAL_LARGS, _)) \ - : Lazy_rep(ac( BOOST_PP_ENUM(n, CGAL_LN, CGAL::approx) )), BOOST_PP_ENUM(n, CGAL_LINIT, _) \ - { this->set_depth(max_n( BOOST_PP_ENUM(n, CGAL_LN, CGAL::depth) ) + 1); } \ - \ - CGAL_LAZY_REP_PRINT_DAG(n) \ -}; - -BOOST_PP_REPEAT_FROM_TO(2, 9, CGAL_LAZY_REP, _) - -#undef CGAL_TMAP -#undef CGAL_PRUNE_TREE -#undef CGAL_LINIT -#undef CGAL_LAZY_REP -#undef CGAL_LN -#undef CGAL_MLIST -#undef CGAL_PRINT_DAG_LN -#undef CGAL_LAZY_REP_PRINT_DAG #undef CGAL_LAZY_PRINT_TYPEID template < typename K1, typename K2 > @@ -854,6 +791,8 @@ struct Lazy_construction_bbox template struct Lazy_construction_nt { + Lazy_construction_nt(){} + Lazy_construction_nt(LK const&){} static const bool Protection = true; @@ -878,30 +817,23 @@ struct Lazy_construction_nt { BOOST_PP_REPEAT_FROM_TO(1, 6, CGAL_RESULT_NT, _) -#define CGAL_NT_OPERATOR(z, n, d) \ - template \ - typename cpp11::result_of::type \ - operator()( BOOST_PP_ENUM(n, CGAL_LARGS, _) ) const { \ - BOOST_PP_REPEAT(n, CGAL_TYPEMAP_EC, L) \ - BOOST_PP_REPEAT(n, CGAL_TYPEMAP_AC, L) \ - typedef typename boost::remove_cv< typename boost::remove_reference < \ - typename cpp11::result_of< EC(BOOST_PP_ENUM_PARAMS(n, E)) >::type >::type >::type ET; \ - typedef typename boost::remove_cv< typename boost::remove_reference < \ - typename cpp11::result_of< AC(BOOST_PP_ENUM_PARAMS(n, A)) >::type >::type >::type AT; \ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); \ - Protect_FPU_rounding P; \ - try { \ - return new Lazy_rep_##n, BOOST_PP_ENUM_PARAMS(n, L) >(ac, ec, BOOST_PP_ENUM_PARAMS(n, l)); \ - } catch (Uncertain_conversion_exception&) { \ - CGAL_BRANCH_PROFILER_BRANCH(tmp); \ - Protect_FPU_rounding P2(CGAL_FE_TONEAREST); \ - return new Lazy_rep_0 >(ec( BOOST_PP_ENUM(n, CGAL_LEXACT, _) )); \ - } \ - } \ + template + auto operator()(L const&...l) const -> + Lazy_exact_nt>> + { + typedef std::remove_cv_t> ET; + typedef std::remove_cv_t> AT; + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Protect_FPU_rounding P; + try { + return new Lazy_rep_n, L... >(ac, ec, l...); + } catch (Uncertain_conversion_exception&) { + CGAL_BRANCH_PROFILER_BRANCH(tmp); + Protect_FPU_rounding P2(CGAL_FE_TONEAREST); + return new Lazy_rep_0 >(ec( CGAL::exact(l)... )); + } + } - BOOST_PP_REPEAT_FROM_TO(1, 6, CGAL_NT_OPERATOR, _) - -#undef INTERVAL_OPERATOR #undef CGAL_RESULT_NT }; @@ -1185,8 +1117,8 @@ public: typedef Lazy, std::pair, E2A> Lazy_pair; Lazy_pair lv(new Lazy_rep_2_2(ac, ec, l1, l2)); // lv->approx() is a std::pair; - r1 = R1(Handle_1(new Lazy_rep_1 >, First >, E2A, Lazy_pair>(First >(), First >(), lv))); - r2 = R2(Handle_2(new Lazy_rep_1 >, Second >, E2A, Lazy_pair>(Second >(), Second >(), lv))); + r1 = R1(Handle_1(new Lazy_rep_n >, First >, E2A, Lazy_pair>(First >(), First >(), lv))); + r2 = R2(Handle_2(new Lazy_rep_n >, Second >, E2A, Lazy_pair>(Second >(), Second >(), lv))); } catch (Uncertain_conversion_exception&) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); @@ -1232,7 +1164,7 @@ public: for (unsigned int i = 0; i < lv.approx().size(); i++) { // FIXME : I'm not sure how this work... #define CGAL_Kernel_obj(X) if (object_cast(& (lv.approx()[i]))) { \ - *it++ = make_object(typename LK::X(new Lazy_rep_1, \ + *it++ = make_object(typename LK::X(new Lazy_rep_n, \ Ith, E2A, Lazy_vector> \ (Ith(i), Ith(i), lv))); \ continue; \ @@ -1304,14 +1236,14 @@ public: CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { - Lazy_object lo(new Lazy_rep_1(ac, ec, l1)); + Lazy_object lo(new Lazy_rep_n(ac, ec, l1)); if(lo.approx().is_empty()) return Object(); #define CGAL_Kernel_obj(X) \ if (object_cast(& (lo.approx()))) { \ - typedef Lazy_rep_1< typename AK::X, typename EK::X, Object_cast, Object_cast, E2A, Lazy_object> Lcr; \ + typedef Lazy_rep_n< typename AK::X, typename EK::X, Object_cast, Object_cast, E2A, Lazy_object> Lcr; \ Lcr * lcr = new Lcr(Object_cast(), Object_cast(), lo); \ return make_object(typename LK::X(lcr)); \ } @@ -1337,14 +1269,14 @@ public: CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { - Lazy_object lo(new Lazy_rep_2(ac, ec, l1, l2)); + Lazy_object lo(new Lazy_rep_n(ac, ec, l1, l2)); if(lo.approx().is_empty()) return Object(); #define CGAL_Kernel_obj(X) \ if (object_cast(& (lo.approx()))) { \ - typedef Lazy_rep_1, Object_cast, E2A, Lazy_object> Lcr; \ + typedef Lazy_rep_n, Object_cast, E2A, Lazy_object> Lcr; \ Lcr * lcr = new Lcr(Object_cast(), Object_cast(), lo); \ return make_object(typename LK::X(lcr)); \ } @@ -1360,7 +1292,7 @@ public: std::vector V;\ V.resize(v_ptr->size()); \ for (unsigned int i = 0; i < v_ptr->size(); i++) { \ - V[i] = typename LK::X(new Lazy_rep_1, \ + V[i] = typename LK::X(new Lazy_rep_n, \ Ith_for_intersection, E2A, Lazy_object> \ (Ith_for_intersection(i), Ith_for_intersection(i), lo)); \ } \ @@ -1391,14 +1323,14 @@ CGAL_Kernel_obj(Point_3) CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { - Lazy_object lo(new Lazy_rep_3(ac, ec, l1, l2, l3)); + Lazy_object lo(new Lazy_rep_n(ac, ec, l1, l2, l3)); if(lo.approx().is_empty()) return Object(); #define CGAL_Kernel_obj(X) \ if (object_cast(& (lo.approx()))) { \ - typedef Lazy_rep_1, Object_cast, E2A, Lazy_object> Lcr; \ + typedef Lazy_rep_n, Object_cast, E2A, Lazy_object> Lcr; \ Lcr * lcr = new Lcr(Object_cast(), Object_cast(), lo); \ return make_object(typename LK::X(lcr)); \ } @@ -1469,7 +1401,7 @@ struct Fill_lazy_variant_visitor_2 : boost::static_visitor<> { typedef typename Type_mapper::type EKT; typedef typename Type_mapper::type LKT; - typedef Lazy_rep_1, Variant_cast, typename LK::E2A, Origin> Lcr; + typedef Lazy_rep_n, Variant_cast, typename LK::E2A, Origin> Lcr; Lcr * lcr = new Lcr(Variant_cast(), Variant_cast(), *o); *r = LKT(lcr); @@ -1484,7 +1416,7 @@ struct Fill_lazy_variant_visitor_2 : boost::static_visitor<> { std::vector V; V.resize(t.size()); for (unsigned int i = 0; i < t.size(); i++) { - V[i] = LKT(new Lazy_rep_1, + V[i] = LKT(new Lazy_rep_n, Ith_for_intersection, typename LK::E2A, Origin> (Ith_for_intersection(i), Ith_for_intersection(i), *o)); } @@ -1565,7 +1497,7 @@ struct Lazy_construction_variant { Protect_FPU_rounding P; try { - Lazy lazy(new Lazy_rep_2(AC(), EC(), l1, l2)); + Lazy lazy(new Lazy_rep_n(AC(), EC(), l1, l2)); // the approximate result requires the trait with types from the AK AT approx_v = lazy.approx(); @@ -1614,7 +1546,7 @@ struct Lazy_construction_variant { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { - Lazy lazy(new Lazy_rep_3(AC(), EC(), l1, l2, l3)); + Lazy lazy(new Lazy_rep_n(AC(), EC(), l1, l2, l3)); // the approximate result requires the trait with types from the AK AT approx_v = lazy.approx(); @@ -1681,7 +1613,7 @@ struct Lazy_construction { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); \ Protect_FPU_rounding P; \ try { \ - return result_type( Handle(new Lazy_rep_##n(ac, ec, BOOST_PP_ENUM_PARAMS(n, l)))); \ + return result_type( Handle(new Lazy_rep_n(ac, ec, BOOST_PP_ENUM_PARAMS(n, l)))); \ } catch (Uncertain_conversion_exception&) { \ CGAL_BRANCH_PROFILER_BRANCH(tmp); \ Protect_FPU_rounding P2(CGAL_FE_TONEAREST); \ @@ -1748,7 +1680,7 @@ struct result { \ CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); \ Protect_FPU_rounding P; \ try { \ - return result_type( Handle(new Lazy_rep_##n(ac, ec, BOOST_PP_ENUM_PARAMS(n, l)))); \ + return result_type( Handle(new Lazy_rep_n(ac, ec, BOOST_PP_ENUM_PARAMS(n, l)))); \ } catch (Uncertain_conversion_exception&) { \ CGAL_BRANCH_PROFILER_BRANCH(tmp); \ Protect_FPU_rounding P2(CGAL_FE_TONEAREST); \ diff --git a/Filtered_kernel/include/CGAL/Lazy_kernel.h b/Filtered_kernel/include/CGAL/Lazy_kernel.h index 90e18354df0..1009198e04d 100644 --- a/Filtered_kernel/include/CGAL/Lazy_kernel.h +++ b/Filtered_kernel/include/CGAL/Lazy_kernel.h @@ -330,7 +330,7 @@ public: FT operator()(const Weighted_point_2& p) const { - typedef Lazy_rep_3 LR; - typedef Lazy_rep_3 LR; - typedef Lazy_rep_3 #include #include +#include #include - +// TODO: add static filters somewhere namespace CGAL { -#define CGAL_BASE \ - Cartesian_base_d::Type, Dim> -template -struct Epeck_d_help1 -: CGAL_BASE -{ - CGAL_CONSTEXPR Epeck_d_help1(){} - CGAL_CONSTEXPR Epeck_d_help1(int d):CGAL_BASE(d){} -}; +#define CGAL_KA Cartesian_base_d +#define CGAL_KE Cartesian_base_d::Type, Dim> +template using Epeck_d_help1 = Lazy_cartesian>; +#undef CGAL_KE +#undef CGAL_KA #undef CGAL_BASE #define CGAL_BASE \ Kernel_d_interface< \ diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_base.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_base.h index 632ee0ef9e7..533b953331c 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_base.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_base.h @@ -88,6 +88,7 @@ struct Cartesian_LA_base_d : public Dimension_base ::add::type ::add::type ::add::type + ::add::type Object_list; typedef typeset< Point_cartesian_const_iterator_tag>::type diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h index a9307329fc1..d60b5d896a8 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h @@ -321,6 +321,12 @@ template struct In_flat_power_side_of_power_sphere_raw : private Store } + +// For the lazy kernel +inline CartesianDKernelFunctors::Flat_orientation const& exact(CartesianDKernelFunctors::Flat_orientation const& o){return o;} +inline CartesianDKernelFunctors::Flat_orientation const& approx(CartesianDKernelFunctors::Flat_orientation const& o){return o;} +inline unsigned depth(CartesianDKernelFunctors::Flat_orientation const&){return 0;} + CGAL_KD_DEFAULT_TYPE(Flat_orientation_tag,(CGAL::CartesianDKernelFunctors::Flat_orientation),(),()); CGAL_KD_DEFAULT_FUNCTOR(In_flat_orientation_tag,(CartesianDKernelFunctors::In_flat_orientation),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); CGAL_KD_DEFAULT_FUNCTOR(In_flat_side_of_oriented_sphere_tag,(CartesianDKernelFunctors::In_flat_side_of_oriented_sphere),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index c1cb7ce07e1..f6463dda4dd 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -151,30 +151,33 @@ template struct Kernel_d_interface : public Base_ { CGAL_FUNCTOR_INIT_STORE(Construct_cartesian_const_iterator_d) typedef typename Get_functor >::type CPI; typedef typename Get_functor >::type CVI; - // FIXME: The following sometimes breaks compilation. The typedef below forces instantiation of this, which forces Point_d, which itself (in the wrapper) needs the derived kernel to tell it what the base kernel is, and that's a cycle. The exact circumstances are not clear, g++ and clang++ are ok in both C++03 and C++11, it is only clang in C++11 without CGAL_CXX11 that breaks. For now, rely on result_type. + // FIXME: The following sometimes breaks compilation. The typedef below forces instantiation of this, which forces Point_d, which itself (in the wrapper) needs the derived kernel to tell it what the base kernel is, and that's a cycle. The exact circumstances are not clear, g++ and clang++ are ok in both C++03 and C++11, it is only clang in C++11 without CGAL_CXX11 that breaks. Relying on CPI::result_type is great for Epick_d but not Epeck_d. //typedef typename CGAL::decay::type>::type result_type; - typedef typename CGAL::decay::type result_type; + //typedef typename CGAL::decay::type result_type; + //typedef decltype(std::declval()(std::declval(),Begin_tag{})) result_type; + // HACK + typedef typename Base::Point_cartesian_const_iterator result_type; // Kernel_d requires a common iterator type for points and vectors // TODO: provide this mixed functor in preKernel? //CGAL_static_assertion((boost::is_same::type>::type, result_type>::value)); - CGAL_static_assertion((boost::is_same::type, result_type>::value)); + //CGAL_static_assertion((boost::is_same::type, result_type>::value)); template - result_type operator()(Point_d const&p, Tag_ t)const{ + auto operator()(Point_d const&p, Tag_ t)const{ return CPI(this->kernel())(p,t); } template - result_type operator()(typename First_if_different::Type const&v, Tag_ t)const{ + auto operator()(typename First_if_different::Type const&v, Tag_ t)const{ return CVI(this->kernel())(v,t); } template - result_type operator()(Obj const&o)const{ + auto operator()(Obj const&o)const{ return operator()(o, Begin_tag()); } - result_type operator()(Point_d const&p, int)const{ + auto operator()(Point_d const&p, int)const{ return operator()(p, End_tag()); } - result_type operator()(typename First_if_different::Type const&v, int)const{ + auto operator()(typename First_if_different::Type const&v, int)const{ return operator()(v, End_tag()); } }; diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_object_converter.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_object_converter.h index 9d8c2280297..152b4f47eda 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_object_converter.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_object_converter.h @@ -95,6 +95,18 @@ template struct KO_converter{ } }; +template struct KO_converter{ + typedef typename Get_type::type argument_type; + typedef typename Get_type::type result_type; + template + result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& s) const { + typename Get_functor::type f(k1); + typename Get_functor::type g(k1); + typename Get_functor >::type cib(k2); + return cib(conv(f(s)),conv(g(s))); + } +}; + template struct KO_converter{ typedef typename Get_type::type argument_type; typedef typename Get_type::type result_type; diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h index 4ae80544fcf..1912ce7f214 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace CGAL { @@ -61,6 +62,47 @@ namespace internal { }; } +template +struct Lazy_construction2 { + static const bool Protection = true; + + typedef typename LK::Approximate_kernel AK; + typedef typename LK::Exact_kernel EK; + typedef typename LK::E2A E2A; + typedef typename Get_functor::type AC; + typedef typename Get_functor::type EC; + typedef typename map_result_tag::type result_tag; + typedef typename Get_type::type AT; + typedef typename Get_type::type ET; + typedef typename Get_type::type result_type; + // same as Handle = Lazy< AT, ET, E2A> + + Lazy_construction2(){} + Lazy_construction2(LK const&k):ac(k.approximate_kernel()),ec(k.exact_kernel()){} + CGAL_NO_UNIQUE_ADDRESS AC ac; + CGAL_NO_UNIQUE_ADDRESS EC ec; + + template + std::enable_if_t<(sizeof...(L)>0), result_type> operator()(L const&...l) const { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Protect_FPU_rounding P; + try { + return new Lazy_rep_n(ac, ec, l...); + } catch (Uncertain_conversion_exception&) { + CGAL_BRANCH_PROFILER_BRANCH(tmp); + Protect_FPU_rounding P2(CGAL_FE_TONEAREST); + return new Lazy_rep_0(ec(CGAL::exact(l)...)); + } + } + // FIXME: this forces us to have default constructors for all types, try to make its instantiation lazier + result_type operator()() const + { + return new Lazy_rep_0(); + } + +#undef CGAL_CONSTRUCTION_OPERATOR +}; + template struct Lazy_cartesian_types { @@ -103,20 +145,30 @@ struct Lazy_cartesian_types }; template -struct Lazy_cartesian : Dimension_base, +struct Lazy_cartesian : Lazy_cartesian_types > { - //CGAL_CONSTEXPR Lazy_cartesian(){} - //CGAL_CONSTEXPR Lazy_cartesian(int d):Base_(d){} + CGAL_CONSTEXPR Lazy_cartesian(){} + CGAL_CONSTEXPR Lazy_cartesian(int d):ak(d),ek(d){} //TODO: Do we want to store an AK and an EK? Or just references? //FIXME: references would be better I guess. //TODO: In any case, make sure that we don't end up storing this kernel for //nothing (it is not empty but references empty kernels or something) - AK_ ak; EK_ ek; + CGAL_NO_UNIQUE_ADDRESS AK_ ak; + CGAL_NO_UNIQUE_ADDRESS EK_ ek; AK_ const& approximate_kernel()const{return ak;} EK_ const& exact_kernel()const{return ek;} + int dimension()const{return ak.dimension();} + void set_dimension(int dim){ak.set_dimension(dim);ek.set_dimension(dim);} + + // For compilers that do not handle [[no_unique_address]] + typedef boost::mpl::and_< + internal::Do_not_store_kernel, + internal::Do_not_store_kernel > Do_not_store_kernel; + + typedef typename EK_::Dimension Dimension; // ? typedef Lazy_cartesian Self; typedef Lazy_cartesian_types Base; //typedef typename Default::Get::type Kernel; @@ -124,8 +176,18 @@ struct Lazy_cartesian : Dimension_base, typedef AK_ Approximate_kernel; typedef EK_ Exact_kernel; typedef E2A_ E2A; - typedef Approx_converter C2A; - typedef Exact_converter C2E; + //typedef Approx_converter C2A; + //typedef Exact_converter C2E; + struct C2A { + C2A(){} + C2A(Kernel const&, Approximate_kernel const&){} + templatedecltype(auto)operator()(T const&t)const{return CGAL::approx(t);} + }; + struct C2E { + C2E(){} + C2E(Kernel const&, Exact_kernel const&){} + templatedecltype(auto)operator()(T const&t)const{return CGAL::exact(t);} + }; typedef typename Exact_kernel::Rep_tag Rep_tag; typedef typename Exact_kernel::Kernel_tag Kernel_tag; @@ -151,12 +213,58 @@ struct Lazy_cartesian : Dimension_base, template struct Functor { typedef typename Get_functor::type FA; typedef typename Get_functor::type FE; - typedef Lazy_construction type; + typedef Lazy_construction2 type; + }; + template struct Functor { + typedef typename Get_functor::type FA; + struct type { + FA fa; + type(){} + type(Kernel const&k):fa(k.approximate_kernel()){} + template + int operator()(P const&p)const{return fa(CGAL::approx(p));} + }; + }; + template struct Functor { + typedef typename Get_functor::type FA; + struct type { + FA fa; + type(){} + type(Kernel const&k):fa(k.approximate_kernel()){} + template + int operator()(V const&v)const{return fa(CGAL::approx(v));} + }; + }; + template struct Functor { + // Don't filter that one, as there is no guarantee that the interval + // basis would be in any way related to the exact basis, the most obvious + // difference being the order of the vectors. + // Don't try to be generic until we have more than just this one. + typedef typename Get_functor::type FE; + typedef typename Get_type::type AT; + typedef typename Get_type::type ET; + typedef typename Base::template Type::type V; // Lazy + struct type { + FE fe; + type(){} + type(Kernel const&k):fe(k.exact_kernel()){} + template + void operator()(Iter i, Iter e, Oter o)const{ + fe(CGAL::exact(i), CGAL::exact(e), + boost::make_function_output_iterator( + [&o](ET const&v){ + *o++ = V(new Lazy_rep_0(v)); + } + ) + ); + } + }; }; - //typedef typename Iterator::type Point_cartesian_const_iterator; - //typedef typename Iterator::type Vector_cartesian_const_iterator; + typedef typename Base::template Iterator::type Point_cartesian_const_iterator; + typedef typename Base::template Iterator::type Vector_cartesian_const_iterator; + // This is really specific to point/vector coordinate iterators template struct Construct_iter : private Store_kernel { Construct_iter(){} @@ -169,7 +277,8 @@ struct Lazy_cartesian : Dimension_base, } template result_type operator()(T const& t,End_tag)const{ - return result_type(t,Self().dimension(),this->kernel()); + typedef typename Get_functor::type PD; + return result_type(t,PD(this->kernel().approximate_kernel())(CGAL::approx(t)),this->kernel()); } }; template struct Functor { diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Hyperplane.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Hyperplane.h index 1a32b080bed..21333780d2c 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Hyperplane.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Hyperplane.h @@ -33,6 +33,7 @@ template class Hyperplane { FT_ s_; public: + Hyperplane(){} Hyperplane(Vector_ const&v, FT_ const&s): v_(v), s_(s) {} // TODO: Add a piecewise constructor? diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h index ff82aec26a5..b6c12e11c83 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h @@ -30,6 +30,7 @@ template class Sphere { FT_ r2_; public: + Sphere(){} Sphere(Point_ const&p, FT_ const&r2): c_(p), r2_(r2) {} // TODO: Add a piecewise constructor? diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index ed0c7d71191..8bb92abdcfe 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -31,6 +31,7 @@ template class Weighted_point { FT_ w_; public: + Weighted_point(){} Weighted_point(Point_ const&p, FT_ const&w): c_(p), w_(w) {} // TODO: Add a piecewise constructor? diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Vector/array.h b/NewKernel_d/include/CGAL/NewKernel_d/Vector/array.h index 6f9aa5bb3f2..f600134e0e4 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Vector/array.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Vector/array.h @@ -162,6 +162,8 @@ BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ ) } }; +// Do not try to instantiate the above +template struct Array_vector {}; } #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Vector/mix.h b/NewKernel_d/include/CGAL/NewKernel_d/Vector/mix.h index de8aac8845a..2e7145f6003 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Vector/mix.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Vector/mix.h @@ -33,6 +33,7 @@ struct Mix_vector }; }; +// FIXME: shouldn't we dispatch based on Max_dim_ instead? template struct Mix_vector, Max_dim_> : Static_::template Rebind_dimension, Max_dim_>::Other diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h index 4d5147dbffc..a97529bf6e7 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h @@ -145,9 +145,8 @@ struct Cartesian_wrap : public Base_ B b; type(){} type(Self const&k):b(k){} - typedef typename B::result_type result_type; #ifdef CGAL_CXX11 - template result_type operator()(U&&...u)const{ + template decltype(auto) operator()(U&&...u)const{ return b(internal::Forward_rep()(u)...); } #else diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Point_d.h b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Point_d.h index a4013b983d3..643828d9733 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Point_d.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Point_d.h @@ -156,6 +156,13 @@ public: return PDBase()(rep()); } + friend auto operator==(Point_d const&p, Point_d const&q) { + typedef typename Get_functor::type EPBase; + return EPBase()(p.rep(), q.rep()); + } + + friend auto operator!=(Point_d const&p, Point_d const&q) { return !(p==q); } + /* Direction_d direction() const { diff --git a/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h index 1e7a34b3e1e..94bd1e2ab76 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h @@ -462,7 +462,7 @@ template struct Linear_base : private Store_kernel { typedef typename R::LA::Dynamic_matrix Matrix; template - result_type operator()(Iter f, Iter e, Oter&o)const{ + result_type operator()(Iter f, Iter e, Oter o)const{ typename Get_functor::type c(this->kernel()); typename Get_functor::type vd(this->kernel()); typename Get_functor >::type cv(this->kernel()); diff --git a/NewKernel_d/include/CGAL/iterator_from_indices.h b/NewKernel_d/include/CGAL/iterator_from_indices.h index 22e772a5031..895a5f47916 100644 --- a/NewKernel_d/include/CGAL/iterator_from_indices.h +++ b/NewKernel_d/include/CGAL/iterator_from_indices.h @@ -50,7 +50,7 @@ class Iterator_from_indices typedef std::ptrdiff_t index_t; Container_* cont; index_t index; - Coord_access ca; + CGAL_NO_UNIQUE_ADDRESS Coord_access ca; void increment(){ ++index; } void decrement(){ --index; } void advance(std::ptrdiff_t n){ index+=n; } @@ -66,6 +66,7 @@ class Iterator_from_indices return ca(*cont,index); } public: + Iterator_from_indices(){} Iterator_from_indices(Container_& cont_,std::size_t n) : cont(&cont_), index(n) {} template diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 30aa5f79882..503450d96d7 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -11,6 +11,7 @@ int main() //#define BOOST_RESULT_OF_USE_DECLTYPE 1 #include +#include #include #include @@ -121,7 +122,6 @@ void test2(){ typedef typename K1::Oriented_side_d OS; typedef typename K1::Orthogonal_vector_d OV; typedef typename K1::Point_dimension_d PD; - typedef typename K1::Point_of_sphere_d PS; typedef typename K1::Point_to_vector_d PV; typedef typename K1::Vector_to_point_d VP; typedef typename K1::Barycentric_coordinates_d BC; @@ -190,7 +190,6 @@ void test2(){ OS os Kinit(oriented_side_d_object); OV ov Kinit(orthogonal_vector_d_object); PD pd Kinit(point_dimension_d_object); - PS ps Kinit(point_of_sphere_d_object); PV pv Kinit(point_to_vector_d_object); VP vp Kinit(vector_to_point_d_object); BC bc Kinit(barycentric_coordinates_d_object); @@ -356,6 +355,8 @@ void test2(){ #endif P z0=cp( 0+2,5-3); P z1=cp(-5+2,0-3); + assert(abs(sd(z0,z1)-50)<.0001); + assert(ed(z0,z0) && !ed(z0,z1)); P z2=cp( 3+2,4-3); P tabz[]={z0,z1,z2}; Sp sp = csp(tabz+0,tabz+3); @@ -368,6 +369,8 @@ void test2(){ assert(abs(sp.squared_radius()-25)<.0001); #if 1 // Fails for an exact kernel + typedef typename K1::Point_of_sphere_d PS; + PS ps Kinit(point_of_sphere_d_object); P psp0=ps(sp,0); P psp1=ps(sp,1); P psp2=ps(sp,2); @@ -423,12 +426,15 @@ template struct Construct_point3_helper { Construct_point3_helper(CP const& x) : cp(x) {} template typename CP::result_type operator()(T1 const&t1, T2 const&t2, T3 const&t3)const{ - double tab[]={(double)t1,(double)t2,(double)t3}; + //double tab[]={(double)t1,(double)t2,(double)t3}; + // The lazy kernel stores iterators, not a vector, so the array must stay alive until update_exact()! For the tests I am keeping the memory leak for now, it is more convenient. + double*tab=new double[3]{(double)t1,(double)t2,(double)t3}; return cp(tab+0,tab+3); } template typename CP::result_type operator()(T1 const&t1, T2 const&t2, T3 const&t3, T4 const&t4)const{ - double tab[]={(double)t1,(double)t2,(double)t3}; + // Same discussion as above + double*tab=new double[3]{(double)t1,(double)t2,(double)t3}; return cp(tab+0,tab+3,t4); } }; @@ -690,6 +696,9 @@ int main(){ test2(); test3(); test3(); + //test2>>(); + //test3>>(); + //test3>(); } #endif