mirror of https://github.com/CGAL/cgal
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:
parent
74514a0fc7
commit
449195eb9d
|
|
@ -90,6 +90,9 @@ Finally, note that this class has some common points with \ccc{boost::tribool}.
|
|||
%% +-----------------------------------+
|
||||
\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}
|
||||
\ccMethod{T inf() const;}
|
||||
{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;}
|
||||
{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}
|
||||
|
||||
|
|
@ -295,6 +301,26 @@ Another option is :
|
|||
This ensures that the first expression is not evaluated twice, and that the second is
|
||||
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}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,6 +111,8 @@ public:
|
|||
T inf() const { return _i; }
|
||||
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; }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
|
|
|
|||
|
|
@ -234,6 +234,51 @@ void test_bool()
|
|||
bool_assert(! (false & utrue));
|
||||
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
|
||||
bool ok = false;
|
||||
try { bool b = indet; use(b); }
|
||||
|
|
|
|||
Loading…
Reference in New Issue