dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/Lazy_exact_nt.h

1439 lines
44 KiB
C++

// 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 <CGAL/number_type_basic.h>
#include <CGAL/assertions.h>
#include <CGAL/boost/iterator/transform_iterator.hpp> // for Root_of functor
#include <boost/operators.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/logical.hpp>
#include <CGAL/Interval_nt.h>
#include <CGAL/Handle.h>
#include <CGAL/NT_converter.h>
#include <CGAL/Profile_counter.h>
#include <CGAL/Lazy.h>
#include <CGAL/Sqrt_extension_fwd.h>
#include <CGAL/Kernel/mpl.h>
#include <CGAL/tss.h>
#include <CGAL/type_traits.h>
#include <CGAL/IO/io.h>
#define CGAL_int(T) typename First_if_different<int, T>::Type
#define CGAL_double(T) typename First_if_different<double, T>::Type
#define CGAL_To_interval(T) To_interval<T>
/*
* This file contains the definition of the number type Lazy_exact_nt<ET>,
* where ET is an exact number type (must provide the exact operations needed).
*
* Lazy_exact_nt<ET> 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<ET> 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 NT> class Lazy_exact_nt;
#ifdef CGAL_LAZY_KERNEL_DEBUG
template <typename ET>
inline
void
print_dag(const Lazy_exact_nt<ET>& l, std::ostream& os, int level=0)
{
l.print_dag(os, level);
}
#endif
// Abstract base representation class for lazy numbers
template <typename ET>
struct Lazy_exact_nt_rep : public Lazy_exact_nt<ET>::Self_rep
{
typedef typename Lazy_exact_nt<ET>::Self_rep Base;
Lazy_exact_nt_rep (const Interval_nt<false> & 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 <typename ET>
struct Lazy_exact_Int_Cst : public Lazy_exact_nt_rep<ET>
{
Lazy_exact_Int_Cst (int i)
: Lazy_exact_nt_rep<ET>(double(i)) {}
void update_exact() const { this->et = new ET((int)this->approx().inf()); }
};
// double constant
template <typename ET, typename X>
struct Lazy_exact_Cst : public Lazy_exact_nt_rep<ET>
{
Lazy_exact_Cst (X x)
: Lazy_exact_nt_rep<ET>(x), cste(x) {}
void update_exact() const { this->et = new ET(cste); }
private:
X cste;
};
// Exact constant
template <typename ET>
struct Lazy_exact_Ex_Cst : public Lazy_exact_nt_rep<ET>
{
Lazy_exact_Ex_Cst (const ET & e)
: Lazy_exact_nt_rep<ET>(CGAL_NTS to_interval(e))
{
this->et = new ET(e);
}
Lazy_exact_Ex_Cst (ET&& e)
: Lazy_exact_nt_rep<ET>(CGAL_NTS to_interval(e))
{
this->et = new ET(std::move(e));
}
void update_exact() const { CGAL_error(); }
};
// Construction from a Lazy_exact_nt<ET1> (which keeps the lazyness).
template <typename ET, typename ET1>
class Lazy_lazy_exact_Cst : public Lazy_exact_nt_rep<ET>
{
mutable Lazy_exact_nt<ET1> l;
public:
Lazy_lazy_exact_Cst (const Lazy_exact_nt<ET1> &x)
: Lazy_exact_nt_rep<ET>(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<ET1>(); }
};
// Unary operations: abs, sqrt, square.
// Binary operations: +, -, *, /, min, max.
// Base unary operation
template <typename ET>
struct Lazy_exact_unary : public Lazy_exact_nt_rep<ET>
{
mutable Lazy_exact_nt<ET> op1;
Lazy_exact_unary (const Interval_nt<false> &i, const Lazy_exact_nt<ET> &a)
: Lazy_exact_nt_rep<ET>(i), op1(a)
{
this->set_depth(op1.depth() + 1);
}
void prune_dag() const { op1 = Lazy_exact_nt<ET>(); }
#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 <typename ET, typename ET1 = ET, typename ET2 = ET>
struct Lazy_exact_binary : public Lazy_exact_nt_rep<ET>
{
mutable Lazy_exact_nt<ET1> op1;
mutable Lazy_exact_nt<ET2> op2;
Lazy_exact_binary (const Interval_nt<false> &i,
const Lazy_exact_nt<ET1> &a, const Lazy_exact_nt<ET2> &b)
: Lazy_exact_nt_rep<ET>(i), op1(a), op2(b)
{
this->set_depth((std::max)(op1.depth(), op2.depth()) + 1);
}
void prune_dag() const
{
op1 = Lazy_exact_nt<ET1>();
op2 = Lazy_exact_nt<ET2>();
}
#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 <typename ET> \
struct NAME : public Lazy_exact_unary<ET> \
{ \
typedef typename Lazy_exact_unary<ET>::AT::Protector P; \
NAME (const Lazy_exact_nt<ET> &a) \
: Lazy_exact_unary<ET>((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 <typename ET, typename ET1 = ET, typename ET2 = ET> \
struct NAME : public Lazy_exact_binary<ET, ET1, ET2> \
{ \
typedef typename Lazy_exact_binary<ET,ET1,ET2>::AT::Protector P; \
NAME (const Lazy_exact_nt<ET1> &a, const Lazy_exact_nt<ET2> &b) \
: Lazy_exact_binary<ET, ET1, ET2>((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 <typename ET>
struct Lazy_exact_Min : public Lazy_exact_binary<ET>
{
Lazy_exact_Min (const Lazy_exact_nt<ET> &a, const Lazy_exact_nt<ET> &b)
: Lazy_exact_binary<ET>((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 <typename ET>
struct Lazy_exact_Max : public Lazy_exact_binary<ET>
{
Lazy_exact_Max (const Lazy_exact_nt<ET> &a, const Lazy_exact_nt<ET> &b)
: Lazy_exact_binary<ET>((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 <typename ET_>
class Lazy_exact_nt
: public Lazy<Interval_nt<false>, ET_, To_interval<ET_> >
, boost::ordered_euclidian_ring_operators2< Lazy_exact_nt<ET_>, int >
, boost::ordered_euclidian_ring_operators2< Lazy_exact_nt<ET_>, double >
{
public:
typedef Lazy_exact_nt<ET_> Self;
typedef Lazy<Interval_nt<false>, ET_, To_interval<ET_> > 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<class T>
Lazy_exact_nt (T i, typename boost::enable_if<boost::mpl::and_<
boost::mpl::or_<boost::is_arithmetic<T>, std::is_enum<T> >,
boost::mpl::not_<boost::is_same<T,ET> > >,void*>::type=0)
: Base(new Lazy_exact_Cst<ET,T>(i)) {}
Lazy_exact_nt (const ET & e)
: Base(new Lazy_exact_Ex_Cst<ET>(e)){}
Lazy_exact_nt (ET&& e)
: Base(new Lazy_exact_Ex_Cst<ET>(std::move(e))){}
template <class ET1>
Lazy_exact_nt (const Lazy_exact_nt<ET1> &x,
typename boost::enable_if<is_implicit_convertible<ET1,ET>,int>::type=0)
: Base(new Lazy_lazy_exact_Cst<ET, ET1>(x)){}
template <class ET1>
explicit Lazy_exact_nt (const Lazy_exact_nt<ET1> &x,
typename boost::disable_if<is_implicit_convertible<ET1,ET>,int>::type=0)
: Base(new Lazy_lazy_exact_Cst<ET, ET1>(x)){}
friend void swap(Lazy_exact_nt& a, Lazy_exact_nt& b) noexcept
{ swap(static_cast<Base&>(a), static_cast<Base&>(b)); }
Self operator+ () const
{ return *this; }
Self operator- () const
{ return new Lazy_exact_Opp<ET>(*this); }
Self & operator+=(const Self& b)
{ return *this = new Lazy_exact_Add<ET>(*this, b); }
Self & operator-=(const Self& b)
{ return *this = new Lazy_exact_Sub<ET>(*this, b); }
Self & operator*=(const Self& b)
{ return *this = new Lazy_exact_Mul<ET>(*this, b); }
Self & operator/=(const Self& b)
{
CGAL_precondition(b != 0);
return *this = new Lazy_exact_Div<ET>(*this, b);
}
// Mixed operators. (could be optimized ?)
Self & operator+=(CGAL_int(ET) b)
{ return *this = new Lazy_exact_Add<ET>(*this, b); }
Self & operator-=(CGAL_int(ET) b)
{ return *this = new Lazy_exact_Sub<ET>(*this, b); }
Self & operator*=(CGAL_int(ET) b)
{ return *this = new Lazy_exact_Mul<ET>(*this, b); }
Self & operator/=(CGAL_int(ET) b)
{
CGAL_precondition(b != 0);
return *this = new Lazy_exact_Div<ET>(*this, b);
}
Self & operator+=(CGAL_double(ET) b)
{ return *this = new Lazy_exact_Add<ET>(*this, b); }
Self & operator-=(CGAL_double(ET) b)
{ return *this = new Lazy_exact_Sub<ET>(*this, b); }
Self & operator*=(CGAL_double(ET) b)
{ return *this = new Lazy_exact_Mul<ET>(*this, b); }
Self & operator/=(CGAL_double(ET) b)
{
CGAL_precondition(b != 0);
return *this = new Lazy_exact_Div<ET>(*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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<bool> 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<ET>(res);
}
Self & operator%=(int b)
{
CGAL_precondition(b != 0);
ET res = this->exact();
res %= b;
return *this = Lazy_exact_nt<ET>(res);
}
Interval_nt<true> interval() const
{
const Interval_nt<false>& i = this->approx();
return Interval_nt<true>(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<const Handle &>(*this),
static_cast<const Handle &>(b));
}
template < typename T >
bool identical(const T&) const
{ return false; }
};
template <typename ET1, typename ET2>
bool
operator<(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
if (a.identical(b))
return false;
Uncertain<bool> res = a.approx() < b.approx();
if (is_certain(res))
return get_certain(res);
CGAL_BRANCH_PROFILER_BRANCH(tmp);
return a.exact() < b.exact();
}
template <typename ET1, typename ET2>
bool
operator==(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
if (a.identical(b))
return true;
Uncertain<bool> res = a.approx() == b.approx();
if (is_certain(res))
return get_certain(res);
CGAL_BRANCH_PROFILER_BRANCH(tmp);
return a.exact() == b.exact();
}
template <typename ET1, typename ET2>
inline
bool
operator>(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{ return b < a; }
template <typename ET1, typename ET2>
inline
bool
operator>=(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{ return ! (a < b); }
template <typename ET1, typename ET2>
inline
bool
operator<=(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{ return b >= a; }
template <typename ET1, typename ET2>
inline
bool
operator!=(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{ return ! (a == b); }
template <typename ET>
inline
Lazy_exact_nt<ET>
operator%(const Lazy_exact_nt<ET>& a, const Lazy_exact_nt<ET>& b)
{
CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION));
CGAL_precondition(b != 0);
return Lazy_exact_nt<ET>(a) %= b;
}
template <typename ET1, typename ET2>
Lazy_exact_nt< typename Coercion_traits<ET1, ET2>::Type >
operator+(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{
CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION));
return new Lazy_exact_Add<typename Coercion_traits<ET1, ET2>::Type,
ET1, ET2>(a, b);
}
template <typename ET1, typename ET2>
Lazy_exact_nt< typename Coercion_traits<ET1, ET2>::Type >
operator-(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{
CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION));
return new Lazy_exact_Sub<typename Coercion_traits<ET1, ET2>::Type,
ET1, ET2>(a, b);
}
template <typename ET1, typename ET2>
Lazy_exact_nt< typename Coercion_traits<ET1, ET2>::Type >
operator*(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{
CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION));
return new Lazy_exact_Mul<typename Coercion_traits<ET1, ET2>::Type,
ET1, ET2>(a, b);
}
template <typename ET1, typename ET2>
Lazy_exact_nt< typename Coercion_traits<ET1, ET2>::Type >
operator/(const Lazy_exact_nt<ET1>& a, const Lazy_exact_nt<ET2>& b)
{
CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION));
CGAL_precondition(b != 0);
return new Lazy_exact_Div<typename Coercion_traits<ET1, ET2>::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<NT&, void> {
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, NT > {
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<NT, bool > {
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<NT, bool > {
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, NT > {
NT operator()( const NT& x ) const {
CGAL_PROFILER(std::string("calls to : ") + std::string(CGAL_PRETTY_FUNCTION));
return new Lazy_exact_Square<typename NT::ET>(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, NT, NT > {
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<NT, NT&, bool > {
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 <class NT, class AlgebraicStructureTag>
struct Sqrt_selector{
struct Sqrt : public CGAL::cpp98::unary_function<NT, NT > {
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<typename NT::ET>(x);
}
};
};
template <class NT>
struct Sqrt_selector<NT,Null_functor> {
typedef Null_functor Sqrt;
};
template< class NT, class Functor >
struct Kth_root_selector {
struct Kth_root : public CGAL::cpp98::binary_function<int, NT, NT > {
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<typename NT::ET>::
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, NT, NT > {
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, NT, NT > {
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, NT, NT > {
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 ET>
class Algebraic_structure_traits< Lazy_exact_nt<ET> >
:public Algebraic_structure_traits_base
< Lazy_exact_nt<ET>,
typename Algebraic_structure_traits<ET>::Algebraic_category >
{
private:
typedef Algebraic_structure_traits<ET> 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
<Lazy_exact_nt<ET>, typename AST_ET::Simplify > ::Simplify Simplify;
typedef typename INTERN_LAZY_EXACT_NT::Unit_part_selector
<Lazy_exact_nt<ET>, typename AST_ET::Unit_part > ::Unit_part Unit_part;
typedef typename INTERN_LAZY_EXACT_NT::Is_zero_selector
<Lazy_exact_nt<ET>, typename AST_ET::Is_zero > ::Is_zero Is_zero;
typedef typename INTERN_LAZY_EXACT_NT::Is_one_selector
<Lazy_exact_nt<ET>, typename AST_ET::Is_one > ::Is_one Is_one;
typedef typename INTERN_LAZY_EXACT_NT::Square_selector
<Lazy_exact_nt<ET>, typename AST_ET::Square > ::Square Square;
typedef typename INTERN_LAZY_EXACT_NT::Integral_division_selector
<Lazy_exact_nt<ET>, typename AST_ET::Integral_division> ::Integral_division Integral_division;
typedef typename INTERN_LAZY_EXACT_NT::Is_square_selector
<Lazy_exact_nt<ET>, typename AST_ET::Is_square > ::Is_square Is_square;
typedef typename INTERN_LAZY_EXACT_NT::Sqrt_selector
<Lazy_exact_nt<ET>, typename AST_ET::Sqrt> ::Sqrt Sqrt;
typedef typename INTERN_LAZY_EXACT_NT::Kth_root_selector
<Lazy_exact_nt<ET>, typename AST_ET::Kth_root > ::Kth_root Kth_root;
typedef typename INTERN_LAZY_EXACT_NT::Root_of_selector
<Lazy_exact_nt<ET>, typename AST_ET::Root_of > ::Root_of Root_of;
typedef typename INTERN_LAZY_EXACT_NT::Gcd_selector
<Lazy_exact_nt<ET>, typename AST_ET::Gcd > ::Gcd Gcd;
typedef typename INTERN_LAZY_EXACT_NT::Div_selector
<Lazy_exact_nt<ET>, typename AST_ET::Div > ::Div Div;
typedef typename INTERN_LAZY_EXACT_NT::Mod_selector
<Lazy_exact_nt<ET>, typename AST_ET::Mod > ::Mod Mod;
typedef typename INTERN_LAZY_EXACT_NT::Div_mod_selector
<Lazy_exact_nt<ET>, typename AST_ET::Div_mod > ::Div_mod Div_mod;
typedef typename INTERN_LAZY_EXACT_NT::Inverse_selector
<Lazy_exact_nt<ET>, typename AST_ET::Inverse > ::Inverse Inverse;
};
//
// Real embeddalbe traits
//
template < typename ET > class Real_embeddable_traits< Lazy_exact_nt<ET> >
: public INTERN_RET::Real_embeddable_traits_base< Lazy_exact_nt<ET> , CGAL::Tag_true > {
// Every type ET of Lazy_exact_nt<ET> 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<ET> 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<ET>(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<Comparison_result> 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<false>& 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<ET>::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<double, double> 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 ET1, class ET2, class F>
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 ET1, class ET2>
class Lazy_exact_nt_coercion_traits_base < Lazy_exact_nt<ET1>, Lazy_exact_nt<ET2>, Tag_true >
{
typedef Coercion_traits<ET1,ET2> CT;
typedef Lazy_exact_nt<ET1> A;
typedef Lazy_exact_nt<ET2> B;
public:
typedef Lazy_exact_nt<typename CT::Type> Type;
typedef typename CT::Are_implicit_interoperable Are_explicit_interoperable;
typedef typename CT::Are_implicit_interoperable Are_implicit_interoperable;
class Cast{
private:
template <class T>
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<ET>, class ET)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO_TEM(ET,Lazy_exact_nt<ET>,class ET)
template<class ET1, class ET2 >
struct Coercion_traits< Lazy_exact_nt<ET1>, Lazy_exact_nt<ET2> >
:public Lazy_exact_nt_coercion_traits_base
<Lazy_exact_nt<ET1>, Lazy_exact_nt<ET2>,
typename Coercion_traits<ET1,ET2>::Are_implicit_interoperable>{};
#define CGAL_COERCION_TRAITS_LAZY_EXACT(NTX) \
template<class ET> \
struct Coercion_traits< NTX, Lazy_exact_nt<ET> >{ \
private: \
typedef Coercion_traits<NTX,ET> CT; \
typedef Lazy_exact_nt<ET> 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 <interoperable,Null_tag,NT> \
::type Type; \
typedef typename boost::mpl::if_c <interoperable, Null_functor, \
INTERN_CT::Cast_from_to<NTX,NT> >::type Cast; \
}; \
\
template<class ET> \
struct Coercion_traits< Lazy_exact_nt<ET>, NTX > \
:public Coercion_traits<NTX, Lazy_exact_nt<ET> >{}; \
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 <Lazy_exact_nt<ET> , CGAL::Tag_false>
: public Fraction_traits<ET> {
public:
typedef Lazy_exact_nt<ET> Type;
};
template < class ET >
class Fraction_traits_base <Lazy_exact_nt<ET> , CGAL::Tag_true>{
typedef Fraction_traits<ET> ETT;
typedef typename ETT::Numerator_type ET_numerator;
typedef typename ETT::Denominator_type ET_denominator;
public:
typedef Lazy_exact_nt<ET> Type;
typedef Tag_true Is_fraction;
typedef Lazy_exact_nt<ET_numerator> Numerator_type;
typedef Lazy_exact_nt<ET_denominator> Denominator_type;
struct Common_factor : CGAL::cpp98::binary_function<Denominator_type,Denominator_type,Denominator_type>{
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,Numerator_type,Denominator_type>{
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<Lazy_exact_nt<ET>,
typename Fraction_traits<ET>::Is_fraction>
{};
template < class ET >
struct Min <Lazy_exact_nt<ET> >
: public CGAL::cpp98::binary_function<Lazy_exact_nt<ET>,Lazy_exact_nt<ET>,Lazy_exact_nt<ET> > {
Lazy_exact_nt<ET> operator()( const Lazy_exact_nt<ET>& x, const Lazy_exact_nt<ET>& y) const
{
if (x.identical(y)){
return x;
}
Uncertain<bool> 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<ET>(x, y);
}
};
template < class ET >
struct Max <Lazy_exact_nt<ET> >
: public CGAL::cpp98::binary_function<Lazy_exact_nt<ET>,Lazy_exact_nt<ET>,Lazy_exact_nt<ET> > {
Lazy_exact_nt<ET> operator()( const Lazy_exact_nt<ET>& x, const Lazy_exact_nt<ET>& y) const
{
if (x.identical(y)){
return x;
}
Uncertain<bool> 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<ET>(x, y);
}
};
template<typename ET> inline
Lazy_exact_nt<ET> min BOOST_PREVENT_MACRO_SUBSTITUTION(
const Lazy_exact_nt<ET> & x,
const Lazy_exact_nt<ET> & y){
return CGAL::Min<Lazy_exact_nt<ET> > ()(x,y);
}
template<typename ET> inline
Lazy_exact_nt<ET> max BOOST_PREVENT_MACRO_SUBSTITUTION(
const Lazy_exact_nt<ET> & x,
const Lazy_exact_nt<ET> & y){
return CGAL::Max<Lazy_exact_nt<ET> > ()(x,y);
}
template <typename ET>
std::ostream &
operator<< (std::ostream & os, const Lazy_exact_nt<ET> & a)
{ return os << CGAL_NTS to_double(a); }
template <typename ET>
std::istream &
operator>> (std::istream & is, Lazy_exact_nt<ET> & 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<ET> >
: public CGAL::cpp98::unary_function< Lazy_exact_nt<ET>, bool > {
public :
bool operator()( const Lazy_exact_nt<ET>& x ) const {
return is_valid(x.approx());
}
};
template < typename ET >
struct NT_converter < Lazy_exact_nt<ET>, ET >
{
const ET& operator()(const Lazy_exact_nt<ET> &a) const
{ return a.exact(); }
};
// Forward declaration to break inclusion cycle
namespace internal {
template<class>struct Exact_field_selector;
template<class>struct Exact_ring_selector;
}
// Compiler can deduce ET from the first argument.
template < typename ET >
struct NT_converter < Lazy_exact_nt<ET>,
typename First_if_different<
typename internal::Exact_field_selector<ET>::Type,
ET>::Type>
{
typename internal::Exact_field_selector<ET>::Type
operator()(const Lazy_exact_nt<ET> &a) const
{ return NT_converter<ET,typename internal::Exact_field_selector<ET>::Type>()(a.exact()); }
};
template < typename ET >
struct NT_converter < Lazy_exact_nt<ET>,
typename First_if_different<
typename First_if_different<
typename internal::Exact_ring_selector<ET>::Type,
ET>::Type,
typename internal::Exact_field_selector<ET>::Type>::Type>
{
typename internal::Exact_ring_selector<ET>::Type operator()(const Lazy_exact_nt<ET> &a) const
{ return NT_converter<ET,typename internal::Exact_ring_selector<ET>::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<ET>& l, double& r)
{ return fit_in_double(l.approx(), r); }
} // namespace internal
template <class NT_,class ROOT_, class ACDE_TAG_, class FP_TAG>
void
print(std::ostream &os, const CGAL::Lazy_exact_nt< Sqrt_extension<NT_,ROOT_,ACDE_TAG_,FP_TAG> > &r)
{
print(os,r.exact());
}
namespace INTERN_LAZY_EXACT_NT {
template< typename ET , typename Tag>
class Modular_traits_base{
public:
typedef Lazy_exact_nt<ET> 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<ET, Tag_true>{
typedef Modular_traits<ET> MT_ET;
public:
typedef Lazy_exact_nt<ET> 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<Lazy_exact_nt<ET> >
:public INTERN_LAZY_EXACT_NT::Modular_traits_base
<ET,typename Modular_traits<ET>::Is_modularizable>{};
#undef CGAL_double
#undef CGAL_int
#undef CGAL_To_interval
} //namespace CGAL
namespace Eigen {
template<class> struct NumTraits;
template<typename ET> struct NumTraits<CGAL::Lazy_exact_nt<ET> >
{
typedef CGAL::Lazy_exact_nt<ET> Real;
// typedef CGAL::Lazy_exact_nt<ET> NonInteger;
typedef CGAL::Lazy_exact_nt<typename NumTraits<ET>::NonInteger> NonInteger;
typedef CGAL::Lazy_exact_nt<ET> Nested;
typedef CGAL::Lazy_exact_nt<ET> Literal;
static inline Real epsilon() { return 0; }
static inline Real dummy_precision() { return 0; }
enum {
IsInteger = NumTraits<ET>::IsInteger,
IsSigned = NumTraits<ET>::IsSigned,
IsComplex = NumTraits<ET>::IsComplex,
RequireInitialization = 1,
ReadCost = 8,
AddCost = 30,
MulCost = 30
};
};
}
#endif // CGAL_LAZY_EXACT_NT_H