diff --git a/.gitattributes b/.gitattributes index 5446f0b9009..1f4188a473b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3485,9 +3485,11 @@ Ridges_3/examples/Ridges_3/skip_vcproj_auto_generation -text Ridges_3/test/Ridges_3/data/ellipsoid.off -text svneol=unset#application/octet-stream Robustness/demo/Robustness/help/index.html svneol=native#text/html Robustness/demo/Robustness/robustness.vcproj eol=crlf +STL_Extension/doc_tex/STL_Extension_ref/Uncertain.tex -text STL_Extension/include/CGAL/Default_argument.h -text STL_Extension/include/CGAL/array.h -text STL_Extension/include/CGAL/type_traits.h -text +STL_Extension/test/STL_Extension/test_Uncertain.cpp -text STL_Extension/test/STL_Extension/test_type_traits.cpp -text Scripts/developer_scripts/autotest_cgal_with_cmake -text Scripts/developer_scripts/check_no_CGAL_USE_without_includes_before -text diff --git a/STL_Extension/doc_tex/STL_Extension/main.tex b/STL_Extension/doc_tex/STL_Extension/main.tex index 6b83b4340c7..ce61555fa31 100644 --- a/STL_Extension/doc_tex/STL_Extension/main.tex +++ b/STL_Extension/doc_tex/STL_Extension/main.tex @@ -26,7 +26,7 @@ generic algorithms, iterators, functor adaptors for binding and swapping arguments and for composition, functors for projection and creation and adaptor classes around iterators and circulators. See also circulators in Chapter~\ref{chapterCirculators}. A class storing polymorphic objects -is also provided. +is also provided, as well as a class to manage the uncertainty of some values. \section{Doubly-Connected List Managing Items in Place} @@ -112,3 +112,23 @@ It can be used by a function to return objects of different types. A mechanism to extract the stored object based on its type is also provided. This class is similar to \ccc{boost::any}. +\section{Uncertainty management} + +The class \ccStyle{Uncertain} represents a range of values of type \ccc{T}. +\ccc{T} is allowed to stand for \ccc{bool}, or CGAL's enumeration types +\ccc{Sign}, \ccc{Comparison_result}, \ccc{Orientation}, \ccc{Oriented_side}, +\ccc{Bounded_side} and \ccc{Angle}. + +The idea is that sometimes you are not sure of the result of a function, +and you would like to communicate that to the caller. \ccc{Uncertain} +allows just that. It also provides functions to naturally extend the +Boolean operations for \ccc{Uncertain} for example. + +\ccc{Uncertain} is used in CGAL as the return type of geometric predicates +when the number type used is interval arithmetic like \ccc{Interval_nt}. +End users typically do not see it as it is hidden in the implementation +of the filtered predicates provided by the various filtered kernels, +but it is important that providers of predicates that are meant to be +filtered by \ccc{Filtered_predicate}, know about it. + +It can also be used in other contexts as well, as it is a general tool. diff --git a/STL_Extension/doc_tex/STL_Extension_ref/Uncertain.tex b/STL_Extension/doc_tex/STL_Extension_ref/Uncertain.tex new file mode 100644 index 00000000000..f1f12283a0d --- /dev/null +++ b/STL_Extension/doc_tex/STL_Extension_ref/Uncertain.tex @@ -0,0 +1,326 @@ +%% ============================================================================= +%% The CGAL Reference Manual +%% Chapter: STL Extensions - The Reference Part +%% ----------------------------------------------------------------------------- +%% author: Sylvain Pion +%% ----------------------------------------------------------------------------- +%% $Id: $ +%% $URL: $ +%% ============================================================================= + +%% +=========================================================================+ + +\begin{ccRefClass}{Uncertain} + +\ccDefinition + +An object of the class \ccClassTemplateName\ represents an uncertainty on the +value of type \ccc{T}. This uncertainty is represented by a non-empty range of +values of type \ccc{T}. + +The idea is that sometimes you are not sure of the result of a function, and +you would like to communicate that to the caller. \ccc{Uncertain} allows +just that. + +\ccc{Uncertain} is also meant to be used as a drop-in replacement for +\ccc{T} in some template contexts, as much as possible. This is why it +provides overloaded operators and functions to naturally extend the Boolean +operations for \ccc{Uncertain} for example, or the operations on +enumeration types. + +\ccc{Uncertain} is used in CGAL as the return type of geometric predicates +when the number type used is interval arithmetic like \ccc{Interval_nt}. End +users typically do not see it, as it is hidden in the implementation of the +filtered predicates provided by the various filtered kernels, but it is +important that providers of predicates that are meant to be filtered by +\ccc{Filtered_predicate}, know about it. + +Note concerning \cgal\ assertions: assertions checking an expression of type +\ccc{Uncertain} will trigger an assertion failure only if the assertion +is certainly false. In case of an indeterminate value, the assertion is not +triggered. This means that we assume, in case of doubt, that there is no +error. + +It can also be used in other contexts as well, as it is a general tool. +This can be seem as support for non-deterministic programming. +Finally, note that this class has some common points with \ccc{boost::tribool}. + + \ccInclude{CGAL/Uncertain.h} + + %% +-----------------------------------+ + \ccParameters + + The parameter \ccStyle{T} can either be \ccc{bool} or one of the three-valued + (-1, 0, 1) enumeration types: \ccc{Sign}, \ccc{Comparison_result}, + \ccc{Orientation}, \ccc{Oriented_side}, \ccc{Bounded_side} or \ccc{Angle}. + + Some functions are defined only when \ccc{T} is \ccc{bool} or alternatively + when it is one of the enumeration types listed previously. + +% TODO : the CGALi::Minmax_traits should be documented (and renamed before that). + + %% +-----------------------------------+ + \ccTypes + \ccSetThreeColumns{static Uncertain}{l.swap( l1)xxxxxxxxxxxx;}{} + \ccPropagateThreeToTwoColumns + + \ccNestedType{value_type}{The type \ccc{T}.} + + \ccNestedType{Uncertain_conversion_exception}{The type of the exception + thrown for uncertain conversions. It is a typedef to the type + \ccc{CGAL::Uncertain_conversion_exception} which derives from \ccc{std::range_error}.} + + %% +-----------------------------------+ + \ccCreation + \ccCreationVariable{u} + + \ccConstructor{Uncertain();} + {introduces an indeterminate value.} + + \ccConstructor{Uncertain(T t);} + {introduces a certain object with value \ccc{t}.} + + \ccMethod{Uncertain& operator=(T t);} + {assigns the certain value \ccc{t} to \ccc{u}.} + + \ccConstructor{Uncertain(T i, T s);} + {introduces an object representing the range with lower bound \ccc{i} and + upper bound \ccc{s}. \ccPrecond $ i<= s$. } + + %% +-----------------------------------+ + \ccHeading{Access Functions} + + % \def\ccTagRmTrailingConst{\ccFalse} + \ccMethod{T inf() const;} + {returns the lower bound of the range represented by~\ccVar.} + + \ccGlue\ccMethod{T sup() const;} + {returns the upper bound of the range represented by~\ccVar.} + + %% +-----------------------------------+ + \ccHeading{Uncertainty testing and conversion} + + \ccMethod{bool is_certain() const;} + {returns \ccc{true} iff the value is certain, that is, it is unique, the range + is a singleton. That is, \ccc{u.inf() == u.sup()}.} + + \ccMethod{T make_certain() const;} + {if \ccVar.\ccc{is_certain()}, then returns the certain value which is represented. + Otherwise, throws an exception of type \ccc{Uncertain_conversion_exception}.} + + \ccMethod{operator T() const;} + {conversion operator to \ccc{T}. It does and returns the same thing as + \ccVar.\ccc{make_certain()}. Note that relying on the automatic conversion + can throw exceptions, which defeats the purpose of propagating uncertainty. + Nevertheless, in many cases, it is hard to avoid it, for example for the + \ccc{&&} and $||$ operators for \ccc{bool} (see below).} + + %% +-----------------------------------+ + \ccHeading{Static member function} + + \def\ccTagRmEigenClassName{\ccFalse} + \ccFunction{static Uncertain Uncertain::indeterminate();} + {returns an indeterminate range, like the default constructor.} + + %% +-----------------------------------+ + \ccHeading{Free functions} + + \ccFunction{template T inf(Uncertain u);} + {returns \ccc{u.inf()}.} + + \ccFunction{template T sup(Uncertain u);} + {returns \ccc{u.sup()}.} + + \ccFunction{template bool is_certain(T t);} + {returns \ccc{true}.} + + \ccFunction{template bool is_certain(Uncertain u);} + {returns \ccc{u}.\ccc{is_certain}().} + + \ccFunction{template bool is_indeterminate(T u);} + {returns \ccc{false}.} + + \ccFunction{template bool is_indeterminate(Uncertain u);} + {returns \ccc{!is_certain(u)}.} + + \ccFunction{template T get_certain(T t);} + {returns \ccc{t}.} + + \ccFunction{template T get_certain(Uncertain u);} + {returns \ccc{u}.\ccc{make_certain}(). \ccPrecond \ccc{u}.\ccc{is_certain}().} + + \ccFunction{template T make_certain(T t);} + {returns \ccc{t}.} + + \ccFunction{template T make_certain(Uncertain u);} + {returns \ccc{u}.\ccc{make_certain}().} + + \ccFunction{template Uncertain make_uncertain(T t);} + {returns \ccc{Uncertain(u)}.} + + \ccFunction{template Uncertain make_uncertain(Uncertain u);} + {returns \ccc{u}.} + + %% +-----------------------------------+ + \ccHeading{Overloaded operators} + + The overloaded operators and functions are defined as preserving the set-inclusion property. + Similarly to interval arithmetic, the returned range is guaranteed to contain + the result of the operation over all values of the input range(s). + In the following documentation we express this as the extension of the corresponding function + over the type \ccc{T}. + + \ccFunction{template + Uncertain operator==(Uncertain u, Uncertain v);} + {returns the extension of the equality operator over \ccc{u} and \ccc{v}.} + + \ccFunction{template + Uncertain operator==(Uncertain u, T v);} + {returns \ccc{u == make_uncertain(v)}.} + + \ccFunction{template + Uncertain operator==(T u, Uncertain v);} + {returns \ccc{v == u}.} + + \ccFunction{template + Uncertain operator!=(Uncertain u, Uncertain v);} + {returns the extension of the inequality operator over \ccc{u} and \ccc{v}.} + + \ccFunction{template + Uncertain operator!=(Uncertain u, T v);} + {returns \ccc{u != make_uncertain(v)}.} + + \ccFunction{template + Uncertain operator!=(T u, Uncertain v);} + {returns \ccc{v != u}.} + + %% +-----------------------------------+ + \ccHeading{Overloaded operators for \ccc{Uncertain} only} + + \ccFunction{Uncertain operator!(Uncertain u);} + {returns the range containing the negated values of \ccc{u}.} + + \ccFunction{Uncertain operator|(Uncertain u, Uncertain v);} + {returns the range containing the values computed as logical or from \ccc{u} and \ccc{v}.} + + \ccFunction{Uncertain operator|(Uncertain u, bool v);} + {returns \ccc{u | make_uncertain(v)}.} + + \ccFunction{Uncertain operator|(bool u, Uncertain v);} + {returns \ccc{v | u}.} + + \ccFunction{Uncertain operator&(Uncertain u, Uncertain v);} + {returns the range containing the values computed as logical and from \ccc{u} and \ccc{v}.} + + \ccFunction{Uncertain operator&(Uncertain u, bool v);} + {returns \ccc{u & make_uncertain(v)}.} + + \ccFunction{Uncertain operator&(bool u, Uncertain v);} + {returns \ccc{v & u}.} + + Note : the logical operators $\&\&$ and $||$ are not overloaded on purpose. The reason + is that, when \ccc{f() && g()} is evaluated and they return \ccc{bool}, then \ccc{g()} + is only evaluated when \ccc{f()} returns \ccc{true}. One could have a dependency so + that \ccc{g()} has an internal precondition that implies that \ccc{f()} returns true. + The overloaded operators for user-defined types do not provide this short-circuiting + property, and so, if the overloaded operators where provided, then \ccc{g()} would + be evaluated, no matter the result of \ccc{f()}, which could lead to an unwanted + situation. The $\&$ and $|$ operators do not have this short-circuiting property, + and are therefore overloaded safely. + + %% +-----------------------------------+ + \ccHeading{Overloaded operators and functions for \ccc{Uncertain} only} + + \ccFunction{template + Uncertain operator<(Uncertain u, Uncertain v);} + {returns the extension of the less-than operator over \ccc{u} and \ccc{v}.} + + \ccFunction{template + Uncertain operator<(Uncertain u, T v);} + {returns \ccc{u < make_uncertain(v)}.} + + \ccFunction{template + Uncertain operator<(T u, Uncertain v);} + {returns \ccc{make_uncertain(u) < v}.} + + \ccFunction{template + Uncertain operator>(Uncertain u, Uncertain v);} + {returns the extension of the greater-than operator over \ccc{u} and \ccc{v}.} + + \ccFunction{template + Uncertain operator>(Uncertain u, T v);} + {returns \ccc{u > make_uncertain(v)}.} + + \ccFunction{template + Uncertain operator>(T u, Uncertain v);} + {returns \ccc{make_uncertain(u) > v}.} + + \ccFunction{template + Uncertain operator<=(Uncertain u, Uncertain v);} + {returns the extension of the less-than or equal operator over \ccc{u} and \ccc{v}.} + + \ccFunction{template + Uncertain operator<=(Uncertain u, T v);} + {returns \ccc{u <= make_uncertain(v)}.} + + \ccFunction{template + Uncertain operator<=(T u, Uncertain v);} + {returns \ccc{make_uncertain(u) <= v}.} + + \ccFunction{template + Uncertain operator>=(Uncertain u, Uncertain v);} + {returns the extension of the greater-than or equal operator over \ccc{u} and \ccc{v}.} + + \ccFunction{template + Uncertain operator>=(Uncertain u, T v);} + {returns \ccc{u > make_uncertain(v)}.} + + \ccFunction{template + Uncertain operator>=(T u, Uncertain v);} + {returns \ccc{make_uncertain(u) >= v}.} + + \ccFunction{template + Uncertain operator*(Uncertain u, Uncertain v);} + {returns the extension of the multiplication operator over \ccc{u} and \ccc{v}. + This requires \ccc{T} to have a multiplication operator as well.} + + \ccFunction{template + Uncertain operator*(Uncertain u, T v);} + {returns \ccc{u * make_uncertain(v)}.} + + \ccFunction{template + Uncertain operator<(T u, Uncertain v);} + {returns \ccc{make_uncertain(u) * v}.} + + \ccFunction{template + Uncertain operator-(Uncertain u);} + {returns the extension of the unary minus operator over \ccc{u}.} + + \ccFunction{template + Uncertain enum_cast(Uncertain u);} + {returns the extension of the \ccc{enum_cast} function over \ccc{u}.} + + %% +-----------------------------------+ + \ccHeading{Other free functions for \ccc{Uncertain}} + + \ccFunction{bool certainly(Uncertain u);} + {returns \ccc{true} iff \ccVar.\ccc{is_certain()}, and the \ccVar.\ccc{make_certain}() + returns \ccc{true}.} + + \ccFunction{bool certainly(bool u);} + {returns \ccc{u}.} + + \ccFunction{bool possibly(Uncertain u);} + {returns \ccc{true} iff \ccVar.\ccc{is_certain()} returns \ccc{false}, or if + \ccVar.\ccc{make_certain}() returns \ccc{true}.} + + \ccFunction{bool possibly(bool u);} + {returns \ccc{u}.} + + +\ccSeeAlso +\ccc{CGAL::Interval_nt} + +\end{ccRefClass} + +\ccParDims diff --git a/STL_Extension/doc_tex/STL_Extension_ref/intro.tex b/STL_Extension/doc_tex/STL_Extension_ref/intro.tex index 8eac2e25f7b..1fc4283cc2e 100644 --- a/STL_Extension/doc_tex/STL_Extension_ref/intro.tex +++ b/STL_Extension/doc_tex/STL_Extension_ref/intro.tex @@ -113,5 +113,6 @@ \ccRefIdfierPage{CGAL::Tag_true}\\ \ccRefIdfierPage{CGAL::Tag_false}\\ \ccRefIdfierPage{CGAL::Null_tag}\\ -\ccRefIdfierPage{CGAL::Null_functor} +\ccRefIdfierPage{CGAL::Null_functor}\\ +\ccRefIdfierPage{CGAL::Uncertain} %% EOF diff --git a/STL_Extension/doc_tex/STL_Extension_ref/main.tex b/STL_Extension/doc_tex/STL_Extension_ref/main.tex index 8a2b44ecc23..e8d4a123c64 100644 --- a/STL_Extension/doc_tex/STL_Extension_ref/main.tex +++ b/STL_Extension/doc_tex/STL_Extension_ref/main.tex @@ -32,6 +32,7 @@ \input{STL_Extension_ref/multiset.tex} \input{STL_Extension_ref/Object.tex} \input{STL_Extension_ref/stl_extension.tex} +\input{STL_Extension_ref/Uncertain.tex} %%\cgalColumnLayout diff --git a/STL_Extension/include/CGAL/Uncertain.h b/STL_Extension/include/CGAL/Uncertain.h index 99133df0c31..b9080cfe192 100644 --- a/STL_Extension/include/CGAL/Uncertain.h +++ b/STL_Extension/include/CGAL/Uncertain.h @@ -21,6 +21,7 @@ #define CGAL_UNCERTAIN_H #include +#include #include #include @@ -76,8 +77,8 @@ public: }; -// Encodes an interval [min;max] of values of type T. -// The primary template is supposed to work for enums and bool. +// Encodes a range [inf,sup] of values of type T. +// T can be enums or bool. template < typename T > class Uncertain @@ -88,10 +89,10 @@ class Uncertain public: - typedef CGAL::Uncertain_conversion_exception Uncertain_conversion_exception; - typedef T value_type; + typedef CGAL::Uncertain_conversion_exception Uncertain_conversion_exception; + Uncertain() : _i(CGALi::Minmax_traits::min), _s(CGALi::Minmax_traits::max) {} @@ -100,12 +101,12 @@ public: : _i(t), _s(t) {} Uncertain(T i, T s) - : _i(i), _s(s) {} + : _i(i), _s(s) { CGAL_precondition(i <= s); } Uncertain& operator=(T t) { _i = _s = t; - return this; + return *this; } T inf() const { return _i; } @@ -173,13 +174,6 @@ T sup(Uncertain i) } -// possibly() declarations (needed as used in the assertions) -// ---------------------------------------------------------- - -inline bool possibly(bool b); -inline bool possibly(Uncertain c); - - // Basic functions // --------------- diff --git a/STL_Extension/include/CGAL/assertions.h b/STL_Extension/include/CGAL/assertions.h index b7a268afb2a..ac1335ad11f 100644 --- a/STL_Extension/include/CGAL/assertions.h +++ b/STL_Extension/include/CGAL/assertions.h @@ -47,6 +47,13 @@ void postcondition_fail ( const char*, const char*, int, const char* = ""); void warning_fail( const char*, const char*, int, const char* = ""); +// The following declarations are needed first, before assertions are used. +// --------------------------------------------------------------------- +template < typename T > class Uncertain; +inline bool possibly(bool b); +inline bool possibly(Uncertain c); + + // macro definitions // ================= // assertions diff --git a/STL_Extension/test/STL_Extension/test_Uncertain.cpp b/STL_Extension/test/STL_Extension/test_Uncertain.cpp new file mode 100644 index 00000000000..32f9e7692ad --- /dev/null +++ b/STL_Extension/test/STL_Extension/test_Uncertain.cpp @@ -0,0 +1,268 @@ +// Sylvain Pion, 2008. + +#include +#include +#include +#include +#include + +// "unused variable" warning killer +template +void use(T) {} + +// generic test , for both enums and bool +template < typename T > +void test() +{ + std::cout << "Testing Uncertain\n"; + + typedef CGAL::Uncertain U; + + // Nested types. + typename U::value_type t = T(); + typename U::Uncertain_conversion_exception e = CGAL::Uncertain_conversion_exception(""); + + // Constructors, assignment. + const T t0 = static_cast(0); + const U u; + const U v = t0; + U w = U (T(), T()); + U v2 = u; + w = (w = t0); + + // Various functions + t = u.inf(); + t = u.sup(); + + assert(! u.is_certain()); + assert( v.is_certain()); + assert(t0 == v.make_certain()); + + T conv = v; + assert(conv == t0); + + U indet = U::indeterminate(); + + t = CGAL::inf(u); + t = CGAL::sup(u); + + assert(! CGAL::is_certain(u)); + assert( CGAL::is_certain(v)); + assert( CGAL::is_certain(t0)); + assert( CGAL::is_indeterminate(u)); + assert(! CGAL::is_indeterminate(v)); + assert(! CGAL::is_indeterminate(t0)); + assert(t0 == CGAL::get_certain(t0)); + assert(t0 == CGAL::get_certain(v)); + assert(t0 == CGAL::make_certain(t0)); + assert(t0 == CGAL::make_certain(v)); + + // Exceptions + bool ok = false; + try { CGAL::get_certain(u); } + catch (CGAL::Assertion_exception) { ok = true; } + assert(ok); + ok = false; + try { CGAL::make_certain(u); T t = u; use(t); } + catch (CGAL::Uncertain_conversion_exception) { ok = true; } + assert(ok); + + U u2 = CGAL::make_uncertain(u); + U u3 = CGAL::make_uncertain(T()); + + // Operators + assert( v == v ); + assert( v == t0 ); + assert( t0 == v ); + assert( ! (v != v) ); + assert( ! (v != t0) ); + assert( ! (t0 != v) ); + + use(t); +} + + +// test only for enums +template < typename T > +void test_enum() +{ + std::cout << "Testing Uncertain\n"; + + test(); // generic test + + typedef CGAL::Uncertain U; + + T n = static_cast(-1); + T z = static_cast(0); + T p = static_cast(1); + + U indet; + + // <, <=, >, >= + assert(U(n) < U(z)); + assert(U(z) < U(p)); + assert(U(n) < z); + assert(n < U(z)); + assert(! CGAL::is_certain(indet < z)); + + assert(U(n) <= U(z)); + assert(U(z) <= U(p)); + assert(U(z) <= U(z)); + assert(U(n) <= z); + assert(U(n) <= n); + assert(n <= U(z)); + assert(z <= U(z)); + assert(! CGAL::is_certain(indet <= z)); + assert(! CGAL::is_certain(indet <= indet)); + + assert(U(z) > U(n)); + assert(U(p) > U(z)); + assert(U(z) > n); + assert(z > U(n)); + assert(! CGAL::is_certain(z > indet)); + + assert(U(z) >= U(n)); + assert(U(p) >= U(z)); + assert(U(z) >= U(z)); + assert(U(z) >= n); + assert(U(n) >= n); + assert(z >= U(n)); + assert(z >= U(z)); + assert(! CGAL::is_certain(z >= indet)); + assert(! CGAL::is_certain(indet >= indet)); + + assert(-p == n); + assert(-n == p); + assert(-z == z); +} + +// test only for enums with multiplication operator +template < typename T > +void test_mult_enum() +{ + std::cout << "Testing Uncertain\n"; + + test_enum(); // generic enum test. + + typedef CGAL::Uncertain U; + + T n = static_cast(-1); + T z = static_cast(0); + T p = static_cast(1); + + U indet; + + assert(n*z == z); + assert(z*n == z); + assert(z*z == z); + assert(p*z == z); + assert(z*p == z); + assert(n*n == p); + assert(p*p == p); + assert(n*p == n); + assert(indet*z == z); + assert(z*indet == z); + assert(CGAL::is_indeterminate(p*indet)); + assert(CGAL::is_indeterminate(n*indet)); +} + + +// test only for bool +void test_bool() +{ + std::cout << "Testing Uncertain\n"; + + test(); // generic test + + typedef CGAL::Uncertain U; + + U utrue = true; + U ufalse = false; + U indet; + + assert(utrue); + assert(!ufalse); + assert(ufalse == !utrue); + assert(utrue != !utrue); + assert(false == !utrue); + assert(true != !utrue); + + assert(utrue | utrue); + assert(utrue | ufalse); + assert(ufalse | utrue); + assert(! (ufalse | ufalse)); + assert(utrue | true); + assert(utrue | false); + assert(ufalse | true); + assert(! (ufalse | false)); + assert(true | utrue); + assert(true | ufalse); + assert(false | utrue); + assert(! (false | ufalse)); + + assert(utrue & utrue); + assert(! (utrue & ufalse)); + assert(! (ufalse & utrue)); + assert(! (ufalse & ufalse)); + assert(utrue & true); + assert(! (utrue & false)); + assert(! (ufalse & true)); + assert(! (ufalse & false)); + assert(true & utrue); + assert(! (true & ufalse)); + assert(! (false & utrue)); + assert(! (false & ufalse)); + + // Test exceptions + bool ok = false; + try { bool b = indet; use(b); } + catch (CGAL::Uncertain_conversion_exception) { ok = true; } + assert(ok); + // The following must throw. + ok = false; + try { U u = indet && utrue; u = indet || ufalse; } + catch (CGAL::Uncertain_conversion_exception) { ok = true; } + assert(ok); + // The following must not throw. + try { bool b = utrue; b = ufalse; } + catch (CGAL::Uncertain_conversion_exception) { assert(false); } + + // certainly, possibly + assert(CGAL::certainly(true)); + assert(CGAL::certainly(utrue)); + assert(!CGAL::certainly(indet)); + assert(!CGAL::certainly(false)); + assert(!CGAL::certainly(ufalse)); + + assert(CGAL::possibly(true)); + assert(CGAL::possibly(utrue)); + assert(CGAL::possibly(indet)); + assert(!CGAL::possibly(false)); + assert(!CGAL::possibly(ufalse)); +} + +void test_enum_cast() +{ + typedef CGAL::Uncertain Us; + typedef CGAL::Uncertain Ub; + typedef CGAL::Uncertain Ua; + + Us s; + Ub b = CGAL::enum_cast(s); + Ua a = CGAL::enum_cast(s); + s = CGAL::enum_cast(b); +} + +int main() +{ + test_bool(); + test_mult_enum(); + test_mult_enum(); + test_mult_enum(); + test_mult_enum(); + test_enum(); + test_enum(); + test_enum_cast(); + + return 0; +}