// ============================================================================ // // Copyright (c) 1999,2000 The CGAL Consortium // // This software and related documentation is part of an INTERNAL release // of the Computational Geometry Algorithms Library (CGAL). It is not // intended for general use. // // ---------------------------------------------------------------------------- // // release : // release_date : // // file : include/CGAL/Lazy_exact_nt.h // revision : $Revision$ // revision_date : $Date$ // package : Interval Arithmetic // author(s) : Sylvain Pion // coordinator : INRIA Sophia-Antipolis () // // ============================================================================ #ifndef CGAL_LAZY_EXACT_NT_H #define CGAL_LAZY_EXACT_NT_H #include #include #include #include #include #include #include #include /* * 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_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. * - Interval rafinement 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 like Filtered_exact_nt<> ? * - 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() later we can do that (having a birthdate like LOOK ?). * could use update_approx(). */ CGAL_BEGIN_NAMESPACE template class Lazy_exact_nt; // Abstract base representation class template struct Lazy_exact_rep : public Rep { Interval_base in; // could be const, except for rafinement ? or mutable ? ET *et; // mutable as well ? Lazy_exact_rep (const Interval_base & i) : in(i), et(NULL) {} private: Lazy_exact_rep (const Lazy_exact_rep&) { abort(); } // cannot be copied. public: Interval_nt approx() const // TODO : return a const ref instead ! { return in; } const ET & exact() { if (et==NULL) update_exact(); return *et; } virtual void update_approx() = 0; // Not used anymore... at the moment :) virtual void update_exact() = 0; virtual ~Lazy_exact_rep () { delete et; }; }; // int constant template struct Lazy_exact_Int_Cst : public Lazy_exact_rep { Lazy_exact_Int_Cst (int i) : Lazy_exact_rep(double(i)) {} void update_approx() { CGAL_assertion(false); } void update_exact() { this->et = new ET((int)this->in.inf()); } }; // double constant template struct Lazy_exact_Cst : public Lazy_exact_rep { Lazy_exact_Cst (double d) : Lazy_exact_rep(d) {} void update_approx() { CGAL_assertion(false); } void update_exact() { this->et = new ET(this->in.inf()); } }; // Exact constant template struct Lazy_exact_Ex_Cst : public Lazy_exact_rep { Lazy_exact_Ex_Cst (const ET & e) : Lazy_exact_rep(to_interval(e)) { this->et = new ET(e); } void update_approx() { CGAL_assertion(false); } void update_exact() { CGAL_assertion(false); } }; // Construction from a Lazy_exact_nt (which keeps the lazyness). template struct Lazy_lazy_exact_Cst : public Lazy_exact_rep { Lazy_lazy_exact_Cst (const Lazy_exact_nt &x) : Lazy_exact_rep(x.approx()), l(x) {} void update_approx() { CGAL_assertion(false); } void update_exact() { this->et = new ET(l.exact()); } Lazy_exact_nt l; }; // Unary operations: abs, sqrt, square. // Binary operations: +, -, *, /, min, max. // Base unary operation template struct Lazy_exact_unary : public Lazy_exact_rep { const Lazy_exact_nt op1; Lazy_exact_unary (const Interval_base &i, const Lazy_exact_nt &a) : Lazy_exact_rep(i), op1(a) {} }; // Base binary operation template struct Lazy_exact_binary : public Lazy_exact_unary { const Lazy_exact_nt op2; Lazy_exact_binary (const Interval_base &i, const Lazy_exact_nt &a, const Lazy_exact_nt &b) : Lazy_exact_unary(i, a), op2(b) {} }; // 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 \ { \ NAME (const Lazy_exact_nt &a) \ : Lazy_exact_unary(OP(a.approx()), a) {} \ \ void update_approx() { this->in = OP(this->op1.approx()); } \ void update_exact() { this->et = new ET(OP(this->op1.exact())); } \ }; CGAL_LAZY_UNARY_OP(CGAL::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::sqrt, Lazy_exact_Sqrt) // A macro for +, -, * and / #define CGAL_LAZY_BINARY_OP(OP, NAME) \ template \ struct NAME : public Lazy_exact_binary \ { \ NAME (const Lazy_exact_nt &a, const Lazy_exact_nt &b) \ : Lazy_exact_binary(a.approx() OP b.approx(), a, b) {} \ \ void update_approx() \ { \ this->in = this->op1.approx() OP this->op2.approx(); \ } \ void update_exact() \ { \ this->et = new ET(this->op1.exact() OP this->op2.exact()); \ } \ }; 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(min(a.approx(), b.approx()), a, b) {} void update_approx() { this->in = min(this->op1.approx(), this->op2.approx()); } void update_exact() { this->et = new ET(min(this->op1.exact(), this->op2.exact())); } }; // 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(max(a.approx(), b.approx()), a, b) {} void update_approx() { this->in = max(this->op1.approx(), this->op2.approx()); } void update_exact() { this->et = new ET(max(this->op1.exact(), this->op2.exact())); } }; // The real number type, handle class template class Lazy_exact_nt : public Handle { public : typedef typename Number_type_traits::Has_gcd Has_gcd; typedef typename Number_type_traits::Has_division Has_division; typedef typename Number_type_traits::Has_sqrt Has_sqrt; typedef Lazy_exact_nt Self; typedef Lazy_exact_rep Self_rep; // Lazy_exact_nt () {} // Handle is not such a nice stuff... at the moment. Lazy_exact_nt (Self_rep *r) { PTR = r; } // Operations Lazy_exact_nt (double d) { PTR = new Lazy_exact_Cst(d); } Lazy_exact_nt (int i = 0) { PTR = new Lazy_exact_Int_Cst(i); } Lazy_exact_nt (const ET & e) { PTR = new Lazy_exact_Ex_Cst(e); } template Lazy_exact_nt (const Lazy_exact_nt &x) { PTR = new Lazy_lazy_exact_Cst(x); } Self operator- () const { return new Lazy_exact_Opp(*this); } Self operator+ (const Self & a) const { return new Lazy_exact_Add(*this, a); } Self operator- (const Self & a) const { return new Lazy_exact_Sub(*this, a); } Self operator* (const Self & a) const { return new Lazy_exact_Mul(*this, a); } Self operator/ (const Self & a) const { return new Lazy_exact_Div(*this, a); } Interval_nt approx() const { return ptr()->approx(); } Interval_nt interval() const { return ptr()->approx(); } Interval_nt_advanced approx_adv() const { return ptr()->approx(); } const ET & exact() const { return ptr()->exact(); } bool operator< (const Self & a) const { try { return approx() < a.approx(); } catch (Interval_base::unsafe_comparison) { // std::cerr << "Interval filter failure (<)" << std::endl; return exact() < a.exact(); } } bool operator> (const Self & a) const { return a<*this; } bool operator>= (const Self & a) const { return !(*this inline double to_double(const Lazy_exact_nt & a) { return CGAL::to_double(a.approx()); } template inline Interval_base to_interval(const Lazy_exact_nt & a) { return a.approx(); } #ifndef CGAL_CFG_MATCHING_BUG_2 namespace NTS { template inline Sign sign(const Lazy_exact_nt & a) { try { return CGAL_NTS sign(a.approx()); } catch (Interval_base::unsafe_comparison) { // std::cerr << "Interval filter failure (sign)" << std::endl; return CGAL_NTS sign(a.exact()); } } template inline Comparison_result compare(const Lazy_exact_nt & a, const Lazy_exact_nt & b) { try { return CGAL_NTS compare(a.approx(), b.approx()); } catch (Interval_base::unsafe_comparison) { // std::cerr << "Interval filter failure (compare)" << std::endl; return CGAL_NTS compare(a.exact(), b.exact()); } } template inline Lazy_exact_nt abs(const Lazy_exact_nt & a) { return new Lazy_exact_Abs(a); } template inline Lazy_exact_nt square(const Lazy_exact_nt & a) { return new Lazy_exact_Square(a); } } // namespace NTS #endif // CGAL_CFG_MATCHING_BUG_2 template inline Lazy_exact_nt sqrt(const Lazy_exact_nt & a) { return new Lazy_exact_Sqrt(a); } #ifndef CGAL_CFG_MATCHING_BUG_2 template inline Lazy_exact_nt min(const Lazy_exact_nt & a, const Lazy_exact_nt & b) { return new Lazy_exact_Min(a, b); } template inline Lazy_exact_nt max(const Lazy_exact_nt & a, const Lazy_exact_nt & b) { return new Lazy_exact_Max(a, b); } #endif // CGAL_CFG_MATCHING_BUG_2 template std::ostream & operator<< (std::ostream & os, const Lazy_exact_nt & a) { return os << CGAL::to_double(a); } template std::istream & operator>> (std::istream & is, Lazy_exact_nt & a) { ET e; is >> e; a = e; return is; } template inline Lazy_exact_nt & operator+=(Lazy_exact_nt & a, const Lazy_exact_nt & b) { return a = a + b; } template inline Lazy_exact_nt & operator-=(Lazy_exact_nt & a, const Lazy_exact_nt & b) { return a = a - b; } template inline Lazy_exact_nt & operator*=(Lazy_exact_nt & a, const Lazy_exact_nt & b) { return a = a * b; } template inline Lazy_exact_nt & operator/=(Lazy_exact_nt & a, const Lazy_exact_nt & b) { return a = a / b; } template inline bool is_finite(const Lazy_exact_nt & a) { return is_finite(a.approx()) || is_finite(a.exact()); } template inline bool is_valid(const Lazy_exact_nt & a) { return is_valid(a.approx()) || is_valid(a.exact()); } template inline io_Operator io_tag (const Lazy_exact_nt&) { return io_Operator(); } #ifndef CGAL_CFG_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION template struct converter > { static inline ET do_it (const Lazy_exact_nt & z) { return z.exact(); } }; #endif CGAL_END_NAMESPACE #endif // CGAL_LAZY_EXACT_NT_H