cgal/STL_Extension/test/STL_Extension/test_Uncertain.cpp

370 lines
11 KiB
C++

// Sylvain Pion, 2008.
#include <CGAL/Uncertain.h>
#include <cassert>
#include <iostream>
#include <CGAL/enum.h>
#include <CGAL/exceptions.h>
#include <CGAL/use.h>
// The assert() macro, e.g. on Leopard, requires an int (due to the use of builtin_expect()).
// So I cast to bool manually (needed when the automatic conversion is switched off).
#define bool_assert(X) assert(bool(X))
// 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 T t2 = CGAL::indeterminate<T>();
const U u = U::indeterminate();
const U uuu = CGAL::indeterminate<U>();
const U uu;
const U v = t0;
U w = U (T(), T());
U v2 = u;
CGAL_USE(v2);
w = (w = t0);
// Various functions
t = u.inf();
t = u.sup();
bool_assert(! u.is_certain());
bool_assert( uu.is_certain());
bool_assert( v.is_certain());
bool_assert(t0 == v.make_certain());
#ifndef CGAL_NO_UNCERTAIN_CONVERSION_OPERATOR
T conv = v;
bool_assert(conv == t0);
#endif
U indet = U::indeterminate();
CGAL_USE(indet);
t = CGAL::inf(u);
t = CGAL::sup(u);
bool_assert(! CGAL::is_certain(u));
bool_assert( CGAL::is_certain(v));
bool_assert( CGAL::is_certain(t0));
bool_assert( CGAL::is_indeterminate(u));
bool_assert( CGAL::is_indeterminate(uuu));
bool_assert(! CGAL::is_indeterminate(v));
bool_assert(! CGAL::is_indeterminate(t0));
bool_assert(t0 == CGAL::get_certain(t0));
bool_assert(t0 == CGAL::get_certain(v));
bool_assert(t0 == CGAL::make_certain(t0));
bool_assert(t0 == CGAL::make_certain(v));
// Exceptions
bool ok = true;
// It is important to let that protection with CGAL_assertion_code,
// because the following test checks that
// CGAL::get_certain(Uncertain) does throw an assertion, *but if
// CGAL_NDEBUG is set*.
// -- Laurent Rineau, 2013/03/26
CGAL_assertion_code( ok = false );
try { CGAL::get_certain(u); }
catch (CGAL::Assertion_exception&) { ok = true; }
bool_assert(ok);
ok = false;
try {
CGAL::make_certain(u);
#ifndef CGAL_NO_UNCERTAIN_CONVERSION_OPERATOR
T t = u;
CGAL_USE(t);
#endif
}
catch (CGAL::Uncertain_conversion_exception&) { ok = true; }
bool_assert(ok);
U u2 = CGAL::make_uncertain(u);
U u3 = CGAL::make_uncertain(T());
CGAL_USE(u2);
CGAL_USE(u3);
// Operators
bool_assert( v == v );
bool_assert( v == t0 );
bool_assert( t0 == v );
bool_assert( ! (v != v) );
bool_assert( ! (v != t0) );
bool_assert( ! (t0 != v) );
CGAL_USE(t);
CGAL_USE(t2);
}
// 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 = U::indeterminate();
// <, <=, >, >=
bool_assert(U(n) < U(z));
bool_assert(U(z) < U(p));
bool_assert(U(n) < z);
bool_assert(n < U(z));
bool_assert(! CGAL::is_certain(indet < z));
bool_assert(U(n) <= U(z));
bool_assert(U(z) <= U(p));
bool_assert(U(z) <= U(z));
bool_assert(U(n) <= z);
bool_assert(U(n) <= n);
bool_assert(n <= U(z));
bool_assert(z <= U(z));
bool_assert(! CGAL::is_certain(indet <= z));
bool_assert(! CGAL::is_certain(indet <= indet));
bool_assert(U(z) > U(n));
bool_assert(U(p) > U(z));
bool_assert(U(z) > n);
bool_assert(z > U(n));
bool_assert(! CGAL::is_certain(z > indet));
bool_assert(U(z) >= U(n));
bool_assert(U(p) >= U(z));
bool_assert(U(z) >= U(z));
bool_assert(U(z) >= n);
bool_assert(U(n) >= n);
bool_assert(z >= U(n));
bool_assert(z >= U(z));
bool_assert(! CGAL::is_certain(z >= indet));
bool_assert(! CGAL::is_certain(indet >= indet));
bool_assert(-p == n);
bool_assert(-n == p);
bool_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 = U::indeterminate();
bool_assert(n*z == z);
bool_assert(z*n == z);
bool_assert(z*z == z);
bool_assert(p*z == z);
bool_assert(z*p == z);
bool_assert(n*n == p);
bool_assert(p*p == p);
bool_assert(n*p == n);
bool_assert(indet*z == z);
bool_assert(z*indet == z);
bool_assert(CGAL::is_indeterminate(p*indet));
bool_assert(CGAL::is_indeterminate(n*indet));
}
template <typename T>
void error_on_bool(T) {}
void error_on_bool(bool) { abort(); }
// 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 = U::indeterminate();
bool_assert(utrue);
bool_assert(!ufalse);
bool_assert(ufalse == !utrue);
bool_assert(utrue != !utrue);
bool_assert(false == !utrue);
bool_assert(true != !utrue);
bool_assert(utrue | utrue);
bool_assert(utrue | ufalse);
bool_assert(ufalse | utrue);
bool_assert(! (ufalse | ufalse));
bool_assert(utrue | true);
bool_assert(utrue | false);
bool_assert(ufalse | true);
bool_assert(! (ufalse | false));
bool_assert(true | utrue);
bool_assert(true | ufalse);
bool_assert(false | utrue);
bool_assert(! (false | ufalse));
bool_assert(utrue & utrue);
bool_assert(! (utrue & ufalse));
bool_assert(! (ufalse & utrue));
bool_assert(! (ufalse & ufalse));
bool_assert(utrue & true);
bool_assert(! (utrue & false));
bool_assert(! (ufalse & true));
bool_assert(! (ufalse & false));
bool_assert(true & utrue);
bool_assert(! (true & ufalse));
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_AND_3(true, true, true));
bool_assert(!CGAL_AND_3(true, false, true));
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));
bool_assert(CGAL_OR_3(false, false, true));
bool_assert(!CGAL_OR_3(false, false, false));
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&) {
std::abort();
}
// Test exceptions
bool ok = false;
try { bool b = indet; CGAL_USE(b); }
catch (CGAL::Uncertain_conversion_exception&) { ok = true; }
bool_assert(ok);
// The following must throw.
ok = false;
try { U u = indet && utrue; u = indet || ufalse; }
catch (CGAL::Uncertain_conversion_exception&) { ok = true; }
bool_assert(ok);
// The following must not throw.
try { bool b = utrue; b = ufalse; CGAL_USE(b); }
catch (CGAL::Uncertain_conversion_exception&) { bool_assert(false); }
// certainly, possibly
bool_assert(CGAL::certainly(true));
bool_assert(CGAL::certainly(utrue));
bool_assert(!CGAL::certainly(indet));
bool_assert(!CGAL::certainly(false));
bool_assert(!CGAL::certainly(ufalse));
bool_assert(CGAL::possibly(true));
bool_assert(CGAL::possibly(utrue));
bool_assert(CGAL::possibly(indet));
bool_assert(!CGAL::possibly(false));
bool_assert(!CGAL::possibly(ufalse));
bool_assert(!CGAL::certainly_not(true));
bool_assert(!CGAL::certainly_not(utrue));
bool_assert(!CGAL::certainly_not(indet));
bool_assert(CGAL::certainly_not(false));
bool_assert(CGAL::certainly_not(ufalse));
bool_assert(!CGAL::possibly_not(true));
bool_assert(!CGAL::possibly_not(utrue));
bool_assert(CGAL::possibly_not(indet));
bool_assert(CGAL::possibly_not(false));
bool_assert(CGAL::possibly_not(ufalse));
// conversion
error_on_bool(0 ? CGAL::make_uncertain(true) : indet);
// error_on_bool(0 ? true : indet); // fails due to the 2 possible conversions
}
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);
CGAL_USE(a);
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;
}