Add documentation and test-suite for CGAL::Uncertain.

Some other fixes.
This commit is contained in:
Sylvain Pion 2008-07-30 16:34:14 +00:00
parent 2da32b8ba8
commit 9ae3ea91b7
8 changed files with 634 additions and 15 deletions

2
.gitattributes vendored
View File

@ -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

View File

@ -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<T>} 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<T>}
allows just that. It also provides functions to naturally extend the
Boolean operations for \ccc{Uncertain<bool>} for example.
\ccc{Uncertain<T>} 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.

View File

@ -0,0 +1,326 @@
%% =============================================================================
%% The CGAL Reference Manual
%% Chapter: STL Extensions - The Reference Part
%% -----------------------------------------------------------------------------
%% author: Sylvain Pion
%% -----------------------------------------------------------------------------
%% $Id: $
%% $URL: $
%% =============================================================================
%% +=========================================================================+
\begin{ccRefClass}{Uncertain<T>}
\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<T>} allows
just that.
\ccc{Uncertain<T>} 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<bool>} for example, or the operations on
enumeration types.
\ccc{Uncertain<T>} 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<bool>} 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<T>}{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<T> Uncertain<T>::indeterminate();}
{returns an indeterminate range, like the default constructor.}
%% +-----------------------------------+
\ccHeading{Free functions}
\ccFunction{template <class T> T inf(Uncertain<T> u);}
{returns \ccc{u.inf()}.}
\ccFunction{template <class T> T sup(Uncertain<T> u);}
{returns \ccc{u.sup()}.}
\ccFunction{template <class T> bool is_certain(T t);}
{returns \ccc{true}.}
\ccFunction{template <class T> bool is_certain(Uncertain<T> u);}
{returns \ccc{u}.\ccc{is_certain}().}
\ccFunction{template <class T> bool is_indeterminate(T u);}
{returns \ccc{false}.}
\ccFunction{template <class T> bool is_indeterminate(Uncertain<T> u);}
{returns \ccc{!is_certain(u)}.}
\ccFunction{template <class T> T get_certain(T t);}
{returns \ccc{t}.}
\ccFunction{template <class T> T get_certain(Uncertain<T> u);}
{returns \ccc{u}.\ccc{make_certain}(). \ccPrecond \ccc{u}.\ccc{is_certain}().}
\ccFunction{template <class T> T make_certain(T t);}
{returns \ccc{t}.}
\ccFunction{template <class T> T make_certain(Uncertain<T> u);}
{returns \ccc{u}.\ccc{make_certain}().}
\ccFunction{template <class T> Uncertain<T> make_uncertain(T t);}
{returns \ccc{Uncertain<T>(u)}.}
\ccFunction{template <class T> Uncertain<T> make_uncertain(Uncertain<T> 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 <class T>
Uncertain<bool> operator==(Uncertain<T> u, Uncertain<T> v);}
{returns the extension of the equality operator over \ccc{u} and \ccc{v}.}
\ccFunction{template <class T>
Uncertain<bool> operator==(Uncertain<T> u, T v);}
{returns \ccc{u == make_uncertain(v)}.}
\ccFunction{template <class T>
Uncertain<bool> operator==(T u, Uncertain<T> v);}
{returns \ccc{v == u}.}
\ccFunction{template <class T>
Uncertain<bool> operator!=(Uncertain<T> u, Uncertain<T> v);}
{returns the extension of the inequality operator over \ccc{u} and \ccc{v}.}
\ccFunction{template <class T>
Uncertain<bool> operator!=(Uncertain<T> u, T v);}
{returns \ccc{u != make_uncertain(v)}.}
\ccFunction{template <class T>
Uncertain<bool> operator!=(T u, Uncertain<T> v);}
{returns \ccc{v != u}.}
%% +-----------------------------------+
\ccHeading{Overloaded operators for \ccc{Uncertain<bool>} only}
\ccFunction{Uncertain<bool> operator!(Uncertain<bool> u);}
{returns the range containing the negated values of \ccc{u}.}
\ccFunction{Uncertain<bool> operator|(Uncertain<bool> u, Uncertain<bool> v);}
{returns the range containing the values computed as logical or from \ccc{u} and \ccc{v}.}
\ccFunction{Uncertain<bool> operator|(Uncertain<bool> u, bool v);}
{returns \ccc{u | make_uncertain(v)}.}
\ccFunction{Uncertain<bool> operator|(bool u, Uncertain<bool> v);}
{returns \ccc{v | u}.}
\ccFunction{Uncertain<bool> operator&(Uncertain<bool> u, Uncertain<bool> v);}
{returns the range containing the values computed as logical and from \ccc{u} and \ccc{v}.}
\ccFunction{Uncertain<bool> operator&(Uncertain<bool> u, bool v);}
{returns \ccc{u & make_uncertain(v)}.}
\ccFunction{Uncertain<bool> operator&(bool u, Uncertain<bool> 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<enum T>} only}
\ccFunction{template <class T>
Uncertain<bool> operator<(Uncertain<T> u, Uncertain<T> v);}
{returns the extension of the less-than operator over \ccc{u} and \ccc{v}.}
\ccFunction{template <class T>
Uncertain<bool> operator<(Uncertain<T> u, T v);}
{returns \ccc{u < make_uncertain(v)}.}
\ccFunction{template <class T>
Uncertain<bool> operator<(T u, Uncertain<T> v);}
{returns \ccc{make_uncertain(u) < v}.}
\ccFunction{template <class T>
Uncertain<bool> operator>(Uncertain<T> u, Uncertain<T> v);}
{returns the extension of the greater-than operator over \ccc{u} and \ccc{v}.}
\ccFunction{template <class T>
Uncertain<bool> operator>(Uncertain<T> u, T v);}
{returns \ccc{u > make_uncertain(v)}.}
\ccFunction{template <class T>
Uncertain<bool> operator>(T u, Uncertain<T> v);}
{returns \ccc{make_uncertain(u) > v}.}
\ccFunction{template <class T>
Uncertain<bool> operator<=(Uncertain<T> u, Uncertain<T> v);}
{returns the extension of the less-than or equal operator over \ccc{u} and \ccc{v}.}
\ccFunction{template <class T>
Uncertain<bool> operator<=(Uncertain<T> u, T v);}
{returns \ccc{u <= make_uncertain(v)}.}
\ccFunction{template <class T>
Uncertain<bool> operator<=(T u, Uncertain<T> v);}
{returns \ccc{make_uncertain(u) <= v}.}
\ccFunction{template <class T>
Uncertain<bool> operator>=(Uncertain<T> u, Uncertain<T> v);}
{returns the extension of the greater-than or equal operator over \ccc{u} and \ccc{v}.}
\ccFunction{template <class T>
Uncertain<bool> operator>=(Uncertain<T> u, T v);}
{returns \ccc{u > make_uncertain(v)}.}
\ccFunction{template <class T>
Uncertain<bool> operator>=(T u, Uncertain<T> v);}
{returns \ccc{make_uncertain(u) >= v}.}
\ccFunction{template <class T>
Uncertain<T> operator*(Uncertain<T> u, Uncertain<T> 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 <class T>
Uncertain<T> operator*(Uncertain<T> u, T v);}
{returns \ccc{u * make_uncertain(v)}.}
\ccFunction{template <class T>
Uncertain<T> operator<(T u, Uncertain<T> v);}
{returns \ccc{make_uncertain(u) * v}.}
\ccFunction{template <class T>
Uncertain<T> operator-(Uncertain<T> u);}
{returns the extension of the unary minus operator over \ccc{u}.}
\ccFunction{template <class T, class U>
Uncertain<T> enum_cast(Uncertain<U> u);}
{returns the extension of the \ccc{enum_cast<T>} function over \ccc{u}.}
%% +-----------------------------------+
\ccHeading{Other free functions for \ccc{Uncertain<bool>}}
\ccFunction{bool certainly(Uncertain<bool> 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<bool> 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<bool>}
\end{ccRefClass}
\ccParDims

View File

@ -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<T>}
%% EOF

View File

@ -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

View File

@ -21,6 +21,7 @@
#define CGAL_UNCERTAIN_H
#include <CGAL/config.h>
#include <CGAL/assertions.h>
#include <CGAL/enum.h>
#include <stdexcept>
@ -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<T>::min),
_s(CGALi::Minmax_traits<T>::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<T> i)
}
// possibly() declarations (needed as used in the assertions)
// ----------------------------------------------------------
inline bool possibly(bool b);
inline bool possibly(Uncertain<bool> c);
// Basic functions
// ---------------

View File

@ -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<bool> c);
// macro definitions
// =================
// assertions

View File

@ -0,0 +1,268 @@
// Sylvain Pion, 2008.
#include <CGAL/Uncertain.h>
#include <cassert>
#include <iostream>
#include <CGAL/enum.h>
#include <CGAL/exceptions.h>
// "unused variable" warning killer
template <typename T>
void use(T) {}
// generic test , for both enums and bool
template < typename T >
void test()
{
std::cout << "Testing Uncertain<T>\n";
typedef CGAL::Uncertain<T> 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<T>(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<enum>\n";
test<T>(); // generic test
typedef CGAL::Uncertain<T> U;
T n = static_cast<T>(-1);
T z = static_cast<T>(0);
T p = static_cast<T>(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<enum with operator*>\n";
test_enum<T>(); // generic enum test.
typedef CGAL::Uncertain<T> U;
T n = static_cast<T>(-1);
T z = static_cast<T>(0);
T p = static_cast<T>(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<bool>\n";
test<bool>(); // generic test
typedef CGAL::Uncertain<bool> 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<CGAL::Sign> Us;
typedef CGAL::Uncertain<CGAL::Bounded_side> Ub;
typedef CGAL::Uncertain<CGAL::Angle> Ua;
Us s;
Ub b = CGAL::enum_cast<CGAL::Bounded_side>(s);
Ua a = CGAL::enum_cast<CGAL::Angle>(s);
s = CGAL::enum_cast<CGAL::Sign>(b);
}
int main()
{
test_bool();
test_mult_enum<CGAL::Sign>();
test_mult_enum<CGAL::Comparison_result>();
test_mult_enum<CGAL::Orientation>();
test_mult_enum<CGAL::Oriented_side>();
test_enum<CGAL::Bounded_side>();
test_enum<CGAL::Angle>();
test_enum_cast();
return 0;
}