Comparisons

As was said before, the definition of the comparison operators induces a slight problem. There are many ways to define them, depending of the return type or the expected order. It is the reason why the meaning of the operators is not fixed once and for all.

The way the operators are defined could have been influenced by a policy, as it is already the case for the rounding and the checking. However, comparisons are more an external property of the the class rather than an internal one. They are meant to be locally modified, independantly of the type of the intervals.

The operators <, <=, >, >=, ==, != are defined each time; and like the arithmetic operators they can take an argument of the base type. However, due to technical limitations, this base type can only be the second argument; so the operators are unfortunately not fully symmetric. The return type is not always bool, since some interesting results can be achieved by using a tri-state return type. So here is the common signatures of the operators:

template<class T, class Policies1, class Policies2>
return_type operator== (const interval<T, Policies1>&, const interval<T, Policies2>&);

template<class T, class Policies>
return_type operator== (const interval<T, Policies>&, const T&);

vided comparisons

Default comparison

If nothing is specified, the meaning of the comparison operators are an extension of the operator on the base type. More precisely, if one of the argument is invalid or empty, an exception is thrown. If the arguments are valid, the following rules are applied to determine the result of [a,b] op [c,d] (just consider c == d if the second argument is of type T):

This comparison allows to replace base types by interval types without changing the meaning of a program. Indeed, if no exception is thrown, the result is the same as before; and if an exception is thrown, the previous comparison was unsure and should have been rewritten.

Other comparisons

The other comparisons are selected by using a namespace. These namespaces are located under boost::numeric::interval_lib::compare and are invoked by:

using namespace boost::numeric::interval_lib::compare::the_comparison_to_select;

After this line, the default meaning of the operators will have been replaced by the meaning located in the namespace. Please note that because of C++ lookup rules, it is not possible to use two namespaces one after another and they must be used in different block hierarchies. Otherwise the compiler will complain about ambiguous operators. To summarize:

// example 1: BAD
using namespace compare1;
...
using namespace compare2;
...

// example 2: GOOD
{ using namespace compare1;
  ...                       }
{ using namespace compare2;
  ...                       }

// example 3: BAD
using namespace compare1;
...
{ using namespace compare2;
  ...                       }

Now comes the list of the provided comparisons. They all are located in their respective header files under <boost/numeric/interval/compare/...>. And as for the default comparison, the operators will generally complain by throwing an exception if feed by invalid values.

Exception

namespace boost {
namespace numeric {
namespace interval_lib {

class comparison_error: std::runtime_error; // "boost::interval: uncertain comparison"

} // namespace interval_lib
} // namespace numeric
} // namespace boost

Explicit comparison functions

In some situation, you may want to perform direct comparisons on the bounds and avoid the indeterminate case that appears with default operators. Some functions are provided for this purpose. They expect their arguments to be valid and return a result after only one comparison. Their names are composed by cer (for "certain", if the default comparison is true, the result is true) or pos (for "possible", if the default comparison is false, the result is false) followed by lt, le, gt, ge, eq or ne. They are located in <boost/numeric/interval/compare/explicit.hpp>. Each of these functions takes two parameters and returns a boolean; the parameters are expected to be valid, undefined behavior may result otherwise. For example, the definition of the "certainly less than" comparison is:

namespace boost {
namespace numeric {
namespace interval_lib {

template<class T, class Policies1, class Policies2>
bool cerlt(const interval<T, Policies1>& x, const interval<T, Policies2>& y);

template<class T, class Policies>
bool cerlt(const interval<T, Policies>& x, const T& y);

template<class T, class Policies>
bool cerlt(const T& x, const interval<T, Policies>& y);

} // namespace interval_lib
} // namespace numeric
} // namespace boost

Revised: 2003-04-22
Copyright (c) Guillaume Melquiond, Sylvain Pion, Hervé Brönnimann, 2002. Polytechnic University.
Copyright (c) Guillaume Melquiond, 2003.