Add CGAL_AND() and CGAL_OR() macros, which do the same as && and || but propagate Uncertain-ty.

(for compilers that support statement expressions, like GCC).

Add Uncertain::is_same() to help in the test-suite.
This commit is contained in:
Sylvain Pion 2008-08-12 10:50:39 +00:00
parent 74514a0fc7
commit 449195eb9d
3 changed files with 90 additions and 0 deletions

View File

@ -90,6 +90,9 @@ Finally, note that this class has some common points with \ccc{boost::tribool}.
%% +-----------------------------------+ %% +-----------------------------------+
\ccHeading{Access Functions} \ccHeading{Access Functions}
The following functions are meant to be used very rarely, they provide ways to inspect
the content of an \ccc{Uncertain<T>} object.
% \def\ccTagRmTrailingConst{\ccFalse} % \def\ccTagRmTrailingConst{\ccFalse}
\ccMethod{T inf() const;} \ccMethod{T inf() const;}
{returns the lower bound of the range represented by~\ccVar.} {returns the lower bound of the range represented by~\ccVar.}
@ -97,6 +100,9 @@ Finally, note that this class has some common points with \ccc{boost::tribool}.
\ccGlue\ccMethod{T sup() const;} \ccGlue\ccMethod{T sup() const;}
{returns the upper bound of the range represented by~\ccVar.} {returns the upper bound of the range represented by~\ccVar.}
\ccGlue\ccMethod{bool is_same(Uncertain u) const;}
{returns true whether \ccVar\ and \ccc{u} are the same range (equality as sets).}
%% +-----------------------------------+ %% +-----------------------------------+
\ccHeading{Uncertainty testing and conversion} \ccHeading{Uncertainty testing and conversion}
@ -295,6 +301,26 @@ Another option is :
This ensures that the first expression is not evaluated twice, and that the second is This ensures that the first expression is not evaluated twice, and that the second is
evaluated only if needed. evaluated only if needed.
This behavior can also be emulated through the use of macros, but only using
non-standard features ("statement expressions", such as provided by GCC). The
macros \ccc{CGAL_AND} and \ccc{CGAL_OR} are provided that perform the lazy
evaluation of these logical operations. On compilers that do not support
statement expressions, the macros simply expand to the $\&\&$ and $||$
operators (which will throw an exception instead of propagating the uncertainty).
\begin{ccExampleCode}
// Logical AND
Uncertain<bool> res = CGAL_AND( p.x() == 0 , p.y() == 0 );
... // Use res
// Logical OR
Uncertain<bool> res = CGAL_OR( q.x() == 0 , q.y() == 0 );
... // Use res
\end{ccExampleCode}
%% +-----------------------------------+ %% +-----------------------------------+
\ccHeading{Overloaded operators and functions for \ccc{Uncertain<enum T>} only} \ccHeading{Overloaded operators and functions for \ccc{Uncertain<enum T>} only}

View File

@ -111,6 +111,8 @@ public:
T inf() const { return _i; } T inf() const { return _i; }
T sup() const { return _s; } T sup() const { return _s; }
bool is_same(Uncertain u) const { return _i == u._i && _s == u._s; }
bool is_certain() const { return _i == _s; } bool is_certain() const { return _i == _s; }
T make_certain() const T make_certain() const
@ -306,6 +308,23 @@ Uncertain<bool> operator&(Uncertain<bool> a, bool b)
return Uncertain<bool>(a.inf() & b, a.sup() & b); return Uncertain<bool>(a.inf() & b, a.sup() & b);
} }
// operator&& and operator|| are not provided because, unless their bool counterpart,
// they lack the "short-circuiting" property.
// We provide macros CGAL_AND and CGAL_OR, which attempt to emulate their behavior.
// Key things : do not evaluate expressions twice, and evaluate the right hand side
// expression only when needed.
#ifdef CGAL_CFG_NO_STATEMENT_EXPRESSIONS
# define CGAL_AND(X, Y) ((X) && (Y))
# define CGAL_OR(X, Y) ((X) || (Y))
#else
# define CGAL_AND(X, Y) \
({ CGAL::Uncertain<bool> CGAL_TMP = (X); \
CGAL::certainly_not(CGAL_TMP) ? CGAL::make_uncertain(false) : CGAL_TMP & (Y); })
# define CGAL_OR(X, Y) \
({ CGAL::Uncertain<bool> CGAL_TMP = (X); \
CGAL::certainly(CGAL_TMP) ? CGAL::make_uncertain(true) : CGAL_TMP | (Y); })
#endif
// Equality operators // Equality operators

View File

@ -234,6 +234,51 @@ void test_bool()
bool_assert(! (false & utrue)); bool_assert(! (false & utrue));
bool_assert(! (false & ufalse)); bool_assert(! (false & ufalse));
bool_assert(!CGAL_AND(true, false));
bool_assert(!CGAL_AND(false, true));
bool_assert(CGAL_AND(true, true));
bool_assert(!CGAL_AND(false, false));
bool_assert(!CGAL_AND(utrue, ufalse));
bool_assert(!CGAL_AND(ufalse, utrue));
bool_assert(CGAL_AND(utrue, utrue));
bool_assert(!CGAL_AND(ufalse, ufalse));
bool_assert(CGAL_OR(true, false));
bool_assert(CGAL_OR(false, true));
bool_assert(CGAL_OR(true, true));
bool_assert(!CGAL_OR(false, false));
bool_assert(CGAL_OR(utrue, ufalse));
bool_assert(CGAL_OR(ufalse, utrue));
bool_assert(CGAL_OR(utrue, utrue));
bool_assert(!CGAL_OR(ufalse, ufalse));
try {
bool_assert( CGAL_AND(utrue, utrue));
bool_assert(!CGAL_AND(ufalse, ufalse));
bool_assert(!CGAL_AND(ufalse, utrue));
bool_assert(!CGAL_AND(utrue, ufalse));
bool_assert(indet.is_same(CGAL_AND(indet, indet)));
bool_assert(indet.is_same(CGAL_AND(utrue, indet)));
bool_assert(indet.is_same(CGAL_AND(indet, utrue)));
bool_assert(!CGAL_AND(ufalse, indet));
bool_assert(!CGAL_AND(indet, ufalse));
bool_assert( CGAL_OR(utrue, utrue));
bool_assert(!CGAL_OR(ufalse, ufalse));
bool_assert( CGAL_OR(ufalse, utrue));
bool_assert( CGAL_OR(utrue, ufalse));
bool_assert(indet.is_same(CGAL_OR(indet, indet)));
bool_assert( CGAL_OR(utrue, indet));
bool_assert( CGAL_OR(indet, utrue));
bool_assert(indet.is_same(CGAL_OR(ufalse, indet)));
bool_assert(indet.is_same(CGAL_OR(indet, ufalse)));
} catch (CGAL::Uncertain_conversion_exception) {
#ifndef CGAL_CFG_NO_STATEMENT_EXPRESSIONS
std::abort();
#endif
}
// Test exceptions // Test exceptions
bool ok = false; bool ok = false;
try { bool b = indet; use(b); } try { bool b = indet; use(b); }