// Copyright (c) 1999-2007 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Number_types/include/CGAL/Lazy_exact_nt.h $ // $Id: Lazy_exact_nt.h c1f2fde 2020-04-11T12:12:27+02:00 Marc Glisse // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Sylvain Pion #ifndef CGAL_LAZY_EXACT_NT_H #define CGAL_LAZY_EXACT_NT_H #include #include #include // for Root_of functor #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CGAL_int(T) typename First_if_different::Type #define CGAL_double(T) typename First_if_different::Type #define CGAL_To_interval(T) To_interval /* * This file contains the definition of the number type Lazy_exact_nt, * where ET is an exact number type (must provide the exact operations needed). * * Lazy_exact_nt provides a DAG-based lazy evaluation, like LEDA's real, * Core's Expr, LEA's lazy rationals... * * The values are first approximated using Interval_base. * The exactness is provided when needed by ET. * * Lazy_exact_nt is just a handle to the abstract base class * Lazy_exact_nt_rep which has pure virtual methods .approx() and .exact(). * From this class derives one class per operation, with one constructor. * * The DAG is managed by : * - Handle and Rep. * - virtual functions to denote the various operators (instead of an enum). * * Other packages with vaguely similar design : APU, MetaCGAL, LOOK. */ /* * TODO : * - Generalize it for constructions at the kernel level. * - Add mixed operations with ET too ? * - Interval refinement functionnality ? * - Separate the handle and the representation(s) in 2 files (?) * maybe not a good idea, better if everything related to one operation is * close together. * - Add a CT template parameter ? * - Add a string constant to provide an expression string (a la MetaCGAL) ? * // virtual ostream operator<<() const = 0; // or string, like Core ? * - Have a template-expression (?) thing that evaluates a temporary element, * and allocates stuff in memory only when really needs to convert to the * NT. (cf gmp++, and maybe other things, Blitz++, Synaps...) */ /* * Interface of the rep classes: * - .approx() returns Interval_nt<> (assumes rounding=nearest). * [ only called from the handle, and declared in the base ] * - .exact() returns ET, if not already done, computes recursively * * - .rafine_approx() ?? */ namespace CGAL { template class Lazy_exact_nt; #ifdef CGAL_LAZY_KERNEL_DEBUG template inline void print_dag(const Lazy_exact_nt& l, std::ostream& os, int level=0) { l.print_dag(os, level); } #endif // Abstract base representation class for lazy numbers template struct Lazy_exact_nt_rep : public Lazy_exact_nt::Self_rep { typedef typename Lazy_exact_nt::Self_rep Base; Lazy_exact_nt_rep (const Interval_nt & i) : Base(i) {} #ifdef CGAL_LAZY_KERNEL_DEBUG void print_dag(std::ostream& os, int level) const { this->print_at_et(os, level); } #endif }; // int constant template struct Lazy_exact_Int_Cst : public Lazy_exact_nt_rep { Lazy_exact_Int_Cst (int i) : Lazy_exact_nt_rep(double(i)) {} void update_exact() const { this->et = new ET((int)this->approx().inf()); } }; // double constant template struct Lazy_exact_Cst : public Lazy_exact_nt_rep { Lazy_exact_Cst (X x) : Lazy_exact_nt_rep(x), cste(x) {} void update_exact() const { this->et = new ET(cste); } private: X cste; }; // Exact constant template struct Lazy_exact_Ex_Cst : public Lazy_exact_nt_rep { Lazy_exact_Ex_Cst (const ET & e) : Lazy_exact_nt_rep(CGAL_NTS to_interval(e)) { this->et = new ET(e); } Lazy_exact_Ex_Cst (ET&& e) : Lazy_exact_nt_rep(CGAL_NTS to_interval(e)) { this->et = new ET(std::move(e)); } void update_exact() const { CGAL_error(); } }; // Construction from a Lazy_exact_nt (which keeps the lazyness). template class Lazy_lazy_exact_Cst : public Lazy_exact_nt_rep { mutable Lazy_exact_nt l; public: Lazy_lazy_exact_Cst (const Lazy_exact_nt &x) : Lazy_exact_nt_rep(x.approx()), l(x) { this->set_depth(l.depth() + 1); } void update_exact() const { this->et = new ET(l.exact()); this->at = l.approx(); prune_dag(); } void prune_dag() const { l = Lazy_exact_nt(); } }; // Unary operations: abs, sqrt, square. // Binary operations: +, -, *, /, min, max. // Base unary operation template struct Lazy_exact_unary : public Lazy_exact_nt_rep { mutable Lazy_exact_nt op1; Lazy_exact_unary (const Interval_nt &i, const Lazy_exact_nt &a) : Lazy_exact_nt_rep(i), op1(a) { this->set_depth(op1.depth() + 1); } void prune_dag() const { op1 = Lazy_exact_nt(); } #ifdef CGAL_LAZY_KERNEL_DEBUG void print_dag(std::ostream& os, int level) const { this->print_at_et(os, level); if(this->is_lazy()){ msg(os, level, "Unary number operator:"); CGAL::print_dag(op1, os, level+1); } } #endif }; // Base binary operation template struct Lazy_exact_binary : public Lazy_exact_nt_rep { mutable Lazy_exact_nt op1; mutable Lazy_exact_nt op2; Lazy_exact_binary (const Interval_nt &i, const Lazy_exact_nt &a, const Lazy_exact_nt &b) : Lazy_exact_nt_rep(i), op1(a), op2(b) { this->set_depth((std::max)(op1.depth(), op2.depth()) + 1); } void prune_dag() const { op1 = Lazy_exact_nt(); op2 = Lazy_exact_nt(); } #ifdef CGAL_LAZY_KERNEL_DEBUG void print_dag(std::ostream& os, int level) const { this->print_at_et(os, level); if(this->is_lazy()){ msg(os, level, "Binary number operator:"); CGAL::print_dag(op1, os, level+1); CGAL::print_dag(op2, os, level+1); } } #endif }; // Here we could use a template class for all operations (STL provides // function objects plus, minus, multiplies, divides...). But it would require // a template template parameter, and GCC 2.95 seems to crash easily with them. // Macro for unary operations #define CGAL_LAZY_UNARY_OP(OP, NAME) \ template \ struct NAME : public Lazy_exact_unary \ { \ typedef typename Lazy_exact_unary::AT::Protector P; \ NAME (const Lazy_exact_nt &a) \ : Lazy_exact_unary((P(), OP(a.approx())), a) {} \ \ void update_exact() const \ { \ this->et = new ET(OP(this->op1.exact())); \ if (!this->approx().is_point()) \ this->at = CGAL_NTS to_interval(*(this->et)); \ this->prune_dag(); \ } \ }; CGAL_LAZY_UNARY_OP(opposite, Lazy_exact_Opp) CGAL_LAZY_UNARY_OP(CGAL_NTS abs, Lazy_exact_Abs) CGAL_LAZY_UNARY_OP(CGAL_NTS square, Lazy_exact_Square) CGAL_LAZY_UNARY_OP(CGAL_NTS sqrt, Lazy_exact_Sqrt) // A macro for +, -, * and / #define CGAL_LAZY_BINARY_OP(OP, NAME) \ template \ struct NAME : public Lazy_exact_binary \ { \ typedef typename Lazy_exact_binary::AT::Protector P; \ NAME (const Lazy_exact_nt &a, const Lazy_exact_nt &b) \ : Lazy_exact_binary((P(), a.approx() OP b.approx()), a, b) {} \ \ void update_exact() const \ { \ this->et = new ET(this->op1.exact() OP this->op2.exact()); \ if (!this->approx().is_point()) \ this->at = CGAL_NTS to_interval(*(this->et)); \ this->prune_dag(); \ } \ }; CGAL_LAZY_BINARY_OP(+, Lazy_exact_Add) CGAL_LAZY_BINARY_OP(-, Lazy_exact_Sub) CGAL_LAZY_BINARY_OP(*, Lazy_exact_Mul) CGAL_LAZY_BINARY_OP(/, Lazy_exact_Div) // Minimum template struct Lazy_exact_Min : public Lazy_exact_binary { Lazy_exact_Min (const Lazy_exact_nt &a, const Lazy_exact_nt &b) : Lazy_exact_binary((CGAL::min)(a.approx(), b.approx()), a, b) {} void update_exact() const { this->et = new ET((CGAL::min)(this->op1.exact(), this->op2.exact())); if (!this->approx().is_point()) this->at = CGAL_NTS to_interval(*(this->et)); this->prune_dag(); } }; // Maximum template struct Lazy_exact_Max : public Lazy_exact_binary { Lazy_exact_Max (const Lazy_exact_nt &a, const Lazy_exact_nt &b) : Lazy_exact_binary((CGAL::max)(a.approx(), b.approx()), a, b) {} void update_exact() const { this->et = new ET((CGAL::max)(this->op1.exact(), this->op2.exact())); if (!this->approx().is_point()) this->at = CGAL_NTS to_interval(*(this->et)); this->prune_dag(); } }; // The real number type, handle class template class Lazy_exact_nt : public Lazy, ET_, To_interval > , boost::ordered_euclidian_ring_operators2< Lazy_exact_nt, int > , boost::ordered_euclidian_ring_operators2< Lazy_exact_nt, double > { public: typedef Lazy_exact_nt Self; typedef Lazy, ET_, To_interval > Base; typedef typename Base::Self_rep Self_rep; typedef typename Base::ET ET; // undocumented typedef typename Base::AT AT; // undocumented typedef typename Base::Exact_type Exact_type; typedef typename Base::Approximate_type Approximate_type; public : Lazy_exact_nt () {} Lazy_exact_nt (Self_rep *r) : Base(r) {} // Also check that ET and AT are constructible from T? template Lazy_exact_nt (T i, typename boost::enable_if, std::is_enum >, boost::mpl::not_ > >,void*>::type=0) : Base(new Lazy_exact_Cst(i)) {} Lazy_exact_nt (const ET & e) : Base(new Lazy_exact_Ex_Cst(e)){} Lazy_exact_nt (ET&& e) : Base(new Lazy_exact_Ex_Cst(std::move(e))){} template Lazy_exact_nt (const Lazy_exact_nt &x, typename boost::enable_if,int>::type=0) : Base(new Lazy_lazy_exact_Cst(x)){} template explicit Lazy_exact_nt (const Lazy_exact_nt &x, typename boost::disable_if,int>::type=0) : Base(new Lazy_lazy_exact_Cst(x)){} friend void swap(Lazy_exact_nt& a, Lazy_exact_nt& b) noexcept { swap(static_cast(a), static_cast(b)); } Self operator+ () const { return *this; } Self operator- () const { return new Lazy_exact_Opp(*this); } Self & operator+=(const Self& b) { return *this = new Lazy_exact_Add(*this, b); } Self & operator-=(const Self& b) { return *this = new Lazy_exact_Sub(*this, b); } Self & operator*=(const Self& b) { return *this = new Lazy_exact_Mul(*this, b); } Self & operator/=(const Self& b) { CGAL_precondition(b != 0); return *this = new Lazy_exact_Div(*this, b); } // Mixed operators. (could be optimized ?) Self & operator+=(CGAL_int(ET) b) { return *this = new Lazy_exact_Add(*this, b); } Self & operator-=(CGAL_int(ET) b) { return *this = new Lazy_exact_Sub(*this, b); } Self & operator*=(CGAL_int(ET) b) { return *this = new Lazy_exact_Mul(*this, b); } Self & operator/=(CGAL_int(ET) b) { CGAL_precondition(b != 0); return *this = new Lazy_exact_Div(*this, b); } Self & operator+=(CGAL_double(ET) b) { return *this = new Lazy_exact_Add(*this, b); } Self & operator-=(CGAL_double(ET) b) { return *this = new Lazy_exact_Sub(*this, b); } Self & operator*=(CGAL_double(ET) b) { return *this = new Lazy_exact_Mul(*this, b); } Self & operator/=(CGAL_double(ET) b) { CGAL_precondition(b != 0); return *this = new Lazy_exact_Div(*this, b); } // Mixed comparisons with int. friend bool operator<(const Lazy_exact_nt& a, int b) { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Uncertain res = a.approx() < b; if (is_certain(res)) return res; CGAL_BRANCH_PROFILER_BRANCH(tmp); return a.exact() < b; } friend bool operator>(const Lazy_exact_nt& a, int b) { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Uncertain res = b < a.approx(); if (is_certain(res)) return get_certain(res); CGAL_BRANCH_PROFILER_BRANCH(tmp); return b < a.exact(); } friend bool operator==(const Lazy_exact_nt& a, int b) { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Uncertain res = b == a.approx(); if (is_certain(res)) return get_certain(res); CGAL_BRANCH_PROFILER_BRANCH(tmp); return b == a.exact(); } // Mixed comparisons with double. friend bool operator<(const Lazy_exact_nt& a, double b) { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Uncertain res = a.approx() < b; if (is_certain(res)) return res; CGAL_BRANCH_PROFILER_BRANCH(tmp); return a.exact() < b; } friend bool operator>(const Lazy_exact_nt& a, double b) { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Uncertain res = b < a.approx(); if (is_certain(res)) return res; CGAL_BRANCH_PROFILER_BRANCH(tmp); return b < a.exact(); } friend bool operator==(const Lazy_exact_nt& a, double b) { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Uncertain res = b == a.approx(); if (is_certain(res)) return res; CGAL_BRANCH_PROFILER_BRANCH(tmp); return b == a.exact(); } // % kills filtering Self & operator%=(const Self& b) { CGAL_precondition(b != 0); ET res = this->exact(); res %= b.exact(); return *this = Lazy_exact_nt(res); } Self & operator%=(int b) { CGAL_precondition(b != 0); ET res = this->exact(); res %= b; return *this = Lazy_exact_nt(res); } Interval_nt interval() const { const Interval_nt& i = this->approx(); return Interval_nt(i.inf(), i.sup()); } Interval_nt_advanced approx_adv() const { return this->ptr()->approx(); } private: static double & relative_precision_of_to_double_internal() { CGAL_STATIC_THREAD_LOCAL_VARIABLE(double, relative_precision_of_to_double, 0.00001); return relative_precision_of_to_double; } public: static const double & get_relative_precision_of_to_double() { return relative_precision_of_to_double_internal(); } static void set_relative_precision_of_to_double(double d) { CGAL_assertion((0 < d) & (d < 1)); relative_precision_of_to_double_internal() = d; } bool identical(const Self& b) const { return ::CGAL::identical( static_cast(*this), static_cast(b)); } template < typename T > bool identical(const T&) const { return false; } }; template bool operator<(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); if (a.identical(b)) return false; Uncertain res = a.approx() < b.approx(); if (is_certain(res)) return get_certain(res); CGAL_BRANCH_PROFILER_BRANCH(tmp); return a.exact() < b.exact(); } template bool operator==(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); if (a.identical(b)) return true; Uncertain res = a.approx() == b.approx(); if (is_certain(res)) return get_certain(res); CGAL_BRANCH_PROFILER_BRANCH(tmp); return a.exact() == b.exact(); } template inline bool operator>(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { return b < a; } template inline bool operator>=(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { return ! (a < b); } template inline bool operator<=(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { return b >= a; } template inline bool operator!=(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { return ! (a == b); } template inline Lazy_exact_nt operator%(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); CGAL_precondition(b != 0); return Lazy_exact_nt(a) %= b; } template Lazy_exact_nt< typename Coercion_traits::Type > operator+(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); return new Lazy_exact_Add::Type, ET1, ET2>(a, b); } template Lazy_exact_nt< typename Coercion_traits::Type > operator-(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); return new Lazy_exact_Sub::Type, ET1, ET2>(a, b); } template Lazy_exact_nt< typename Coercion_traits::Type > operator*(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); return new Lazy_exact_Mul::Type, ET1, ET2>(a, b); } template Lazy_exact_nt< typename Coercion_traits::Type > operator/(const Lazy_exact_nt& a, const Lazy_exact_nt& b) { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); CGAL_precondition(b != 0); return new Lazy_exact_Div::Type, ET1, ET2>(a, b); } // // Algebraic structure traits // namespace INTERN_LAZY_EXACT_NT { template< class NT, class Functor > struct Simplify_selector { struct Simplify : public CGAL::cpp98::unary_function { void operator()( NT& ) const { // TODO: In the old implementation the Simplify-functor was the default // (which does nothing). But this cannot be the correct way!? } }; }; template< class NT > struct Simplify_selector< NT, Null_functor > { typedef Null_functor Simplify; }; template< class NT, class Functor > struct Unit_part_selector { struct Unit_part : public CGAL::cpp98::unary_function { NT operator()( const NT& x ) const { return NT( CGAL_NTS unit_part( x.exact() ) ); } }; }; template< class NT > struct Unit_part_selector< NT, Null_functor > { typedef Null_functor Unit_part; }; template< class NT, class Functor > struct Is_zero_selector { struct Is_zero : public CGAL::cpp98::unary_function { bool operator()( const NT& x ) const { return CGAL_NTS is_zero( x.exact() ); } }; }; template< class NT > struct Is_zero_selector< NT, Null_functor > { typedef Null_functor Is_zero; }; template< class NT, class Functor > struct Is_one_selector { struct Is_one : public CGAL::cpp98::unary_function { bool operator()( const NT& x ) const { return CGAL_NTS is_one( x.exact() ); } }; }; template< class NT > struct Is_one_selector< NT, Null_functor > { typedef Null_functor Is_one; }; template< class NT, class Functor > struct Square_selector { struct Square : public CGAL::cpp98::unary_function { NT operator()( const NT& x ) const { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); return new Lazy_exact_Square(x); } }; }; template< class NT > struct Square_selector< NT, Null_functor > { typedef Null_functor Square; }; template< class NT, class Functor > struct Integral_division_selector { struct Integral_division : public CGAL::cpp98::binary_function { NT operator()( const NT& x, const NT& y ) const { return NT( CGAL_NTS integral_division( x.exact(), y.exact() ) ); } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( NT ) }; }; template< class NT > struct Integral_division_selector< NT, Null_functor > { typedef Null_functor Integral_division; }; template< class NT, class Functor > struct Is_square_selector { struct Is_square : public CGAL::cpp98::binary_function { bool operator()( const NT& x, NT& y ) const { typename NT::ET y_et; bool result = CGAL_NTS is_square( x.exact(), y_et ); y = NT(y_et); return result; } bool operator()( const NT& x) const { typename NT::ET y_et; return CGAL_NTS is_square( x.exact(), y_et ); } }; }; template< class NT > struct Is_square_selector< NT, Null_functor > { typedef Null_functor Is_square; }; template struct Sqrt_selector{ struct Sqrt : public CGAL::cpp98::unary_function { NT operator ()(const NT& x) const { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); CGAL_precondition(x >= 0); return new Lazy_exact_Sqrt(x); } }; }; template struct Sqrt_selector { typedef Null_functor Sqrt; }; template< class NT, class Functor > struct Kth_root_selector { struct Kth_root : public CGAL::cpp98::binary_function { NT operator()( int k, const NT& x ) const { return NT( CGAL_NTS kth_root( k, x.exact() ) ); } }; }; template< class NT > struct Kth_root_selector< NT, Null_functor > { typedef Null_functor Kth_root; }; template< class NT, class Functor > struct Root_of_selector { private: struct Cast{ typedef typename NT::ET result_type; result_type operator()(const NT& lazy_exact) const { return lazy_exact.exact(); } }; public: struct Root_of { // typedef typename Functor::Boundary Boundary; typedef NT result_type; template< class Input_iterator > NT operator()( int k, Input_iterator begin, Input_iterator end ) const { Cast cast; return NT( typename Algebraic_structure_traits:: Root_of()( k, ::boost::make_transform_iterator( begin, cast ), ::boost::make_transform_iterator( end, cast ) ) ); } }; }; template< class NT > struct Root_of_selector< NT, Null_functor > { typedef Null_functor Root_of; }; template< class NT, class Functor > struct Gcd_selector { struct Gcd : public CGAL::cpp98::binary_function { NT operator()( const NT& x, const NT& y ) const { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); return NT( CGAL_NTS gcd( x.exact(), y.exact() ) ); } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( NT ) }; }; template< class NT > struct Gcd_selector< NT, Null_functor > { typedef Null_functor Gcd; }; template< class NT, class Functor > struct Div_selector { struct Div : public CGAL::cpp98::binary_function { NT operator()( const NT& x, const NT& y ) const { return NT( CGAL_NTS div( x.exact(), y.exact() ) ); } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( NT ) }; }; template< class NT > struct Div_selector< NT, Null_functor > { typedef Null_functor Div; }; template< class NT, class Functor > struct Inverse_selector { struct Inverse { typedef NT result_type; NT operator()( const NT& x ) const { return NT( 1 ) / x ; } }; }; template< class NT > struct Inverse_selector< NT, Null_functor > { typedef Null_functor Inverse; }; template< class NT, class Functor > struct Mod_selector { struct Mod : public CGAL::cpp98::binary_function { NT operator()( const NT& x, const NT& y ) const { return NT( CGAL_NTS mod( x.exact(), y.exact() ) ); } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR( NT ) }; }; template< class NT > struct Mod_selector< NT, Null_functor > { typedef Null_functor Mod; }; template< class NT, class Functor > struct Div_mod_selector { struct Div_mod { typedef void result_type; typedef NT first_argument_type; typedef NT second_argument_type; typedef NT& third_argument_type; typedef NT& fourth_argument_type; void operator()( const NT& x, const NT& y, NT& q, NT& r ) const { typename NT::ET q_et; typename NT::ET r_et; CGAL_NTS div_mod( x.exact(), y.exact(), q_et, r_et ); q = NT( q_et ); r = NT( r_et ); } template< class NT1, class NT2 > void operator()( const NT1& x, const NT2& y, NT& q, NT& r ) const { CGAL_static_assertion((::boost::is_same< typename Coercion_traits< NT1, NT2 >::Type, NT >::value)); typename Coercion_traits< NT1, NT2 >::Cast cast; operator()( cast(x), cast(y), q, r ); } }; }; template< class NT > struct Div_mod_selector< NT, Null_functor >{ typedef Null_functor Div_mod; }; } // namespace INTERN_LAZY_EXACT_NT template class Algebraic_structure_traits< Lazy_exact_nt > :public Algebraic_structure_traits_base < Lazy_exact_nt, typename Algebraic_structure_traits::Algebraic_category > { private: typedef Algebraic_structure_traits AST_ET; typedef typename AST_ET::Algebraic_category ET_as_tag; public: typedef typename AST_ET::Is_exact Is_exact; typedef typename AST_ET::Is_numerical_sensitive Is_numerical_sensitive; typedef typename INTERN_LAZY_EXACT_NT::Simplify_selector , typename AST_ET::Simplify > ::Simplify Simplify; typedef typename INTERN_LAZY_EXACT_NT::Unit_part_selector , typename AST_ET::Unit_part > ::Unit_part Unit_part; typedef typename INTERN_LAZY_EXACT_NT::Is_zero_selector , typename AST_ET::Is_zero > ::Is_zero Is_zero; typedef typename INTERN_LAZY_EXACT_NT::Is_one_selector , typename AST_ET::Is_one > ::Is_one Is_one; typedef typename INTERN_LAZY_EXACT_NT::Square_selector , typename AST_ET::Square > ::Square Square; typedef typename INTERN_LAZY_EXACT_NT::Integral_division_selector , typename AST_ET::Integral_division> ::Integral_division Integral_division; typedef typename INTERN_LAZY_EXACT_NT::Is_square_selector , typename AST_ET::Is_square > ::Is_square Is_square; typedef typename INTERN_LAZY_EXACT_NT::Sqrt_selector , typename AST_ET::Sqrt> ::Sqrt Sqrt; typedef typename INTERN_LAZY_EXACT_NT::Kth_root_selector , typename AST_ET::Kth_root > ::Kth_root Kth_root; typedef typename INTERN_LAZY_EXACT_NT::Root_of_selector , typename AST_ET::Root_of > ::Root_of Root_of; typedef typename INTERN_LAZY_EXACT_NT::Gcd_selector , typename AST_ET::Gcd > ::Gcd Gcd; typedef typename INTERN_LAZY_EXACT_NT::Div_selector , typename AST_ET::Div > ::Div Div; typedef typename INTERN_LAZY_EXACT_NT::Mod_selector , typename AST_ET::Mod > ::Mod Mod; typedef typename INTERN_LAZY_EXACT_NT::Div_mod_selector , typename AST_ET::Div_mod > ::Div_mod Div_mod; typedef typename INTERN_LAZY_EXACT_NT::Inverse_selector , typename AST_ET::Inverse > ::Inverse Inverse; }; // // Real embeddalbe traits // template < typename ET > class Real_embeddable_traits< Lazy_exact_nt > : public INTERN_RET::Real_embeddable_traits_base< Lazy_exact_nt , CGAL::Tag_true > { // Every type ET of Lazy_exact_nt has to be real embeddable. CGAL_static_assertion((::boost::is_same< typename Real_embeddable_traits< ET > ::Is_real_embeddable, Tag_true >::value)); public: typedef Lazy_exact_nt Type; class Abs : public CGAL::cpp98::unary_function< Type, Type > { public: Type operator()( const Type& a ) const { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); return new Lazy_exact_Abs(a); } }; class Sgn : public CGAL::cpp98::unary_function< Type, ::CGAL::Sign > { public: ::CGAL::Sign operator()( const Type& a ) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); Uncertain< ::CGAL::Sign> res = CGAL_NTS sign(a.approx()); if (is_certain(res)) return get_certain(res); CGAL_BRANCH_PROFILER_BRANCH(tmp); return CGAL_NTS sign(a.exact()); } }; class Compare : public CGAL::cpp98::binary_function< Type, Type, Comparison_result > { public: Comparison_result operator()( const Type& a, const Type& b ) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); if (a.identical(b)) return EQUAL; Uncertain res = CGAL_NTS compare(a.approx(), b.approx()); if (is_certain(res)) return get_certain(res); CGAL_BRANCH_PROFILER_BRANCH(tmp); return CGAL_NTS compare(a.exact(), b.exact()); } CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT( Type, Comparison_result ) }; class To_double : public CGAL::cpp98::unary_function< Type, double > { public: double operator()( const Type& a ) const { CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); const Interval_nt& app = a.approx(); double r; if (fit_in_double(app, r)) return r; // If it's precise enough, then OK. if (has_smaller_relative_precision(app, Lazy_exact_nt::get_relative_precision_of_to_double())) return CGAL_NTS to_double(app); CGAL_BRANCH_PROFILER_BRANCH(tmp); // Otherwise we trigger exact computation first, // which will refine the approximation. a.exact(); return CGAL_NTS to_double(a.approx()); } }; class To_interval : public CGAL::cpp98::unary_function< Type, std::pair< double, double > > { public: std::pair operator()( const Type& a ) const { CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); return a.approx().pair(); } }; class Is_finite : public CGAL::cpp98::unary_function< Type, bool > { public: bool operator()( const Type& x ) const { return CGAL_NTS is_finite(x.approx()) || CGAL_NTS is_finite(x.exact()); } }; }; template class Lazy_exact_nt_coercion_traits_base { public: typedef Tag_false Are_explicit_interoperable; typedef Tag_false Are_implicit_interoperable; //typedef Null_type Type typedef Null_functor Cast; }; template class Lazy_exact_nt_coercion_traits_base < Lazy_exact_nt, Lazy_exact_nt, Tag_true > { typedef Coercion_traits CT; typedef Lazy_exact_nt A; typedef Lazy_exact_nt B; public: typedef Lazy_exact_nt Type; typedef typename CT::Are_implicit_interoperable Are_explicit_interoperable; typedef typename CT::Are_implicit_interoperable Are_implicit_interoperable; class Cast{ private: template Type cast(const T& x) const{ return Type(x); } Type cast(const Type& x) const{ return x; } public: typedef Type result_type; Type operator()(const A& x) const { return cast(x);} Type operator()(const B& x) const { return cast(x);} }; }; CGAL_DEFINE_COERCION_TRAITS_FOR_SELF_TEM(Lazy_exact_nt, class ET) CGAL_DEFINE_COERCION_TRAITS_FROM_TO_TEM(ET,Lazy_exact_nt,class ET) template struct Coercion_traits< Lazy_exact_nt, Lazy_exact_nt > :public Lazy_exact_nt_coercion_traits_base , Lazy_exact_nt, typename Coercion_traits::Are_implicit_interoperable>{}; #define CGAL_COERCION_TRAITS_LAZY_EXACT(NTX) \ template \ struct Coercion_traits< NTX, Lazy_exact_nt >{ \ private: \ typedef Coercion_traits CT; \ typedef Lazy_exact_nt NT; \ public: \ typedef typename CT::Are_explicit_interoperable \ Are_explicit_interoperable; \ typedef typename CT::Are_implicit_interoperable \ Are_implicit_interoperable; \ private: \ static const bool interoperable \ =boost::is_same< Are_implicit_interoperable, Tag_false>::value; \ public: \ typedef typename boost::mpl::if_c \ ::type Type; \ typedef typename boost::mpl::if_c >::type Cast; \ }; \ \ template \ struct Coercion_traits< Lazy_exact_nt, NTX > \ :public Coercion_traits >{}; \ CGAL_COERCION_TRAITS_LAZY_EXACT(int) CGAL_COERCION_TRAITS_LAZY_EXACT(short) CGAL_COERCION_TRAITS_LAZY_EXACT(double) CGAL_COERCION_TRAITS_LAZY_EXACT(float) #undef CGAL_COERCION_TRAITS_LAZY_EXACT namespace INTERN_LAZY_EXACT_NT { template < typename NT, typename TAG > class Fraction_traits_base; template < class ET > class Fraction_traits_base , CGAL::Tag_false> : public Fraction_traits { public: typedef Lazy_exact_nt Type; }; template < class ET > class Fraction_traits_base , CGAL::Tag_true>{ typedef Fraction_traits ETT; typedef typename ETT::Numerator_type ET_numerator; typedef typename ETT::Denominator_type ET_denominator; public: typedef Lazy_exact_nt Type; typedef Tag_true Is_fraction; typedef Lazy_exact_nt Numerator_type; typedef Lazy_exact_nt Denominator_type; struct Common_factor : CGAL::cpp98::binary_function{ Denominator_type operator()(const Denominator_type& a, const Denominator_type& b) const { typename ETT::Common_factor common_factor; return Denominator_type(common_factor(a.exact(),b.exact())); } }; struct Compose : CGAL::cpp98::binary_function{ Type operator()(const Numerator_type& n, const Denominator_type& d) const { typename ETT::Compose compose; return Type(compose(n.exact(),d.exact())); } }; struct Decompose { typedef void result_type; typedef Type first_argument_type; typedef Numerator_type second_argument_type; typedef Denominator_type third_argument_type; void operator()(const Type& f, Numerator_type& n, Denominator_type& d) const { typename ETT::Decompose decompose; ET_numerator nn; ET_denominator dd; decompose(f.exact(),nn,dd); n = Numerator_type(nn); d = Denominator_type(dd); } }; }; } // namespace INTERN_LAZY_EXACT_NT template < class ET > class Fraction_traits< Lazy_exact_nt< ET > > :public INTERN_LAZY_EXACT_NT::Fraction_traits_base, typename Fraction_traits::Is_fraction> {}; template < class ET > struct Min > : public CGAL::cpp98::binary_function,Lazy_exact_nt,Lazy_exact_nt > { Lazy_exact_nt operator()( const Lazy_exact_nt& x, const Lazy_exact_nt& y) const { if (x.identical(y)){ return x; } Uncertain res = x.approx() < y.approx(); if(is_certain(res)){ return res.make_certain() ? x : y; } CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); return new Lazy_exact_Min(x, y); } }; template < class ET > struct Max > : public CGAL::cpp98::binary_function,Lazy_exact_nt,Lazy_exact_nt > { Lazy_exact_nt operator()( const Lazy_exact_nt& x, const Lazy_exact_nt& y) const { if (x.identical(y)){ return x; } Uncertain res = x.approx() > y.approx(); if(is_certain(res)){ return res.make_certain() ? x : y; } CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION)); return new Lazy_exact_Max(x, y); } }; template inline Lazy_exact_nt min BOOST_PREVENT_MACRO_SUBSTITUTION( const Lazy_exact_nt & x, const Lazy_exact_nt & y){ return CGAL::Min > ()(x,y); } template inline Lazy_exact_nt max BOOST_PREVENT_MACRO_SUBSTITUTION( const Lazy_exact_nt & x, const Lazy_exact_nt & y){ return CGAL::Max > ()(x,y); } template std::ostream & operator<< (std::ostream & os, const Lazy_exact_nt & a) { return os << CGAL_NTS to_double(a); } template std::istream & operator>> (std::istream & is, Lazy_exact_nt & a) { ET e; internal::read_float_or_quotient(is, e); if (is) a = e; return is; } template< class ET > class Is_valid< Lazy_exact_nt > : public CGAL::cpp98::unary_function< Lazy_exact_nt, bool > { public : bool operator()( const Lazy_exact_nt& x ) const { return is_valid(x.approx()); } }; template < typename ET > struct NT_converter < Lazy_exact_nt, ET > { const ET& operator()(const Lazy_exact_nt &a) const { 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 // queried). template < typename ET > inline bool fit_in_double(const Lazy_exact_nt& l, double& r) { return fit_in_double(l.approx(), r); } } // namespace internal template void print(std::ostream &os, const CGAL::Lazy_exact_nt< Sqrt_extension > &r) { print(os,r.exact()); } namespace INTERN_LAZY_EXACT_NT { template< typename ET , typename Tag> class Modular_traits_base{ public: typedef Lazy_exact_nt NT; typedef ::CGAL::Tag_false Is_modularizable; typedef ::CGAL::Null_functor Residue_type; typedef ::CGAL::Null_functor Modular_image; typedef ::CGAL::Null_functor Modular_image_representative; }; template< typename ET > class Modular_traits_base{ typedef Modular_traits MT_ET; public: typedef Lazy_exact_nt NT; typedef CGAL::Tag_true Is_modularizable; typedef typename MT_ET::Residue_type Residue_type; struct Modular_image{ Residue_type operator()(const NT& a){ typename MT_ET::Modular_image modular_image; return modular_image(a.exact()); } }; struct Modular_image_representative{ NT operator()(const Residue_type& x){ typename MT_ET::Modular_image_representative modular_image_representative; return NT(modular_image_representative(x)); } }; }; } // namespace INTERN_LAZY_EXACT_NT template < typename ET > class Modular_traits > :public INTERN_LAZY_EXACT_NT::Modular_traits_base ::Is_modularizable>{}; #undef CGAL_double #undef CGAL_int #undef CGAL_To_interval } //namespace CGAL namespace Eigen { template struct NumTraits; template struct NumTraits > { typedef CGAL::Lazy_exact_nt Real; // typedef CGAL::Lazy_exact_nt NonInteger; typedef CGAL::Lazy_exact_nt::NonInteger> NonInteger; typedef CGAL::Lazy_exact_nt Nested; typedef CGAL::Lazy_exact_nt Literal; static inline Real epsilon() { return 0; } static inline Real dummy_precision() { return 0; } enum { IsInteger = NumTraits::IsInteger, IsSigned = NumTraits::IsSigned, IsComplex = NumTraits::IsComplex, RequireInitialization = 1, ReadCost = 8, AddCost = 30, MulCost = 30 }; }; } #endif // CGAL_LAZY_EXACT_NT_H