// Copyright (c) 2005 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) : Sylvain Pion #ifndef CGAL_UNCERTAIN_H #define CGAL_UNCERTAIN_H #include #include #include CGAL_BEGIN_NAMESPACE namespace CGALi { // Accessory traits class to provide min and max value of a type. // Specialized for bool and CGAL's enums. template < typename T > struct Minmax_traits; template <> struct Minmax_traits { static const bool min = false; static const bool max = true; }; template <> struct Minmax_traits { static const Sign min = NEGATIVE; static const Sign max = POSITIVE; }; template <> struct Minmax_traits { static const Comparison_result min = SMALLER; static const Comparison_result max = LARGER; }; template <> struct Minmax_traits { static const Oriented_side min = ON_NEGATIVE_SIDE; static const Oriented_side max = ON_POSITIVE_SIDE; }; template <> struct Minmax_traits { static const Bounded_side min = ON_UNBOUNDED_SIDE; static const Bounded_side max = ON_BOUNDED_SIDE; }; template <> struct Minmax_traits { static const Angle min = OBTUSE; static const Angle max = ACUTE; }; } // namespace CGALi // Encodes an interval [min;max] of values of type T. // The primary template is supposed to work for enums and bool. template < typename T > class Uncertain { T _i, _s; static unsigned failures; // Number of conversion failures. public: typedef T value_type; Uncertain() : _i(CGALi::Minmax_traits::min), _s(CGALi::Minmax_traits::max) {} Uncertain(const T & t) : _i(t), _s(t) {} Uncertain(const T & i, const T & s) : _i(i), _s(s) {} const T & inf() const { return _i; } const T & sup() const { return _s; } // NB : conversion to bool might be too risky // (boost::tribool uses something else). operator const T &() const { if (_i == _s) return _i; //++failures; ++Uncertain::number_of_failures(); // reasonnable ? throw std::range_error("undecidable conversion of Uncertain"); } static unsigned & number_of_failures() { return failures; } static Uncertain indeterminate(); }; template < typename T > unsigned Uncertain::failures = 0; // Access functions // ---------------- template < typename T > inline const T & inf(Uncertain const& i) { return i.inf(); } template < typename T > inline const T & sup(Uncertain const& i) { return i.sup(); } // Basic functions // --------------- template < typename T > inline Uncertain Uncertain::indeterminate() { return Uncertain(); } template < typename T > inline bool is_indeterminate(T const& a) { return false; } template < typename T > inline bool is_indeterminate(Uncertain const& a) { return a.inf() != a.sup(); } template < typename T > inline bool is_singleton(Uncertain const& a) { return a.inf() == a.sup(); } // Boolean operations for Uncertain // -------------------------------------- inline Uncertain operator!(Uncertain const& a) { return Uncertain(!a.sup(), !a.inf()); } inline Uncertain operator|(Uncertain const& a, Uncertain const& b) { return Uncertain(a.inf() || b.inf(), a.sup() || b.sup()); } inline Uncertain operator|(bool a, Uncertain const& b) { return Uncertain(a || b.inf(), a || b.sup()); } inline Uncertain operator|(Uncertain const& a, bool b) { return Uncertain(a.inf() || b, a.sup() || b); } inline Uncertain operator&(Uncertain const& a, Uncertain const& b) { return Uncertain(a.inf() && b.inf(), a.sup() && b.sup()); } inline Uncertain operator&(bool a, Uncertain const& b) { return Uncertain(a && b.inf(), a && b.sup()); } inline Uncertain operator&(Uncertain const& a, bool b) { return Uncertain(a.inf() && b, a.sup() && b); } // Equality operators template < typename T > inline Uncertain operator==(Uncertain const& a, Uncertain const& b) { if (is_indeterminate(a) || is_indeterminate(b)) return Uncertain::indeterminate(); return a.inf() == b.inf(); } template < typename T > inline Uncertain operator==(Uncertain const& a, const T & b) { if (is_indeterminate(a)) return Uncertain::indeterminate(); return a.inf() == b; } template < typename T > inline Uncertain operator==(const T & a, Uncertain const& b) { if (is_indeterminate(b)) return Uncertain::indeterminate(); return a == b.inf(); } template < typename T > inline Uncertain operator!=(Uncertain const& a, Uncertain const& b) { return ! (a == b); } template < typename T > inline Uncertain operator!=(Uncertain const& a, const T & b) { return ! (a == b); } template < typename T > inline Uncertain operator!=(const T & a, Uncertain const& b) { return ! (a == b); } // Maker function (a la std::make_pair). template < typename T > inline Uncertain make_uncertain(const T&t) { return Uncertain(t); } template < typename T > inline const Uncertain & make_uncertain(const Uncertain &t) { return t; } // opposite template < typename T > inline Uncertain opposite(const Uncertain &u) { return Uncertain(opposite(u.sup()), opposite(u.inf())); } // enum_cast overload #ifdef CGAL_CFG_MATCHING_BUG_5 template < typename T, typename U > inline Uncertain enum_cast_bug(const Uncertain& u, const T*) { return Uncertain(static_cast(u.inf()), static_cast(u.sup())); } #else template < typename T, typename U > inline Uncertain enum_cast(const Uncertain& u) { return Uncertain(static_cast(u.inf()), static_cast(u.sup())); } #endif CGAL_END_NAMESPACE #endif // CGAL_UNCERTAIN_H