// 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; version 2.1 of the License. // See the file LICENSE.LGPL distributed with CGAL. // // 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$ // // // Author(s) : Andreas Fabri, Sylvain Pion #ifndef CGAL_LAZY_H #define CGAL_LAZY_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CGAL_HAS_THREADS # include #endif namespace CGAL { namespace internal { BOOST_MPL_HAS_XXX_TRAIT_DEF(AT) BOOST_MPL_HAS_XXX_TRAIT_DEF(ET) } template class Lazy; template class Lazy_exact_nt; template inline const AT& approx(const Lazy& l) { return l.approx(); } // Where is this one (non-const) needed ? Is it ? template inline AT& approx(Lazy& l) { return l.approx(); } template inline const ET& exact(const Lazy& l) { return l.exact(); } template inline unsigned depth(const Lazy& l) { return l.depth(); } /* #define CGAL_LAZY_FORWARD(T) \ inline T const & approx(T const& d) { return d; } \ inline T const & exact (T const& d) { return d; } \ inline unsigned depth (T const& ) { return 0; } CGAL_LAZY_FORWARD(double) CGAL_LAZY_FORWARD(float) CGAL_LAZY_FORWARD(int) CGAL_LAZY_FORWARD(unsigned) 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) */ template inline T const & approx(T const& d) { return d; }; template inline T const & exact (T const& d) { return d; }; template inline unsigned depth (T const& ) { return 0; }; #ifdef CGAL_LAZY_KERNEL_DEBUG template void print_at(std::ostream& os, const T& at) { os << at; } template void print_at(std::ostream& os, const std::vector& at) { os << "std::vector"; } template <> void print_at(std::ostream& os, const Object& o) { os << "Object"; } template void print_at(std::ostream& os, const std::pair & at) { os << "[ " << at.first << " | " << at.second << " ]" << std::endl ; } template inline void print_dag(const Lazy& l, std::ostream& os, int level = 0) { l.print_dag(os, level); } inline void print_dag(double d, std::ostream& os, int level) { for(int i = 0; i < level; i++) os << " "; os << d << std::endl; } inline void msg(std::ostream& os, int level, char* s) { for(int i = 0; i < level; i++) os << " "; os << s << std::endl; } inline void print_dag(const Null_vector& nv, std::ostream& os, int level) { for(int i = 0; i < level; i++) os << " "; os << "Null_vector" << std::endl; } inline void print_dag(const Origin& nv, std::ostream& os, int level) { for(int i = 0; i < level; i++) os << " "; os << "Origin" << std::endl; } #endif struct Depth_base { #ifdef CGAL_PROFILE unsigned depth_; Depth_base() { set_depth(0); } unsigned depth() const { return depth_; } void set_depth(unsigned i) { depth_ = i; CGAL_HISTOGRAM_PROFILER(std::string("[Lazy_kernel DAG depths]"), i); //(unsigned) ::log2(double(i))); } #else unsigned depth() const { return 0; } void set_depth(unsigned) {} #endif }; // Abstract base class for lazy numbers and lazy objects template class Lazy_rep : public Rep, public Depth_base { Lazy_rep (const Lazy_rep&); // cannot be copied. public: typedef AT_ AT; mutable AT at; mutable ET *et; Lazy_rep () : at(), et(NULL) {} Lazy_rep (const AT& a) : at(a), et(NULL) {} Lazy_rep (const AT& a, const ET& e) : at(a), et(new ET(e)) {} const AT& approx() const { return at; } AT& approx() { return at; } const ET & exact() const { if (et==NULL) update_exact(); return *et; } ET & exact() { if (et==NULL) update_exact(); return *et; } #ifdef CGAL_LAZY_KERNEL_DEBUG void print_at_et(std::ostream& os, int level) const { for(int i = 0; i < level; i++){ os << " "; } os << "Approximation: "; print_at(os, at); os << std::endl; if(! is_lazy()){ for(int i = 0; i < level; i++){ os << " "; } os << "Exact: "; print_at(os, *et); os << std::endl; } } virtual void print_dag(std::ostream& os, int level) const {} #endif bool is_lazy() const { return et == NULL; } virtual void update_exact() const = 0; virtual ~Lazy_rep() { delete et; } }; //____________________________________________________________ // The rep for the leaf node // FIXME TODO : Factorize all the Lazy_rep_[0-8] !!! template class Lazy_rep_0 : public Lazy_rep { typedef Lazy_rep Base; public: void update_exact() const { this->et = new ET(); } Lazy_rep_0() : Lazy_rep() {} Lazy_rep_0(const AT& a, const ET& e) : Lazy_rep(a, e) {} Lazy_rep_0(const AT& a, void*) : Lazy_rep(a) {} Lazy_rep_0(const ET& e) : Lazy_rep(E2A()(e), e) {} void print_dag(std::ostream& os, int level) const { this->print_at_et(os, level); } }; //____________________________________________________________ template class Lazy_rep_1 : public Lazy_rep::type, typename decay::type, E2A> , private EC { typedef typename decay::type AT; typedef typename decay::type ET; 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 void print_dag(std::ostream& os, int level) const { this->print_at_et(os, level); if(this->is_lazy()){ CGAL::msg(os, level, "DAG with one child node:"); CGAL::print_dag(l1_, os, level+1); } } #endif }; //____________________________________________________________ template class Lazy_rep_2 : public Lazy_rep::type, typename decay::type, E2A> , private EC { typedef typename decay::type AT; typedef typename decay::type ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(ec()(CGAL::exact(l1_), CGAL::exact(l2_))); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); } Lazy_rep_2(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2) : Lazy_rep(ac(CGAL::approx(l1), CGAL::approx(l2))), l1_(l1), l2_(l2) { this->set_depth(max_n(CGAL::depth(l1_), CGAL::depth(l2_)) + 1); } #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::msg(os, level, "DAG with two child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); } } #endif }; //____________________________________________________________ template class Lazy_rep_3 : public Lazy_rep::type, typename decay::type, E2A> , private EC { typedef typename decay::type AT; typedef typename decay::type ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; mutable L3 l3_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(ec()(CGAL::exact(l1_), CGAL::exact(l2_), CGAL::exact(l3_))); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); l3_ = L3(); } Lazy_rep_3(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2, const L3& l3) : Lazy_rep(ac(CGAL::approx(l1), CGAL::approx(l2), CGAL::approx(l3))), l1_(l1), l2_(l2), l3_(l3) { this->set_depth(max_n(CGAL::depth(l1_), CGAL::depth(l2_), CGAL::depth(l3_)) + 1); } #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::msg(os, level, "DAG with three child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); CGAL::print_dag(l3_, os, level+1); } } #endif }; //____________________________________________________________ template class Lazy_rep_4 : public Lazy_rep , private EC { typedef typename AC::result_type AT; typedef typename EC::result_type ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; mutable L3 l3_; mutable L4 l4_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(ec()(CGAL::exact(l1_), CGAL::exact(l2_), CGAL::exact(l3_), CGAL::exact(l4_))); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); l3_ = L3(); l4_ = L4(); } Lazy_rep_4(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2, const L3& l3, const L4& l4) : Lazy_rep(ac(CGAL::approx(l1), CGAL::approx(l2), CGAL::approx(l3), CGAL::approx(l4))), l1_(l1), l2_(l2), l3_(l3), l4_(l4) { this->set_depth(max_n(CGAL::depth(l1_), CGAL::depth(l2_), CGAL::depth(l3_), CGAL::depth(l4_)) + 1); } #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::msg(os, level, "DAG with four child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); CGAL::print_dag(l3_, os, level+1); CGAL::print_dag(l4_, os, level+1); } } #endif }; //____________________________________________________________ template class Lazy_rep_5 : public Lazy_rep , private EC { typedef typename AC::result_type AT; typedef typename EC::result_type ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; mutable L3 l3_; mutable L4 l4_; mutable L5 l5_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(ec()(CGAL::exact(l1_), CGAL::exact(l2_), CGAL::exact(l3_), CGAL::exact(l4_), CGAL::exact(l5_))); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); l3_ = L3(); l4_ = L4(); l5_ = L5(); } Lazy_rep_5(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2, const L3& l3, const L4& l4, const L5& l5) : Lazy_rep(ac(CGAL::approx(l1), CGAL::approx(l2), CGAL::approx(l3), CGAL::approx(l4), CGAL::approx(l5))), l1_(l1), l2_(l2), l3_(l3), l4_(l4), l5_(l5) { this->set_depth(max_n(CGAL::depth(l1_), CGAL::depth(l2_), CGAL::depth(l3_), CGAL::depth(l4_), CGAL::depth(l5_)) + 1); } #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::msg(os, level, "DAG with five child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); CGAL::print_dag(l3_, os, level+1); CGAL::print_dag(l4_, os, level+1); CGAL::print_dag(l5_, os, level+1); } } #endif }; template class Lazy_rep_6 : public Lazy_rep , private EC { typedef typename AC::result_type AT; typedef typename EC::result_type ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; mutable L3 l3_; mutable L4 l4_; mutable L5 l5_; mutable L6 l6_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(ec()(CGAL::exact(l1_), CGAL::exact(l2_), CGAL::exact(l3_), CGAL::exact(l4_), CGAL::exact(l5_), CGAL::exact(l6_))); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); l3_ = L3(); l4_ = L4(); l5_ = L5(); l6_ = L6(); } Lazy_rep_6(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2, const L3& l3, const L4& l4, const L5& l5, const L6& l6) : Lazy_rep(ac(CGAL::approx(l1), CGAL::approx(l2), CGAL::approx(l3), CGAL::approx(l4), CGAL::approx(l5), CGAL::approx(l6))), l1_(l1), l2_(l2), l3_(l3), l4_(l4), l5_(l5), l6_(l6) { this->set_depth(max_n(CGAL::depth(l1_), CGAL::depth(l2_), CGAL::depth(l3_), CGAL::depth(l4_), CGAL::depth(l5_), CGAL::depth(l6_)) + 1); } #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::msg(os, level, "DAG with 6 child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); CGAL::print_dag(l3_, os, level+1); CGAL::print_dag(l4_, os, level+1); CGAL::print_dag(l5_, os, level+1); CGAL::print_dag(l6_, os, level+1); } } #endif }; template class Lazy_rep_7 : public Lazy_rep , private EC { typedef typename AC::result_type AT; typedef typename EC::result_type ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; mutable L3 l3_; mutable L4 l4_; mutable L5 l5_; mutable L6 l6_; mutable L7 l7_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(ec()(CGAL::exact(l1_), CGAL::exact(l2_), CGAL::exact(l3_), CGAL::exact(l4_), CGAL::exact(l5_), CGAL::exact(l6_), CGAL::exact(l7_))); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); l3_ = L3(); l4_ = L4(); l5_ = L5(); l6_ = L6(); l7_ = L7(); } Lazy_rep_7(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2, const L3& l3, const L4& l4, const L5& l5, const L6& l6, const L7& l7) : Lazy_rep(ac(CGAL::approx(l1), CGAL::approx(l2), CGAL::approx(l3), CGAL::approx(l4), CGAL::approx(l5), CGAL::approx(l6), CGAL::approx(l7))), l1_(l1), l2_(l2), l3_(l3), l4_(l4), l5_(l5), l6_(l6), l7_(l7) { this->set_depth(max_n(CGAL::depth(l1_), CGAL::depth(l2_), CGAL::depth(l3_), CGAL::depth(l4_), CGAL::depth(l5_), CGAL::depth(l6_), CGAL::depth(l7_)) + 1); } #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::msg(os, level, "DAG with 7 child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); CGAL::print_dag(l3_, os, level+1); CGAL::print_dag(l4_, os, level+1); CGAL::print_dag(l5_, os, level+1); CGAL::print_dag(l6_, os, level+1); CGAL::print_dag(l7_, os, level+1); } } #endif }; template class Lazy_rep_8 : public Lazy_rep , private EC { typedef typename AC::result_type AT; typedef typename EC::result_type ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; mutable L3 l3_; mutable L4 l4_; mutable L5 l5_; mutable L6 l6_; mutable L7 l7_; mutable L8 l8_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(ec()(CGAL::exact(l1_), CGAL::exact(l2_), CGAL::exact(l3_), CGAL::exact(l4_), CGAL::exact(l5_), CGAL::exact(l6_), CGAL::exact(l7_), CGAL::exact(l8_))); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); l3_ = L3(); l4_ = L4(); l5_ = L5(); l6_ = L6(); l7_ = L7(); l8_ = L8(); } Lazy_rep_8(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2, const L3& l3, const L4& l4, const L5& l5, const L6& l6, const L7& l7, const L8& l8) : Lazy_rep(ac(CGAL::approx(l1), CGAL::approx(l2), CGAL::approx(l3), CGAL::approx(l4), CGAL::approx(l5), CGAL::approx(l6), CGAL::approx(l7), CGAL::approx(l8))), l1_(l1), l2_(l2), l3_(l3), l4_(l4), l5_(l5), l6_(l6), l7_(l7), l8_(l8) { this->set_depth(max_n(CGAL::depth(l1_), CGAL::depth(l2_), CGAL::depth(l3_), CGAL::depth(l4_), CGAL::depth(l5_), CGAL::depth(l6_), CGAL::depth(l7_), CGAL::depth(l8_)) + 1); } #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::msg(os, level, "DAG with 8 child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); CGAL::print_dag(l3_, os, level+1); CGAL::print_dag(l4_, os, level+1); CGAL::print_dag(l5_, os, level+1); CGAL::print_dag(l6_, os, level+1); CGAL::print_dag(l7_, os, level+1); CGAL::print_dag(l8_, os, level+1); } } #endif }; template < typename K1, typename K2 > struct Approx_converter { typedef Approx_converter Self; typedef K1 Source_kernel; typedef K2 Target_kernel; //typedef Converter Number_type_converter; Approx_converter(){} Approx_converter(K1 const&,K2 const&){} //TODO: check that it is normal that we never need k1 or k2 here template struct result_; template struct result_ { typedef typename T::AT const& type; }; template struct result_ { typedef transforming_iterator type; }; template struct result; template struct result : result_::value,is_iterator::value>{}; template struct result{typedef Null_vector type;}; template struct result{typedef Bbox_2 type;}; template struct result{typedef Bbox_3 type;}; template < typename T > const typename T::AT& operator()(const T&t) const { return t.approx(); } template transforming_iterator,It>::type> operator()(const It& i) const { return make_transforming_iterator(i,*this); } const Null_vector& operator()(const Null_vector& n) const { return n; } const Bbox_2& operator()(const Bbox_2& b) const { return b; } const Bbox_3& operator()(const Bbox_3& b) const { return b; } }; template < typename K1, typename K2 > struct Exact_converter { typedef Exact_converter Self; typedef K1 Source_kernel; typedef K2 Target_kernel; //typedef Converter Number_type_converter; Exact_converter(){} Exact_converter(K1 const&,K2 const&){} //TODO: check that it is normal that we never need k1 or k2 here template struct result_; template struct result_ { typedef typename T::ET const& type; }; template struct result_ { typedef transforming_iterator type; }; template struct result; template struct result : result_::value,is_iterator::value>{}; template struct result{typedef Null_vector type;}; template struct result{typedef Bbox_2 type;}; template struct result{typedef Bbox_3 type;}; template < typename T > const typename T::ET& operator()(const T&t) const { return t.exact(); } template transforming_iterator,It>::type> operator()(const It& i) const { return make_transforming_iterator(i,*this); } const Null_vector& operator()(const Null_vector& n) const { return n; } const Bbox_2& operator()(const Bbox_2& b) const { return b; } const Bbox_3& operator()(const Bbox_3& b) const { return b; } }; //____________________________________________________________ template class Lazy_rep_with_vector_1 : public Lazy_rep, std::vector, E2A> , private EC { typedef std::vector AT; typedef std::vector ET; typedef Lazy_rep Base; mutable L1 l1_; const EC& ec() const { return *this; } public: void update_exact() const { // TODO : This looks really unfinished... std::vector vec; this->et = new ET(); //this->et->reserve(this->at.size()); ec()(CGAL::exact(l1_), std::back_inserter(*(this->et))); if(this->et==NULL) E2A()(*(this->et)); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); } Lazy_rep_with_vector_1(const AC& ac, const EC& /*ec*/, const L1& l1) : l1_(l1) { ac(CGAL::approx(l1), std::back_inserter(this->at)); } #ifdef CGAL_LAZY_KERNEL_DEBUG void print_dag(std::ostream& os, int level) const { this->print_at_et(os, level); os << "A Lazy_rep_with_vector_1 of size " << this->at.size() << std::endl; if(this->is_lazy()){ CGAL::msg(os, level, "DAG with one child node:"); CGAL::print_dag(l1_, os, level+1); } } #endif }; template class Lazy_rep_with_vector_2 : public Lazy_rep, std::vector, E2A> , private EC { typedef std::vector AT; typedef std::vector ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(); this->et->reserve(this->at.size()); ec()(CGAL::exact(l1_), CGAL::exact(l2_), std::back_inserter(*(this->et))); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); } Lazy_rep_with_vector_2(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2) : l1_(l1), l2_(l2) { ac(CGAL::approx(l1), CGAL::approx(l2), std::back_inserter(this->at)); } #ifdef CGAL_LAZY_KERNEL_DEBUG void print_dag(std::ostream& os, int level) const { this->print_at_et(os, level); os << "A Lazy_rep_with_vector_2 of size " << this->at.size() << std::endl; if(this->is_lazy()){ CGAL::msg(os, level, "DAG with two child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); } } #endif }; template class Lazy_rep_2_1 : public Lazy_rep , private EC { typedef typename R1::AT AT; typedef typename R1::ET ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(); ec()(CGAL::exact(l1_), CGAL::exact(l2_), *(this->et)); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); } Lazy_rep_2_1(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2) : Lazy_rep(), l1_(l1), l2_(l2) { ac(CGAL::approx(l1), CGAL::approx(l2), this->at); } #ifdef CGAL_LAZY_KERNEL_DEBUG void print_dag(std::ostream& os, int level) const { this->print_at_et(os, level); os << "A Lazy_rep_2_1" << std::endl; if(this->is_lazy()){ CGAL::msg(os, level, "DAG with two child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); } } #endif }; //____________________________________________________________________________________ // The following rep class stores two non-const reference parameters of type R1 and R2 template class Lazy_rep_2_2 : public Lazy_rep, std::pair, E2A> , private EC { typedef std::pair AT; typedef std::pair ET; typedef Lazy_rep Base; mutable L1 l1_; mutable L2 l2_; const EC& ec() const { return *this; } public: void update_exact() const { this->et = new ET(); ec()(CGAL::exact(l1_), CGAL::exact(l2_), this->et->first, this->et->second ); this->at = E2A()(*(this->et)); // Prune lazy tree l1_ = L1(); l2_ = L2(); } Lazy_rep_2_2(const AC& ac, const EC& /*ec*/, const L1& l1, const L2& l2) : Lazy_rep(), l1_(l1), l2_(l2) { ac(CGAL::approx(l1), CGAL::approx(l2), this->at.first, this->at.second); } #ifdef CGAL_LAZY_KERNEL_DEBUG void print_dag(std::ostream& os, int level) const { this->print_at_et(os, level); os << "A Lazy_rep_2_2" << std::endl; if(this->is_lazy()){ CGAL::msg(os, level, "DAG with two child nodes:"); CGAL::print_dag(l1_, os, level+1); CGAL::print_dag(l2_, os, level+1); } } #endif }; //____________________________________________________________ // The handle class template class Lazy : public Handle { public : typedef Lazy Self; typedef Lazy_rep Self_rep; typedef AT_ AT; // undocumented typedef ET_ ET; // undocumented typedef AT Approximate_type; typedef ET Exact_type; /* typedef Self Rep; const Rep& rep() const { return *this; } Rep& rep() { return *this; } */ Lazy() : Handle(zero()) {} // Before Lazy::zero() used Boost.Thread, the definition of Lazy() was: // Lazy() // #ifndef CGAL_HAS_THREAD // : Handle(zero()) {} // #else // { // PTR = new Lazy_rep_0(); // } // #endif Lazy(Self_rep *r) { PTR = r; } Lazy(const ET& e) { PTR = new Lazy_rep_0(e); } const AT& approx() const { return ptr()->approx(); } const ET& exact() const { return ptr()->exact(); } AT& approx() { return ptr()->approx(); } ET& exact() { return ptr()->exact(); } unsigned depth() const { return ptr()->depth(); } void print_dag(std::ostream& os, int level) const { ptr()->print_dag(os, level); } private: // We have a static variable for optimizing the default constructor, // which is in particular heavily used for pruning DAGs. static const Self & zero() { #ifdef CGAL_HAS_THREADS static boost::thread_specific_ptr z; if (z.get() == NULL) { z.reset(new Self(new Lazy_rep_0())); } return * z.get(); #else static const Self z = new Lazy_rep_0(); return z; #endif } Self_rep * ptr() const { return (Self_rep*) PTR; } }; // The magic functor for Construct_bbox_[2,3], as there is no Lazy template struct Lazy_construction_bbox { static const bool Protection = true; typedef typename LK::Approximate_kernel AK; typedef typename LK::Exact_kernel EK; typedef typename AC::result_type result_type; AC ac; EC ec; template result_type operator()(const L1& l1) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); // Protection is outside the try block as VC8 has the CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG Protect_FPU_rounding P; try { return ac(CGAL::approx(l1)); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return ec(CGAL::exact(l1)); } } }; template struct Lazy_construction_nt { static const bool Protection = true; typedef typename LK::Approximate_kernel AK; typedef typename LK::Exact_kernel EK; typedef typename LK::E2A E2A; typedef typename decay::type AT; typedef typename decay::type ET; typedef Lazy_exact_nt result_type; AC ac; EC ec; Lazy_construction_nt(){} Lazy_construction_nt(LK const&k):ac(k.approximate_kernel()),ec(k.exact_kernel()){} template result_type operator()(const L1& l1) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { return new Lazy_rep_1, L1>(ac, ec, l1); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return new Lazy_rep_0 >(ec(CGAL::exact(l1))); } } template result_type operator()(const L1& l1, const L2& l2) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { return new Lazy_rep_2, L1,L2>(ac, ec, l1,l2); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return new Lazy_rep_0 >(ec(CGAL::exact(l1), CGAL::exact(l2))); } } template result_type operator()(const L1& l1, const L2& l2, const L3& l3) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { return new Lazy_rep_3, L1,L2,L3>(ac, ec, l1,l2,l3); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return new Lazy_rep_0 >(ec(CGAL::exact(l1), CGAL::exact(l2), CGAL::exact(l3))); } } template result_type operator()(const L1& l1, const L2& l2, const L3& l3, const L4& l4) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { return new Lazy_rep_4, L1,L2,L3,L4>(ac, ec, l1,l2,l3,l4); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return new Lazy_rep_0 >(ec(CGAL::exact(l1), CGAL::exact(l2), CGAL::exact(l3), CGAL::exact(l4))); } } template result_type operator()(const L1& l1, const L2& l2, const L3& l3, const L4& l4, const L5& l5) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { return new Lazy_rep_5, L1,L2,L3,L4,L5>(ac, ec, l1,l2,l3,l4,l5); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return new Lazy_rep_0 >(ec(CGAL::exact(l1), CGAL::exact(l2), CGAL::exact(l3), CGAL::exact(l4), CGAL::exact(l5))); } } }; template Object make_lazy(const Object& eto) { typedef typename LK::Approximate_kernel AK; typedef typename LK::Exact_kernel EK; typedef typename LK::E2A E2A; if (eto.is_empty()) return Object(); #define CGAL_Kernel_obj(X) \ if (const typename EK::X* ptr = object_cast(&eto)) \ return make_object(typename LK::X(new Lazy_rep_0(*ptr))); #include std::cerr << "object_cast inside Lazy_construction_rep::operator() failed. It needs more else if's (#2)" << std::endl; std::cerr << "dynamic type of the Object : " << eto.type().name() << std::endl; return Object(); } // This functor selects the i'th element in a vector of Object's // and casts it to what is in the Object template struct Ith { typedef T2 result_type; // We keep a Sign member object // for future utilisation, in case // we have pairs of 2 T2 objects e.g. // for a numeric_point vector returned // from a construction of a possible // lazy algebraic kernel int i; Sign sgn; Ith(int i_) : i(i_) {sgn=NEGATIVE;} Ith(int i_, bool b_) : i(i_) { sgn= (b_) ? POSITIVE : ZERO;} const T2& operator()(const std::vector& v) const { if(sgn==NEGATIVE) return *object_cast(&v[i]); typedef std::pair Pair_type_1; typedef std::pair > Pair_type_2; if(const Pair_type_1 *p1 = object_cast(&v[i])) return p1->first; else if(const Pair_type_2 *p2 = object_cast(&v[i])) return p2->first; CGAL_error_msg( " Unexpected encapsulated type "); } }; template struct Lazy_cartesian_const_iterator_2 { typedef typename LK::Approximate_kernel AK; typedef typename LK::Exact_kernel EK; typedef typename LK::Cartesian_const_iterator_2 result_type; AC ac; EC ec; public: template < typename L1> result_type operator()(const L1& l1) const { return result_type(&l1); } template < typename L1> result_type operator()(const L1& l1, int i) const { return result_type(&l1,i); } }; template struct Lazy_cartesian_const_iterator_3 { typedef typename LK::Approximate_kernel AK; typedef typename LK::Exact_kernel EK; typedef typename LK::Cartesian_const_iterator_3 result_type; AC ac; EC ec; public: template < typename L1> result_type operator()(const L1& l1) const { return result_type(&l1); } template < typename L1> result_type operator()(const L1& l1, int i) const { return result_type(&l1,i); } }; // This is the magic functor for functors that write their result in a reference argument // In a first version we assume that the references are of type Lazy, // and that the result type is void template struct Lazy_functor_2_1 { static const bool Protection = true; typedef void result_type; AC ac; EC ec; public: template void operator()(const L1& l1, const L2& l2, R1& r1) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { // we suppose that R1 is a Lazy r1 = R1(new Lazy_rep_2_1(ac, ec, l1, l2)); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); typename R1::ET et; ec(CGAL::exact(l1), CGAL::exact(l2), et); r1 = R1(new Lazy_rep_0(et)); } } }; template struct First { typedef typename T::first_type result_type; const typename T::first_type& operator()(const T& p) const { return p.first; } }; template struct Second { typedef typename T::second_type result_type; const typename T::second_type& operator()(const T& p) const { return p.second; } }; // This is the magic functor for functors that write their result in a reference argument // In a first version we assume that the references are of type Lazy, // and that the result type is void //template template struct Lazy_functor_2_2 { static const bool Protection = true; typedef void result_type; typedef typename LK::Approximate_kernel AK; typedef typename LK::Exact_kernel EK; typedef typename EK::FT EFT; typedef typename LK::E2A E2A; AC ac; EC ec; public: template void operator()(const L1& l1, const L2& l2, R1& r1, R2& r2) const { typedef Lazy Handle_1; typedef Lazy Handle_2; CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { typedef Lazy, std::pair, EFT, 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))); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); typename R1::ET et1, et2; ec(CGAL::exact(l1), CGAL::exact(l2), et1, et2); r1 = R1(Handle_1(new Lazy_rep_0(et1))); r2 = R2(Handle_2(new Lazy_rep_0(et2))); } } }; // This is the magic functor for functors that write their result as Objects into an output iterator template struct Lazy_intersect_with_iterators { static const bool Protection = true; typedef typename LK::Approximate_kernel AK; typedef typename LK::Exact_kernel EK; typedef typename EK::FT EFT; typedef typename LK::E2A E2A; typedef void result_type; typedef Lazy Lazy_object; typedef Lazy, std::vector, EFT, E2A> Lazy_vector; AC ac; EC ec; public: // In the example we intersect two Lazys // and write into a back_inserter(list,Lazy]) >) template OutputIterator operator()(const L1& l1, const L2& l2, OutputIterator it) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Protect_FPU_rounding P; try { Lazy_vector lv(new Lazy_rep_with_vector_2(ac, ec, l1, l2)); // lv.approx() is a std::vector // that is, when we get here we have constructed all approximate results 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, \ Ith, E2A, Lazy_vector> \ (Ith(i), Ith(i), lv))); \ continue; \ } #include std::cerr << "we need more casts" << std::endl; } } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); // TODO: Instead of using a vector, write an iterator adapter Protect_FPU_rounding P2(CGAL_FE_TONEAREST); std::vector exact_objects; ec(CGAL::exact(l1), CGAL::exact(l2), std::back_inserter(exact_objects)); for (std::vector::const_iterator oit = exact_objects.begin(); oit != exact_objects.end(); ++oit){ *it++ = make_lazy(*oit); } } return it; } }; template struct Object_cast { typedef T result_type; const T& operator()(const Object& o) const { return *object_cast(&o); } }; // The following functor returns an Object with a Lazy inside // As the nested kernels return Objects of AK::Something and EK::Something // we have to unwrap them from the Object, and wrap them in a Lazy // // TODO: write operators for other than two arguments. For the current kernel we only need two for Intersect_2 template struct Lazy_construction_object { static const bool Protection = true; typedef typename LK::Approximate_kernel AK; typedef typename LK::Exact_kernel EK; typedef typename EK::FT EFT; typedef typename LK::E2A E2A; typedef typename AC::result_type AT; typedef typename EC::result_type ET; typedef Object result_type; typedef Lazy Lazy_object; AC ac; EC ec; public: template result_type operator()(const L1& l1) const { 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)); 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; \ Lcr * lcr = new Lcr(Object_cast(), Object_cast(), lo); \ return make_object(typename LK::X(lcr)); \ } #include std::cerr << "object_cast inside Lazy_construction_rep::operator() failed. It needs more else if's (#1)" << std::endl; std::cerr << "dynamic type of the Object : " << lo.approx().type().name() << std::endl; } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); ET eto = ec(CGAL::exact(l1)); return make_lazy(eto); } return Object(); } template result_type operator()(const L1& l1, const L2& l2) const { 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)); 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; \ Lcr * lcr = new Lcr(Object_cast(), Object_cast(), lo); \ return make_object(typename LK::X(lcr)); \ } #include std::cerr << "object_cast inside Lazy_construction_rep::operator() failed. It needs more else if's (#1)" << std::endl; std::cerr << "dynamic type of the Object : " << lo.approx().type().name() << std::endl; } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); ET eto = ec(CGAL::exact(l1), CGAL::exact(l2)); return make_lazy(eto); } return Object(); } }; //____________________________________________________________ // The magic functor that has Lazy as result type template struct Lazy_construction { static const bool Protection = true; typedef typename LK::Approximate_kernel AK; typedef typename LK::Exact_kernel EK; typedef typename EK::FT EFT; typedef typename Default::Get::type E2A; typedef typename decay::type AT; typedef typename decay::type ET; typedef Lazy Handle; //typedef typename Type_mapper::type result_type; typedef Handle result_type; AC ac; EC ec; Lazy_construction(){} Lazy_construction(LK const&k):ac(k.approximate_kernel()),ec(k.exact_kernel()){} public: result_type operator()() const { return result_type( Handle(new Lazy_rep_0()) ); } template result_type operator()(const L1& l1) const { 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_1(ac, ec, l1)) ); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return result_type( Handle(new Lazy_rep_0(ec(CGAL::exact(l1)))) ); } } template result_type operator()(const L1& l1, const L2& l2) const { 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_2(ac, ec, l1, l2)) ); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return result_type( Handle(new Lazy_rep_0(ec(CGAL::exact(l1), CGAL::exact(l2)))) ); } } template result_type operator()(const L1& l1, const L2& l2, const L3& l3) const { 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_3(ac, ec, l1, l2, l3)) ); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return result_type( Handle(new Lazy_rep_0(ec(CGAL::exact(l1), CGAL::exact(l2), CGAL::exact(l3)))) ); } } template result_type operator()(const L1& l1, const L2& l2, const L3& l3, const L4& l4) const { 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_4(ac, ec, l1, l2, l3, l4)) ); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return result_type( Handle(new Lazy_rep_0(ec(CGAL::exact(l1), CGAL::exact(l2), CGAL::exact(l3), CGAL::exact(l4)))) ); } } template result_type operator()(const L1& l1, const L2& l2, const L3& l3, const L4& l4, const L5& l5) const { 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_5(ac, ec, l1, l2, l3, l4, l5)) ); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return result_type( Handle(new Lazy_rep_0(ec(CGAL::exact(l1), CGAL::exact(l2), CGAL::exact(l3), CGAL::exact(l4), CGAL::exact(l5)))) ); } } template result_type operator()(const L1& l1, const L2& l2, const L3& l3, const L4& l4, const L5& l5, const L6& l6) const { 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_6(ac, ec, l1, l2, l3, l4, l5, l6)) ); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return result_type( Handle(new Lazy_rep_0(ec(CGAL::exact(l1), CGAL::exact(l2), CGAL::exact(l3), CGAL::exact(l4), CGAL::exact(l5), CGAL::exact(l6)))) ); } } template result_type operator()(const L1& l1, const L2& l2, const L3& l3, const L4& l4, const L5& l5, const L6& l6, const L7& l7) const { 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_7(ac, ec, l1, l2, l3, l4, l5, l6, l7)) ); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return result_type( Handle(new Lazy_rep_0(ec(CGAL::exact(l1), CGAL::exact(l2), CGAL::exact(l3), CGAL::exact(l4), CGAL::exact(l5), CGAL::exact(l6), CGAL::exact(l7)))) ); } } template result_type operator()(const L1& l1, const L2& l2, const L3& l3, const L4& l4, const L5& l5, const L6& l6, const L7& l7, const L8& l8) const { 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_8(ac, ec, l1, l2, l3, l4, l5, l6, l7, l8)) ); } catch (Uncertain_conversion_exception) { CGAL_BRANCH_PROFILER_BRANCH(tmp); Protect_FPU_rounding P2(CGAL_FE_TONEAREST); return result_type( Handle(new Lazy_rep_0(ec(CGAL::exact(l1), CGAL::exact(l2), CGAL::exact(l3), CGAL::exact(l4), CGAL::exact(l5), CGAL::exact(l6), CGAL::exact(l7), CGAL::exact(l8)))) ); } } }; } //namespace CGAL #endif // CGAL_LAZY_H