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}
|
\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}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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); }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue