mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-07-13 06:14:11 -04:00
Squashed 'boost/' content from commit b4feb19f2
git-subtree-dir: boost git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
@@ -0,0 +1,252 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Checking policies</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Checking policies</h1>
|
||||
|
||||
<p>A checking policy controls how the <code>interval</code> class will deal
|
||||
with special cases like: empty intervals, infinite numbers, invalid
|
||||
values.</p>
|
||||
|
||||
<p>For example, let's consider <code>operator+(interval, T)</code>. The
|
||||
second argument could be an invalid value (for a floating-point number, it
|
||||
is a NaN). What to do in such a case? First, we could say that the second
|
||||
argument can never be an invalid number. Second, we could also say such a
|
||||
situation can arise but is forbidden. Third, we could allow such values and
|
||||
generate an empty interval when encountered. And there is many other
|
||||
possibilities.</p>
|
||||
|
||||
<p>It is the reason why such a policy is used: there is a lot of
|
||||
interesting behaviors and it would be sad to arbitrarily select one of
|
||||
these.</p>
|
||||
|
||||
<h2>Requirements</h2>
|
||||
|
||||
<p>The checking class should satisfy the following requirement (in the form
|
||||
of an interface):</p>
|
||||
<pre>
|
||||
/* requirements for checking policy */
|
||||
struct checking
|
||||
{
|
||||
static T pos_inf();
|
||||
static T neg_inf();
|
||||
static T nan();
|
||||
static bool is_nan(const T&);
|
||||
static T empty_lower();
|
||||
static T empty_upper();
|
||||
static bool is_empty(const T&, const T&);
|
||||
};
|
||||
</pre>
|
||||
|
||||
<p>The first two functions, <code>pos_inf</code> and <code>neg_inf</code>,
|
||||
are invoked each time the library has to create the infinite bound of an
|
||||
interval. For example, <code>interval::whole</code> computes
|
||||
<code>interval(checking::neg_inf(), checking::pos_inf())</code>. If
|
||||
infinite values are allowed and
|
||||
<code>std::numeric_limits<T>::infinity()</code> returns a correct
|
||||
value, such a value can be used.</p>
|
||||
|
||||
<p>Next comes <code>nan</code>. This function is used each time a function
|
||||
need to return a value of type <code>T</code> but is unable to compute it.
|
||||
It only happens when one of the arguments of the function is invalid. For
|
||||
example, if you ask what the median value of an empty interval is,
|
||||
<code>nan</code> will be used. But please remember: <code>lower</code> and
|
||||
<code>upper</code> directly return the value stocked in the interval; so,
|
||||
if the interval is empty, <code>lower</code> will not answer
|
||||
<code>by</code> a call to <code>checking::nan</code> (but will return the
|
||||
same value than <code>checking::empty_lower</code> could return).</p>
|
||||
|
||||
<p><code>empty_lower</code> and <code>empty_upper</code> respectively
|
||||
return the lower and upper bound of the empty interval. There is no
|
||||
requirements for <code>empty_lower</code> and <code>empty_upper</code> to
|
||||
return the same value than <code>checking::nan</code>. For example, if the
|
||||
type <code>T</code> does not have any invalid value, the
|
||||
<code>empty_</code> functions can return the [1;0] interval.</p>
|
||||
|
||||
<p><code>is_nan</code> is used to test if a value of type <code>T</code> is
|
||||
invalid or not. <code>is_empty</code> tests if the interval formed by the
|
||||
two arguments is empty or not. Such tests will generally be at the
|
||||
beginning of each function which involves an argument of type
|
||||
<code>T</code>. If one of the inputs is declared invalid, the the function
|
||||
will try to produce an invalid value or an input interval.</p>
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
<pre>
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace interval_lib {
|
||||
|
||||
template<class T>
|
||||
struct checking_base;
|
||||
template<class T, class Checking = checking_base<T>, class Exception = exception_create_empty<T> >
|
||||
struct checking_no_empty;
|
||||
template<class T, class Checking = checking_base<T> >
|
||||
struct checking_no_nan;
|
||||
template<class T, class Checking = checking_base<T>, class Exception = exception_invalid_number<T> >
|
||||
struct checking_catch_nan;
|
||||
|
||||
template<class T> struct exception_create_empty { T operator()(); };
|
||||
template<class T> struct exception_invalid_number { void operator()(); };
|
||||
|
||||
} // namespace numeric
|
||||
} // namespace interval_lib
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2>Predefined classes</h2>
|
||||
|
||||
<p>In order to simplify the customization of the policy, some templates are
|
||||
already defined in the library.</p>
|
||||
|
||||
<p>First of all, there is <code>checking_base</code>. Thanks to the
|
||||
information provided by <code>std::numeric_limits<T></code>, this
|
||||
class is able to generate a base for the policy. If <code>T</code> has
|
||||
quiet NaNs (as said by <code>numeric_limits::has_quiet_NaN</code>), then
|
||||
the value is used for <code>nan</code>, <code>empty_lower</code>,
|
||||
<code>empty_upper</code>; and a basic test is used for <code>is_nan</code>
|
||||
(it is <code>x!=x</code>). If <code>T</code> does not have quiet NaNs, then
|
||||
<code>nan</code> is an <code>assert(false)</code>, the empty interval is
|
||||
[1,0], and <code>is_nan</code> always return <code>false</code>. As for
|
||||
<code>nan</code>, <code>pos_inf</code> returns
|
||||
<code>numeric_limits::infinity()</code> if possible, or is an
|
||||
<code>assert(false</code>) otherwise. <code>neg_inf</code> returns the
|
||||
opposite. Finally, <code>is_empty(T l,T u)</code> is always defined by
|
||||
<code>!(l<=u)</code>.</p>
|
||||
|
||||
<p>Next comes <code>checking_no_empty</code>. Using it means that each time
|
||||
an empty interval should be produced (by <code>empty_lower</code> and
|
||||
<code>empty_upper</code>), the function object given by the
|
||||
<code>Exception</code> argument of the template is invoked and the value it
|
||||
returns is propagated. So, if <code>Exception</code> is appropriately
|
||||
defined (for example it could throw an exception, hence the name of the
|
||||
argument), you can be sure no empty interval will ever be created. So
|
||||
<code>is_empty</code> will always return <code>false</code> (since there is
|
||||
no need to test for an empty interval). And as explained before, in that
|
||||
case we can also replace <code>nan</code> by an <code>assert(false)</code>;
|
||||
you will be sure no invalid number will ever be produced. If this template
|
||||
is not used, it implicitly means that all the functions can produce empty
|
||||
intervals and they correctly deal with empty interval arguments.</p>
|
||||
|
||||
<p>Finally there are <code>checking_no_nan</code> and
|
||||
<code>checking_catch_nan</code>. The first one expresses the functions of
|
||||
the library will never get an invalid number as argument. So
|
||||
<code>is_nan</code> will only return <code>false</code>. The other one
|
||||
means the arguments can be an invalid number but in that case,
|
||||
<code>is_nan</code> will call the function object <code>Exception</code>
|
||||
and return <code>false</code>. Indeed, this template means invalid numbers
|
||||
should never make their way through to the body of the function. If none of
|
||||
this two templates is used, it implicitly means that all the functions can
|
||||
get invalid number arguments and they will correctly deal with them.</p>
|
||||
|
||||
<p><code>exception_create_empty</code> throws
|
||||
<code>std::runtime_error</code> with the message <code>"boost::interval:
|
||||
empty interval created"</code> and <code>exception_invalid_number</code>
|
||||
throws <code>std::invalid_argument</code> with the message
|
||||
<code>"boost::interval: invalid number"</code>.</p>
|
||||
|
||||
<h2>Customizing your own checking policy</h2>
|
||||
|
||||
<p>In order to define a suitable policy, you need to correctly say what you
|
||||
expect from your interval class. First of all, are you interested in
|
||||
getting empty intervals at the end of a calculus? If you do not want to
|
||||
obtain empty intervals, <code>empty_lower</code> and
|
||||
<code>empty_upper</code> have to fail when invoked (they can throw an
|
||||
exception, set a flag, etc). However, if no function is able to produce an
|
||||
empty interval, it is no more necessary to do the test, so
|
||||
<code>is_empty</code> may always return <code>false</code>. In this case, a
|
||||
good compiler will do a lot of optimizations.</p>
|
||||
|
||||
<p>You could also be interested in getting empty intervals at the end of
|
||||
the calculus. For example, if you need to transform an array of unsure
|
||||
values (or intervals) in a new array of intervals, you may not want to stop
|
||||
the conversion at the first encountered problem. So
|
||||
<code>empty_lower</code> and <code>empty_upper</code> need to return
|
||||
suitable values in order to define an empty interval (you can use an upper
|
||||
bound which is not greater or equal than the lower bound for example); and
|
||||
<code>is_empty</code> must be able to distinguish empty intervals from the
|
||||
valid intervals.</p>
|
||||
|
||||
<p>Another important question is: is it possible that some base numbers
|
||||
(objects of type <code>T</code>) are invalid? And if it is possible, are
|
||||
they allowed or not ? If it is not possible, no test is necessary;
|
||||
<code>is_nan</code> may always return <code>false</code>. In this case too,
|
||||
a good compiler will do a lot of optimizations. If function arguments can
|
||||
hold invalid numbers, two cases must be considered according to whether
|
||||
they are allowed or not. If they are allowed, <code>is_nan</code> just has
|
||||
to test if they are invalid or not. If they are forbidden,
|
||||
<code>is_nan</code> should fail (exception, assert, etc.) when invoked on
|
||||
an invalid argument and return <code>false</code> otherwise. The value
|
||||
returned by <code>nan</code> does not have any interest since the interval
|
||||
functions are guaranteed not to produce invalid interval bounds unless the
|
||||
user passes invalid numbers to the constructors. So you can put an assert
|
||||
inside if you do not trust the library. :-)</p>
|
||||
|
||||
<p>And finally, you need to decide what to do with <code>nan</code> if it
|
||||
has not already been decided at the beginning, and with
|
||||
<code>pos_inf</code> and <code>neg_inf</code>. These functions should
|
||||
return a value or start an exceptional behavior (especially if the base
|
||||
type does not have corresponding values).</p>
|
||||
|
||||
<h2>Some examples</h2>
|
||||
|
||||
<ul>
|
||||
<li>If you need a checking policy that allows the library to correctly
|
||||
manipulate data, even if they contain invalid numbers and empty
|
||||
intervals, then <code>checking_base<T></code> is a
|
||||
possibility.</li>
|
||||
|
||||
<li>If you do not want empty intervals to be created and are not sure all
|
||||
the numbers are valid, then <code>checking_catch_nan<T,
|
||||
checking_no_empty<T> ></code> can help you.</li>
|
||||
|
||||
<li>If all the numbers will be valid and if no empty interval is supposed
|
||||
to be created (or if you do not want them to be created), then you can
|
||||
use <code>checking_no_nan<T, checking_no_empty<T> ></code>.
|
||||
Please note that if <code>T</code> does not have a way to represent
|
||||
invalid numbers, then this policy will behave the same way as
|
||||
<code>checking_no_empty<T></code>. This is the default policy and
|
||||
it is also called <code>interval_lib::checking_strict</code>.</li>
|
||||
|
||||
<li>If all numerical data are valid but the algorithm can produce and
|
||||
manipulate empty intervals, then <code>checking_no_nan<T></code>
|
||||
should be used.</li>
|
||||
|
||||
<li>Similarly, if invalid data have to be signaled and the algorithm can
|
||||
manipulate empty intervals, the <code>checking_catch_nan<T></code>
|
||||
is a solution.</li>
|
||||
|
||||
<li>If you do not mind having undefined results when an empty interval or
|
||||
an interval number is produced, your best bet is to create your own
|
||||
policy by overloading <code>checking_base</code> and modifying
|
||||
<code>is_nan</code> et <code>is_empty</code> in order for them to always
|
||||
return <code>false</code>. It is probably the fastest checking policy
|
||||
available; however, it suffers from its deficient security.</li>
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University<br>
|
||||
Copyright © 2003-2004 Guillaume Melquiond</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,204 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Comparisons</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Comparisons</h1>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>The operators <code><</code>, <code><=</code>, <code>></code>,
|
||||
<code>>=</code>, <code>==</code>, <code>!=</code> 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 <code>bool</code>, since some interesting
|
||||
results can be achieved by using a tri-state return type. So here is the
|
||||
common signatures of the operators:</p>
|
||||
<pre>
|
||||
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&);
|
||||
</pre>
|
||||
|
||||
<h2>vided comparisons</h2>
|
||||
|
||||
<h3>Default comparison</h3>
|
||||
|
||||
<p>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
|
||||
[<i>a</i>,<i>b</i>] <code>op</code> [<i>c</i>,<i>d</i>] (just consider
|
||||
<i>c</i> <code>==</code> <i>d</i> if the second argument is of type
|
||||
<code>T</code>):</p>
|
||||
|
||||
<ul>
|
||||
<li>if ∀ <i>x</i> ∈ [<i>a</i>,<i>b</i>] ∀ <i>y</i>
|
||||
∈ [<i>c</i>,<i>d</i>] <code>(</code><i>x</i> <code>op</code>
|
||||
y<code>)</code>, then <code>true</code></li>
|
||||
|
||||
<li>if ∀ <i>x</i> ∈ [<i>a</i>,<i>b</i>] ∀ <i>y</i>
|
||||
∈ [<i>c</i>,<i>d</i>] <code>!(</code><i>x</i> <code>op</code>
|
||||
y<code>)</code>, then <code>false</code></li>
|
||||
|
||||
<li>otherwise throw an exception.</li>
|
||||
</ul>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h3>Other comparisons</h3>
|
||||
|
||||
<p>The other comparisons are selected by using a namespace. These
|
||||
namespaces are located under
|
||||
<code>boost::numeric::interval_lib::compare</code> and are invoked by:</p>
|
||||
<pre>
|
||||
using namespace boost::numeric::interval_lib::compare::the_comparison_to_select;
|
||||
</pre>
|
||||
|
||||
<p>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:</p>
|
||||
<pre>
|
||||
// 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;
|
||||
... }
|
||||
</pre>
|
||||
|
||||
<p>Now comes the list of the provided comparisons. They all are located in
|
||||
their respective header files under
|
||||
<code><boost/numeric/interval/compare/...></code>. And as for the
|
||||
default comparison, the operators will generally complain by throwing an
|
||||
exception if feed by invalid values.</p>
|
||||
|
||||
<ul>
|
||||
<li><code>certain</code>: this comparison is equivalent to the default
|
||||
scheme with the exceptional case mapped to <code>false</code>. So these
|
||||
operators answer <code>true</code> only when the comparison is verified
|
||||
for all pairs of elements.</li>
|
||||
|
||||
<li><code>possible</code>: this time, the exceptional case is mapped to
|
||||
<code>true</code>. The operators answer <code>true</code> as soon as the
|
||||
comparison is verified for a pair of elements.<br></li>
|
||||
|
||||
<li><code>lexicographic</code>: the lexicographic order (the lower bounds
|
||||
are first compared, and if it is not enough to know the result, the upper
|
||||
bounds are then compared). This order does not have a meaning in interval
|
||||
arithmetic. However, since it is the natural total order on pair of
|
||||
(totally ordered) numbers, it may be handy in some cases.</li>
|
||||
|
||||
<li><code>set</code>: the set inclusion partial order. This time, an
|
||||
empty interval is not considered to be invalid (but an invalid number is
|
||||
still invalid). <code><=</code> and <code><</code> are the subset
|
||||
and proper subset relations; and <code>>=</code> and <code>></code>
|
||||
are the superset and proper superset relations.</li>
|
||||
|
||||
<li><code>tribool</code>: this comparison relies on the Boost tristate
|
||||
boolean library and changes the default operators so that an explicit
|
||||
indeterminate value is returned in the third case instead of throwing an
|
||||
exception.</li>
|
||||
</ul>
|
||||
|
||||
<h3>Exception</h3>
|
||||
<pre>
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace interval_lib {
|
||||
|
||||
class comparison_error: std::runtime_error; // "boost::interval: uncertain comparison"
|
||||
|
||||
} // namespace interval_lib
|
||||
} // namespace numeric
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2>Explicit comparison functions</h2>
|
||||
|
||||
<p>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 <code>cer</code> (for "certain", if the default
|
||||
comparison is true, the result is true) or <code>pos</code> (for
|
||||
"possible", if the default comparison is false, the result is false)
|
||||
followed by <code>lt</code>, <code>le</code>, <code>gt</code>,
|
||||
<code>ge</code>, <code>eq</code> or <code>ne</code>. They are located in
|
||||
<code><boost/numeric/interval/compare/explicit.hpp></code>. 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:</p>
|
||||
<pre>
|
||||
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
|
||||
</pre>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University<br>
|
||||
Copyright © 2003 Guillaume Melquiond</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,211 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Tests and Examples</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1>Tests and Examples</h1>
|
||||
|
||||
<h2>A first example</h2>
|
||||
|
||||
<p>This example shows how to design a function which takes a polynomial and
|
||||
a value and returns the sign of this polynomial at this point. This
|
||||
function is a filter: if the answer is not guaranteed, the functions says
|
||||
so. The reason of using a filter rather than a simple evaluation function
|
||||
is: computations with floating-point numbers will incur approximations and
|
||||
it can be enough to change the sign of the polynomial. So, in order to
|
||||
validate the result, the function will use interval arithmetic.</p>
|
||||
|
||||
<p>The first step is the inclusion of the appropriate headers. Because the
|
||||
function will handle floating-point bounds, the easiest solution is:</p>
|
||||
<pre>
|
||||
#include <boost/numeric/interval.hpp>
|
||||
</pre>
|
||||
|
||||
<p>Now, let's begin the function. The polynomial is given by the array of
|
||||
its coefficients and its size (strictly greater to its degree). In order to
|
||||
simplify the code, two namespaces of the library are included.</p>
|
||||
<pre>
|
||||
int sign_polynomial(double x, double P[], int sz) {
|
||||
using namespace boost::numeric;
|
||||
using namespace interval_lib;
|
||||
</pre>
|
||||
|
||||
<p>Then we can define the interval type. Since no special behavior is
|
||||
required, the default policies are enough:</p>
|
||||
<pre>
|
||||
typedef interval<double> I;
|
||||
</pre>
|
||||
|
||||
<p>For the evaluation, let's just use the Horner scheme with interval
|
||||
arithmetic. The library overloads all the arithmetic operators and provides
|
||||
mixed operations, so the only difference between the code with and without
|
||||
interval arithmetic lies in the type of the iterated value
|
||||
<code>y</code>:</p>
|
||||
<pre>
|
||||
I y = P[sz - 1];
|
||||
for(int i = sz - 2; i >= 0; i--)
|
||||
y = y * x + P[i];
|
||||
</pre>
|
||||
|
||||
<p>The last step is the computation of the sign of <code>y</code>. It is
|
||||
done by choosing an appropriate comparison scheme and then doing the
|
||||
comparison with the usual operators:</p>
|
||||
<pre>
|
||||
using namespace compare::certain;
|
||||
if (y > 0.) return 1;
|
||||
if (y < 0.) return -1;
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The answer <code>0</code> does not mean the polynomial is zero at this
|
||||
point. It only means the answer is not known since <code>y</code> contains
|
||||
zero and thus does not have a precise sign.</p>
|
||||
|
||||
<p>Now we have the expected function. However, due to the poor
|
||||
implementations of floating-point rounding in most of the processors, it
|
||||
can be useful to say to optimize the code; or rather, to let the library
|
||||
optimize it. The main condition for this optimization is that the interval
|
||||
code should not be mixed with floating-point code. In this example, it is
|
||||
the case, since all the operations done in the functions involve the
|
||||
library. So the code can be rewritten:</p>
|
||||
<pre>
|
||||
int sign_polynomial(double x, double P[], int sz) {
|
||||
using namespace boost::numeric;
|
||||
using namespace interval_lib;
|
||||
typedef interval<double> I_aux;
|
||||
|
||||
I_aux::traits_type::rounding rnd;
|
||||
typedef unprotect<I_aux>::type I;
|
||||
|
||||
I y = P[sz - 1];
|
||||
for(int i = sz - 2; i >= 0; i--)
|
||||
y = y * x + P[i];
|
||||
|
||||
using namespace compare::certain;
|
||||
if (y > 0.) return 1;
|
||||
if (y < 0.) return -1;
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The difference between this code and the previous is the use of another
|
||||
interval type. This new type <code>I</code> indicates to the library that
|
||||
all the computations can be done without caring for the rounding mode. And
|
||||
because of that, it is up to the function to care about it: a rounding
|
||||
object need to be alive whenever the optimized type is used.</p>
|
||||
|
||||
<h2>Other tests and examples</h2>
|
||||
|
||||
<p>In <code>libs/numeric/interval/test/</code> and
|
||||
<code>libs/numeric/interval/examples/</code> are some test and example
|
||||
programs.. The examples illustrate a few uses of intervals. For a general
|
||||
description and considerations on using this library, and some potential
|
||||
domains of application, please read this <a href=
|
||||
"guide.htm">mini-guide</a>.</p>
|
||||
|
||||
<h3>Tests</h3>
|
||||
|
||||
<p>The test programs are as follows. Please note that they require the use
|
||||
of the Boost.test library and can be automatically tested by using
|
||||
<code>bjam</code> (except for interval_test.cpp).</p>
|
||||
|
||||
<p><b>add.cpp</b> tests if the additive and subtractive operators and the
|
||||
respective _std and _opp rounding functions are correctly implemented. It
|
||||
is done by using symbolic expressions as a base type.</p>
|
||||
|
||||
<p><b>cmp.cpp</b>, <b>cmp_lex.cpp</b>, <b>cmp_set.cpp</b>, and
|
||||
<b>cmp_tribool.cpp</b> test if the operators <code><</code>
|
||||
<code>></code> <code><=</code> <code>>=</code> <code>==</code>
|
||||
<code>!=</code> behave correctly for the default, lexicographic, set, and
|
||||
tristate comparisons. <b>cmp_exp.cpp</b> tests the explicit comparison
|
||||
functions <code>cer..</code> and <code>pos..</code> behave correctly.
|
||||
<b>cmp_exn.cpp</b> tests if the various policies correctly detect
|
||||
exceptional cases. All these tests use some simple intervals ([1,2] and
|
||||
[3,4], [1,3] and [2,4], [1,2] and [2,3], etc).</p>
|
||||
|
||||
<p><b>det.cpp</b> tests if the <code>_std</code> and <code>_opp</code>
|
||||
versions in protected and unprotected mode produce the same result when
|
||||
Gauss scheme is used on an unstable matrix (in order to exercise rounding).
|
||||
The tests are done for <code>interval<float></code> and
|
||||
<code>interval<double></code>.</p>
|
||||
|
||||
<p><b>fmod.cpp</b> defines a minimalistic version of
|
||||
<code>interval<int></code> and uses it in order to test
|
||||
<code>fmod</code> on some specific interval values.</p>
|
||||
|
||||
<p><b>mul.cpp</b> exercises the multiplication, the finite division, the
|
||||
square and the square root with some integer intervals leading to exact
|
||||
results.</p>
|
||||
|
||||
<p><b>pi.cpp</b> tests if the interval value of π (for <code>int</code>,
|
||||
<code>float</code> and <code>double</code> base types) contains the number
|
||||
π (defined with 21 decimal digits) and if it is a subset of
|
||||
[π±1ulp] (in order to ensure some precision).</p>
|
||||
|
||||
<p><b>pow.cpp</b> tests if the <code>pow</code> function behaves correctly
|
||||
on some simple test cases.</p>
|
||||
|
||||
<p><b>test_float.cpp</b> exercises the arithmetic operations of the library
|
||||
for floating point base types.</p>
|
||||
|
||||
<p><b>interval_test.cpp</b> tests if the interval library respects the
|
||||
inclusion property of interval arithmetic by computing some functions and
|
||||
operations for both <code>double</code> and
|
||||
<code>interval<double></code>.</p>
|
||||
|
||||
<h2>Examples</h2>
|
||||
|
||||
<p><b>filter.cpp</b> contains filters for computational geometry able to
|
||||
find the sign of a determinant. This example is inspired by the article
|
||||
<em>Interval arithmetic yields efficient dynamic filters for computational
|
||||
geometry</em> by Brönnimann, Burnikel and Pion, 2001.</p>
|
||||
|
||||
<p><b>findroot_demo.cpp</b> finds zeros of some functions by using
|
||||
dichotomy and even produces gnuplot data for one of them. The processor has
|
||||
to correctly handle elementary functions for this example to properly
|
||||
work.</p>
|
||||
|
||||
<p><b>horner.cpp</b> is a really basic example of unprotecting the interval
|
||||
operations for a whole function (which computes the value of a polynomial
|
||||
by using Horner scheme).</p>
|
||||
|
||||
<p><b>io.cpp</b> shows some stream input and output operators for intervals
|
||||
.The wide variety of possibilities explains why the library do not
|
||||
implement i/o operators and they are left to the user.</p>
|
||||
|
||||
<p><b>newton-raphson.cpp</b> is an implementation of a specialized version
|
||||
of Newton-Raphson algorithm for finding the zeros of a function knowing its
|
||||
derivative. It exercises unprotecting, full division, some set operations
|
||||
and empty intervals.</p>
|
||||
|
||||
<p><b>transc.cpp</b> implements the transcendental part of the rounding
|
||||
policy for <code>double</code> by using an external library (the MPFR
|
||||
subset of GMP in this case).</p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University<br>
|
||||
Copyright © 2003 Guillaume Melquiond</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,122 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Choosing Your Own Interval Type</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1>Choosing Your Own Interval Type</h1>
|
||||
|
||||
<p>First of all, you need to select your base type. In order to obtain an
|
||||
useful interval type, the numbers should respect some requirements. Please
|
||||
refer to <a href="numbers.htm">this page</a> in order to see them. When
|
||||
your base type is robust enough, you can go to the next step: the choice of
|
||||
the policies.</p>
|
||||
|
||||
<p>As you should already know if you did not come to this page by accident,
|
||||
the <code>interval</code> class expect a policies argument describing the
|
||||
<a href="rounding.htm">rounding</a> and <a href="checking.htm">checking</a>
|
||||
policies. The first thing to do is to verify if the default policies are or
|
||||
are not adapted to your case. If your base type is not <code>float</code>,
|
||||
<code>double</code>, or <code>long double</code>, the default rounding
|
||||
policy is probably not adapted. However, by specializing
|
||||
<code>interval_lib::rounded_math</code> to your base type, the default
|
||||
rounding policy will be suitable.</p>
|
||||
|
||||
<p>The default policies define an interval type that performs precise
|
||||
computations (for <code>float</code>, <code>double</code>, <code>long
|
||||
double</code>), detects invalid numbers and throws exception each times an
|
||||
empty interval is created. This is a brief description and you should refer
|
||||
to the corresponding sections for a more precise description of the default
|
||||
policies. Unless you need some special behavior, this default type is
|
||||
usable in a lot of situations.</p>
|
||||
|
||||
<p>After having completely defined the interval type (and its policies),
|
||||
the only thing left to do is to verify that the constants are defined and
|
||||
<code>std::numeric_limits</code> is correct (if needed). Now you can use
|
||||
your brand new interval type.</p>
|
||||
|
||||
<h2>Some Examples</h2>
|
||||
|
||||
<h3>Solving systems</h3>
|
||||
|
||||
<p>If you use the interval library in order to solve equation and
|
||||
inequation systems by bisection, something like
|
||||
<code>boost::interval<double></code> is probably what you need. The
|
||||
computations are precise, and they may be fast if enclosed in a protected
|
||||
rounding mode block (see the <a href="rounding.htm#perf">performance</a>
|
||||
section). The comparison are "certain"; it is probably the most used type
|
||||
of comparison, and the other comparisons are still accessible by the
|
||||
explicit comparison functions. The checking forbid empty interval; they are
|
||||
not needed since there would be an empty interval at end of the computation
|
||||
if an empty interval is created during the computation, and no root would
|
||||
be inside. The checking also forbid invalid numbers (NaN for floating-point
|
||||
numbers). It can be a minor performance hit if you only use exact
|
||||
floating-point constants (which are clearly not NaNs); however, if
|
||||
performance really does matter, you will probably use a good compiler which
|
||||
knows how to inline functions and all these annoying little tests will
|
||||
magically disappear (if not, it is time to upgrade your compiler).</p>
|
||||
|
||||
<h3>Manipulating wide intervals</h3>
|
||||
|
||||
<p>You may want to use the library on intervals with imprecise bounds or on
|
||||
inexact numbers. In particular, it may be an existing algorithm that you
|
||||
want to rewrite and simplify by using the library. In that case, you are
|
||||
not really interested by the inclusion property; you are only interested by
|
||||
the computation algorithms the library provides. So you do not need to use
|
||||
any rounding; the checking also may not be useful. Use an "exact
|
||||
computation" rounding (you are allowed to think the name strangely applies
|
||||
to the situation) and a checking that never tests for any invalid numbers
|
||||
or empty intervals. By doing that, you will obtain library functions
|
||||
reduced to their minimum (an addition of two intervals will only be two
|
||||
additions of numbers).</p>
|
||||
|
||||
<h3>Computing ranges</h3>
|
||||
|
||||
<p>The inputs of your program may be empty intervals or invalid values (for
|
||||
example, a database can allow undefined values in some field) and the core
|
||||
of your program could also do some non-arithmetic computations that do not
|
||||
always propagate empty intervals. For example, in the library, the
|
||||
<code>hull</code> function can happily receive an empty interval but not
|
||||
generate an empty interval if the other input is valid. The
|
||||
<code>intersect</code> function is also able to produce empty intervals if
|
||||
the intervals do not overlap. In that case, it is not really interesting if
|
||||
an exception is thrown each time an empty interval is produced or an
|
||||
invalid value is used; it would be better to generate and propagate empty
|
||||
intervals. So you need to change the checking policy to something like
|
||||
<code>interval_lib::checking_base<T></code>.</p>
|
||||
|
||||
<h3>Switching interval types</h3>
|
||||
|
||||
<p>This example does not deal with a full case, but with a situation that
|
||||
can occur often. Sometimes, it can be useful to change the policies of an
|
||||
interval by converting it to another type. For example, this happens when
|
||||
you use an unprotected version of the interval type in order to speed up
|
||||
the computations; it is a change of the rounding policy. It also happens
|
||||
when you want to temporarily allow empty intervals to be created; it is a
|
||||
change of the checking policy. These changes should not be prohibited: they
|
||||
can greatly enhance a program (lisibility, interest, performance).</p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,218 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Headers Inclusion</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1>Headers Inclusion</h1>
|
||||
|
||||
<p>The easiest way to access to the library is by including the main
|
||||
header:</p>
|
||||
<pre>
|
||||
#include <boost/numeric/interval.hpp>
|
||||
</pre>
|
||||
|
||||
<p>This header will include almost all the other headers (except the ones
|
||||
listed as extensions). However, you may not want to access all the
|
||||
functionalities of the library. So this page stands as a reminder for the
|
||||
whole structure of the library.
|
||||
<code><boost/numeric/interval.hpp></code> is the only header to be
|
||||
located directly under <code>boost/numeric</code>; all the other headers
|
||||
are located in the subdirectory <code>boost/numeric/interval</code>. And
|
||||
each time this documentation will refer to
|
||||
<code>interval/something.hpp</code>, it is
|
||||
<code><boost/numeric/interval/something.hpp></code>.</p>
|
||||
|
||||
<p>Please also note that all the following headers are independent and can
|
||||
easily be pre-compiled if necessary (for compilers which support
|
||||
pre-compiled headers of course).</p>
|
||||
|
||||
<h2>Function definitions</h2>
|
||||
|
||||
<p>The following headers contain the definition of the
|
||||
<code>interval</code> class and all the friendly functions and
|
||||
operators.</p>
|
||||
|
||||
<h3><code>interval/interval.hpp</code></h3>
|
||||
|
||||
<p>This header contains the definition and the declaration of the
|
||||
<code>interval</code> class. However, this class is templated and the
|
||||
default template parameters are not available by this header. In
|
||||
particular, this header does not provide the default specialization of the
|
||||
<code>interval</code> class for the floating-point types
|
||||
(<code>interval<float></code>, <code>interval<double></code>
|
||||
and <code>interval<long double></code>). So, unless you use your own
|
||||
policies, this header is not really useful on its own.</p>
|
||||
|
||||
<h3><code>interval/utility.hpp</code></h3>
|
||||
|
||||
<p>In this header are all the functions that do not expect any arithmetic
|
||||
property from the base number type. It only expects the bounds to be
|
||||
ordered; but it should not surprise you since it is a requirement of the
|
||||
whole library. You will find in this header the definitions of access and
|
||||
related functions: <code>lower</code>, <code>upper</code>,
|
||||
<code>checked_lower</code>, <code>checked_upper</code>,
|
||||
<code>median</code>, <code>width</code>, <code>widen</code>. There are also
|
||||
the set-like functions: <code>in,</code> <code>zero_in</code>,
|
||||
<code>empty</code>, <code>subset</code>, <code>proper_subset</code>,
|
||||
<code>overlap</code>, <code>singleton</code>, <code>equal</code>,
|
||||
<code>intersect</code>, <code>hull</code>, <code>bisect</code>. Finally,
|
||||
<code>abs</code>, <code>min</code>, and <code>max</code> are defined.</p>
|
||||
|
||||
<h3><code>interval/arith.hpp</code></h3>
|
||||
|
||||
<p>Here are the binary operators <code>+</code>, <code>-</code>,
|
||||
<code>*</code>, <code>/</code> and the unary operator <code>-</code>.</p>
|
||||
|
||||
<h3><code>interval/arith2.hpp</code></h3>
|
||||
|
||||
<p>This header defines <code>fmod</code>, <code>square</code>,
|
||||
<code>sqrt</code>, <code>pow</code>, and <code>root</code>.</p>
|
||||
|
||||
<h3><code>interval/arith3.hpp</code></h3>
|
||||
|
||||
<p>The third arithmetic header: it provides the functions <code>add</code>,
|
||||
<code>sub</code>, <code>mul</code>, and <code>div</code>. The type of their
|
||||
arguments is the base number type.</p>
|
||||
|
||||
<h3><code>interval/transc.hpp</code></h3>
|
||||
|
||||
<p>It is the last of the headers with mathematical functions; it provides
|
||||
the following functions: <code>cos</code>, <code>sin</code>,
|
||||
<code>tan</code>, <code>acos</code>, <code>asin</code>, <code>atan</code>,
|
||||
<code>cosh</code>, <code>sinh</code>, <code>tanh</code>,
|
||||
<code>acosh</code>, <code>asinh</code>, <code>atanh</code>,
|
||||
<code>exp</code>, and <code>log</code>.</p>
|
||||
|
||||
<h2>Policies</h2>
|
||||
|
||||
<p>The following headers define some policies. They may be needed if you
|
||||
use the default policies.</p>
|
||||
|
||||
<h3><code>interval/rounded_arith.hpp</code></h3>
|
||||
|
||||
<p>This header defines the three provided rounding policies for the
|
||||
arithmetic functions: <code>rounded_arith_std</code>,
|
||||
<code>rounded_arith_opp</code>, <code>rounded_arith_exact</code>.</p>
|
||||
|
||||
<h3><code>interval/rounded_transc.hpp</code></h3>
|
||||
|
||||
<p>This header defines the three provided rounding policies for the
|
||||
transcendental functions: <code>rounded_transc_std</code>,
|
||||
<code>rounded_transc_opp</code>, <code>rounded_transc_exact</code>. It is
|
||||
separated from <code>rounded_arith.hpp</code> since the transcendental part
|
||||
of the rounding policy is probably less useful than the arithmetic
|
||||
part.</p>
|
||||
|
||||
<h3><code>interval/hw_rounding.hpp</code></h3>
|
||||
|
||||
<p>Here are full rounding policies for the basic floating-point types. The
|
||||
policies are processor-dependent; and to allow the user code to be
|
||||
portable, they only define the common subset of the hardware available
|
||||
functions, which are the arithmetic functions of the rounding policy.</p>
|
||||
|
||||
<h3><code>interval/checking.hpp</code></h3>
|
||||
|
||||
<p>This header provides the predefined checking policies:
|
||||
<code>checking_base</code>, <code>checking_no_empty</code>,
|
||||
<code>checking_no_nan</code>, <code>checking_catch_nan</code>,
|
||||
<code>checking_strict</code>.</p>
|
||||
|
||||
<h3><code>interval/policies.hpp</code></h3>
|
||||
|
||||
<p>Here are defined the helpers for manipulating policies. It contains
|
||||
<code>policies</code> (and so is needed for using default policies),
|
||||
<code>change_rounding</code>, <code>change_checking</code>,
|
||||
<code>unprotect</code>, etc.</p>
|
||||
|
||||
<h2>Comparisons</h2>
|
||||
|
||||
<h3><code>interval/compare.hpp</code></h3>
|
||||
|
||||
<p>This header includes all the following headers. They provide some
|
||||
predefined comparison namespaces.</p>
|
||||
|
||||
<h3><code>interval/compare/certain.hpp</code></h3>
|
||||
|
||||
<p>Here is <code>compare::certain</code>.</p>
|
||||
|
||||
<h3><code>interval/compare/possible.hpp</code></h3>
|
||||
|
||||
<p>And here is its friend <code>compare::possible</code>.</p>
|
||||
|
||||
<h3><code>interval/compare/explicit.hpp</code></h3>
|
||||
|
||||
<p>The explicit comparison functions <code>cerlt</code>,
|
||||
<code>posge</code>, etc are defined in this header.</p>
|
||||
|
||||
<h3><code>interval/compare/lexicographic.hpp</code></h3>
|
||||
|
||||
<p>This header provides <code>compare::lexicographic</code>.</p>
|
||||
|
||||
<h3><code>interval/compare/set.hpp</code></h3>
|
||||
|
||||
<p>This header provides <code>compare::set</code>.</p>
|
||||
|
||||
<h2>Extensions</h2>
|
||||
|
||||
<p>The following headers are not included by <code>interval.hpp</code> and
|
||||
will usually provide not always desirable capabilities.</p>
|
||||
|
||||
<h3><code>interval/io.hpp</code></h3>
|
||||
|
||||
<p>Here are defined basic stream operators <code><<</code> and
|
||||
<code>>></code>. They should only be used as a first approach and
|
||||
later be replaced by a customized version.</p>
|
||||
|
||||
<h3><code>interval/limits.hpp</code></h3>
|
||||
|
||||
<p>A specialization of <code>std::numeric_limits</code> adapted to the
|
||||
interval type.</p>
|
||||
|
||||
<h3><code>interval/compare/tribool.hpp</code></h3>
|
||||
|
||||
<p>This header provides a comparison namespace
|
||||
<code>compare::tribool</code> especially adapted to a tristate boolean.</p>
|
||||
|
||||
<h3><code>interval/ext/integer.hpp</code></h3>
|
||||
|
||||
<p>This header provides mixed operations between intervals and integers. It
|
||||
is done by converting the integer to the base number type. Because this
|
||||
comparison is not always correct (for a big <code>int</code> may not be
|
||||
exactly convertible to <code>float</code>), this header is not
|
||||
automatically included and the user should ensure that this behavior is
|
||||
compatible with what she wants to do (if it is only to multiply some
|
||||
intervals by 2, it probably is a good thing to include this header).</p>
|
||||
|
||||
<h3><code>interval/ext/x86_fast_rounding_control.hpp</code></h3>
|
||||
|
||||
<p>This header defines a new rounding policy allowing to workaround the
|
||||
precision problem of the x86 processors (and so speeding up the
|
||||
computations). However, it only is a partial solution and it shouldn't be
|
||||
used when there is a possibility of underflow or overflow.</p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University<br>
|
||||
Copyright © 2003-2006 Guillaume Melquiond, ENS Lyon</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=interval.htm">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="interval.htm">interval.htm</a>. <hr>
|
||||
<p>© Copyright Beman Dawes, 2001</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
||||
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,990 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Boost Interval Arithmetic Library</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"middle"> Interval Arithmetic Library</h1>
|
||||
|
||||
<center>
|
||||
<table width="80%" summary="">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>Contents of this page:</b><br>
|
||||
<a href="#intro">Introduction</a><br>
|
||||
<a href="#synopsis">Synopsis</a><br>
|
||||
<a href="#interval">Template class <code>interval</code></a><br>
|
||||
<a href="#opers">Operations and functions</a><br>
|
||||
<a href="#interval_lib">Interval support library</a><br>
|
||||
<!--<a href="#compil">Compilation notes</a><br>-->
|
||||
<a href="#dangers">Common pitfalls and dangers</a><br>
|
||||
<a href="#rationale">Rationale</a><br>
|
||||
<a href="#acks">History and Acknowledgments</a></td>
|
||||
|
||||
<td><b>Other pages associated with this page:</b><br>
|
||||
<a href="rounding.htm">Rounding policies</a><br>
|
||||
<a href="checking.htm">Checking policies</a><br>
|
||||
<a href="policies.htm">Policies manipulation</a><br>
|
||||
<a href="comparisons.htm">Comparisons</a><br>
|
||||
<a href="numbers.htm">Base number type requirements</a><br>
|
||||
<a href="guide.htm">Choosing your own interval type</a><br>
|
||||
<a href="examples.htm">Test and example programs</a><br>
|
||||
<a href="includes.htm">Headers inclusion</a><br>
|
||||
<a href="todo.htm">Some items on the todo list</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<h2 id="intro">Introduction and Overview</h2>
|
||||
|
||||
<p>As implied by its name, this library is intended to help manipulating
|
||||
mathematical intervals. It consists of a single header <<a href=
|
||||
"../../../../boost/numeric/interval.hpp">boost/numeric/interval.hpp</a>>
|
||||
and principally a type which can be used as <code>interval<T></code>.
|
||||
In fact, this interval template is declared as
|
||||
<code>interval<T,Policies></code> where <code>Policies</code> is a
|
||||
policy class that controls the various behaviours of the interval class;
|
||||
<code>interval<T></code> just happens to pick the default policies
|
||||
for the type <code>T</code>.</p>
|
||||
|
||||
<p><span style="color: #FF0000; font-weight: bold">Warning!</span>
|
||||
Guaranteed interval arithmetic for native floating-point format is not
|
||||
supported on every combination of processor, operating system, and
|
||||
compiler. This is a list of systems known to work correctly when using
|
||||
<code>interval<float></code> and <code>interval<double></code>
|
||||
with basic arithmetic operators.</p>
|
||||
|
||||
<ul>
|
||||
<li>x86-like hardware is supported by the library with GCC, Visual C++
|
||||
≥ 7.1, Intel compiler (≥ 8 on Windows), CodeWarrior (≥ 9), as
|
||||
long as the traditional x87 floating-point unit is used for
|
||||
floating-point computations (no <code>-mfpmath=sse2</code> support).</li>
|
||||
|
||||
<li>Sparc hardware is supported with GCC and Sun compiler.</li>
|
||||
|
||||
<li>PowerPC hardware is supported with GCC and CodeWarrior, when
|
||||
floating-point computations are not done with the Altivec unit.</li>
|
||||
|
||||
<li>Alpha hardware is supported with GCC, except maybe for the square
|
||||
root. The options <code>-mfp-rounding-mode=d -mieee</code> have to be
|
||||
used.</li>
|
||||
</ul>
|
||||
|
||||
<p>The previous list is not exhaustive. And even if a system does not
|
||||
provide guaranteed computations for hardware floating-point types, the
|
||||
interval library is still usable with user-defined types and for doing box
|
||||
arithmetic.</p>
|
||||
|
||||
<h3>Interval Arithmetic</h3>
|
||||
|
||||
<p>An interval is a pair of numbers which represents all the numbers
|
||||
between these two. (Intervals are considered closed so the bounds are
|
||||
included.) The purpose of this library is to extend the usual arithmetic
|
||||
functions to intervals. These intervals will be written [<i>a</i>,<i>b</i>]
|
||||
to represent all the numbers between <i>a</i> and <i>b</i> (included).
|
||||
<i>a</i> and <i>b</i> can be infinite (but they can not be the same
|
||||
infinite) and <i>a</i> ≤ <i>b</i>.</p>
|
||||
|
||||
<p>The fundamental property of interval arithmetic is the
|
||||
<em><strong>inclusion property</strong></em>:</p>
|
||||
|
||||
<dl>
|
||||
<dd>``if <i>f</i> is a function on a set of numbers, <i>f</i> can be
|
||||
extended to a new function defined on intervals. This new function
|
||||
<i>f</i> takes one interval argument and returns an interval result such
|
||||
as: ∀ <i>x</i> ∈ [<i>a</i>,<i>b</i>], <i>f</i>(<i>x</i>)
|
||||
∈ <i>f</i>([<i>a</i>,<i>b</i>]).''</dd>
|
||||
</dl>
|
||||
|
||||
<p>Such a property is not limited to functions with only one argument.
|
||||
Whenever possible, the interval result should be the smallest one able to
|
||||
satisfy the property (it is not really useful if the new functions always
|
||||
answer [-∞,+∞]).</p>
|
||||
|
||||
<p>There are at least two reasons a user would like to use this library.
|
||||
The obvious one is when the user has to compute with intervals. One example
|
||||
is when input data have some builtin imprecision: instead of a number, an
|
||||
input variable can be passed as an interval. Another example application is
|
||||
to solve equations, by bisecting an interval until the interval width is
|
||||
small enough. A third example application is in computer graphics, where
|
||||
computations with boxes, segments or rays can be reduced to computations
|
||||
with points via intervals.</p>
|
||||
|
||||
<p>Another common reason to use interval arithmetic is when the computer
|
||||
doesn't produce exact results: by using intervals, it is possible to
|
||||
quantify the propagation of rounding errors. This approach is used often in
|
||||
numerical computation. For example, let's assume the computer stores
|
||||
numbers with ten decimal significant digits. To the question 1 + 1E-100 -
|
||||
1, the computer will answer 0 although the correct answer would be 1E-100.
|
||||
With the help of interval arithmetic, the computer will answer [0,1E-9].
|
||||
This is quite a huge interval for such a little result, but the precision
|
||||
is now known, without having to compute error propagation.</p>
|
||||
|
||||
<h3>Numbers, rounding, and exceptional behavior</h3>
|
||||
|
||||
<p>The <em><strong>base number type</strong></em> is the type that holds
|
||||
the bounds of the interval. In order to successfully use interval
|
||||
arithmetic, the base number type must present some <a href=
|
||||
"rounding.htm">characteristics</a>. Firstly, due to the definition of an
|
||||
interval, the base numbers have to be totally ordered so, for instance,
|
||||
<code>complex<T></code> is not usable as base number type for
|
||||
intervals. The mathematical functions for the base number type should also
|
||||
be compatible with the total order (for instance if x>y and z>t, then
|
||||
it should also hold that x+z > y+t), so modulo types are not usable
|
||||
either.</p>
|
||||
|
||||
<p>Secondly, the computations must be exact or provide some rounding
|
||||
methods (for instance, toward minus or plus infinity) if we want to
|
||||
guarantee the inclusion property. Note that we also may explicitely specify
|
||||
no rounding, for instance if the base number type is exact, i.e. the result
|
||||
of a mathematical operation is always computed and represented without loss
|
||||
of precision. If the number type is not exact, we may still explicitely
|
||||
specify no rounding, with the obvious consequence that the inclusion
|
||||
property is no longer guaranteed.</p>
|
||||
|
||||
<p>Finally, because heavy loss of precision is always possible, some
|
||||
numbers have to represent infinities or an exceptional behavior must be
|
||||
defined. The same situation also occurs for NaN (<i>Not a Number</i>).</p>
|
||||
|
||||
<p>Given all this, one may want to limit the template argument T of the
|
||||
class template <code>interval</code> to the floating point types
|
||||
<code>float</code>, <code>double</code>, and <code>long double</code>, as
|
||||
defined by the IEEE-754 Standard. Indeed, if the interval arithmetic is
|
||||
intended to replace the arithmetic provided by the floating point unit of a
|
||||
processor, these types are the best choice. Unlike
|
||||
<code>std::complex</code>, however, we don't want to limit <code>T</code>
|
||||
to these types. This is why we allow the rounding and exceptional behaviors
|
||||
to be given by the two policies (rounding and checking). We do nevertheless
|
||||
provide highly optimized rounding and checking class specializations for
|
||||
the above-mentioned floating point types.</p>
|
||||
|
||||
<h3>Operations and functions</h3>
|
||||
|
||||
<p>It is straightforward to define the elementary arithmetic operations on
|
||||
intervals, being guided by the inclusion property. For instance, if [a,b]
|
||||
and [c,d] are intervals, [a,b]+[c,d] can be computed by taking the smallest
|
||||
interval that contains all the numbers x+y for x in [a,b] and y in [c,d];
|
||||
in this case, rounding a+c down and b+d up will suffice. Other operators
|
||||
and functions are similarly defined (see their definitions below).</p>
|
||||
|
||||
<h3>Comparisons</h3>
|
||||
|
||||
<p>It is also possible to define some comparison operators. Given two
|
||||
intervals, the result is a tri-state boolean type
|
||||
{<i>false</i>,<i>true,indeterminate</i>}. The answers <i>false</i> and
|
||||
<i>true</i> are easy to manipulate since they can directly be mapped on the
|
||||
boolean <i>true</i> and <i>false</i>. But it is not the case for the answer
|
||||
<em>indeterminate</em> since comparison operators are supposed to be
|
||||
boolean functions. So, what to do in order to obtain boolean answers?</p>
|
||||
|
||||
<p>One solution consists of deciding to adopt an exceptional behavior, such
|
||||
as a failed assertion or raising an exception. In this case, the
|
||||
exceptional behavior will be triggered when the result is
|
||||
indeterminate.</p>
|
||||
|
||||
<p>Another solution is to map <em>indeterminate</em> always to
|
||||
<i>false,</i> or always to <i>true</i>. If <i>false</i> is chosen, the
|
||||
comparison will be called "<i>certain</i>;" indeed, the result of
|
||||
[<i>a</i>,<i>b</i>] < [<i>c</i>,<i>d</i>] will be <i>true</i> if and
|
||||
only if: ∀ <i>x</i> ∈ [<i>a</i>,<i>b</i>] ∀ <i>y</i>
|
||||
∈ [<i>c</i>,<i>d</i>], <i>x</i> < <i>y</i>. If <i>true</i> is
|
||||
chosen, the comparison will be called "<i>possible</i>;" indeed, the result
|
||||
of [<i>a</i>,<i>b</i>] < [<i>c</i>,<i>d</i>] will be <i>true</i> if and
|
||||
only if: ∃ <i>x</i> ∈ [<i>a</i>,<i>b</i>] ∃ <i>y</i>
|
||||
∈ [<i>c</i>,<i>d</i>], <i>x</i> < <i>y</i>.</p>
|
||||
|
||||
<p>Since any of these solution has a clearly defined semantics, it is not
|
||||
clear that we should enforce either of them. For this reason, the default
|
||||
behavior consists to mimic the real comparisons by throwing an exception in
|
||||
the indeterminate case. Other behaviors can be selected bu using specific
|
||||
comparison namespace. There is also a bunch of explicitely named comparison
|
||||
functions. See <a href="comparisons.htm">comparisons</a> pages for further
|
||||
details.</p>
|
||||
|
||||
<h3>Overview of the library, and usage</h3>
|
||||
|
||||
<p>This library provides two quite distinct levels of usage. One is to use
|
||||
the basic class template <code>interval<T></code> without specifying
|
||||
the policy. This only requires one to know and understand the concepts
|
||||
developed above and the content of the namespace boost. In addition to the
|
||||
class <code>interval<T></code>, this level of usage provides
|
||||
arithmetic operators (<code>+</code>, <code>-</code>, <code>*</code>,
|
||||
<code>/</code>), algebraic and piecewise-algebraic functions
|
||||
(<code>abs</code>, <code>square</code>, <code>sqrt</code>,
|
||||
<code>pow</code>), transcendental and trigonometric functions
|
||||
(<code>exp</code>, <code>log</code>, <code>sin</code>, <code>cos</code>,
|
||||
<code>tan</code>, <code>asin</code>, <code>acos</code>, <code>atan</code>,
|
||||
<code>sinh</code>, <code>cosh</code>, <code>tanh</code>,
|
||||
<code>asinh</code>, <code>acosh</code>, <code>atanh</code>), and the
|
||||
standard comparison operators (<code><</code>, <code><=</code>,
|
||||
<code>></code>, <code>>=</code>, <code>==</code>, <code>!=</code>),
|
||||
as well as several interval-specific functions (<code>min</code>,
|
||||
<code>max</code>, which have a different meaning than <code>std::min</code>
|
||||
and <code>std::max</code>; <code>lower</code>, <code>upper</code>,
|
||||
<code>width</code>, <code>median</code>, <code>empty</code>,
|
||||
<code>singleton</code>, <code>equal</code>, <code>in</code>,
|
||||
<code>zero_in</code>, <code>subset</code>, <code>proper_subset</code>,
|
||||
<code>overlap</code>, <code>intersect</code>, <code>hull</code>,
|
||||
<code>bisect</code>).</p>
|
||||
|
||||
<p>For some functions which take several parameters of type
|
||||
<code>interval<T></code>, all combinations of argument types
|
||||
<code>T</code> and <code>interval<T></code> which contain at least
|
||||
one <code>interval<T></code>, are considered in order to avoid a
|
||||
conversion from the arguments of type <code>T</code> to a singleton of type
|
||||
<code>interval<T></code>. This is done for efficiency reasons (the
|
||||
fact that an argument is a singleton sometimes renders some tests
|
||||
unnecessary).</p>
|
||||
|
||||
<p>A somewhat more advanced usage of this library is to hand-pick the
|
||||
policies <code>Rounding</code> and <code>Checking</code> and pass them to
|
||||
<code>interval<T, Policies></code> through the use of <code>Policies
|
||||
:= boost::numeric::interval_lib::policies<Rounding,Checking></code>.
|
||||
Appropriate policies can be fabricated by using the various classes
|
||||
provided in the namespace <code>boost::numeric::interval_lib</code> as
|
||||
detailed in section <a href="#interval_lib">Interval Support Library</a>.
|
||||
It is also possible to choose the comparison scheme by overloading
|
||||
operators through namespaces.</p>
|
||||
|
||||
<h2><a name="synopsis" id="synopsis"></a>Synopsis</h2>
|
||||
<pre>
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
|
||||
namespace interval_lib {
|
||||
|
||||
/* this declaration is necessary for the declaration of interval */
|
||||
template <class T> struct default_policies;
|
||||
|
||||
/* ... ; the full synopsis of namespace interval_lib can be found <a href=
|
||||
"#interval_lib">here</a> */
|
||||
|
||||
} // namespace interval_lib
|
||||
|
||||
|
||||
/* template interval_policies; class definition can be found <a href=
|
||||
"policies.htm">here</a> */
|
||||
template<class Rounding, class Checking>
|
||||
struct interval_policies;
|
||||
|
||||
/* template class interval; class definition can be found <a href=
|
||||
"#interval">here</a> */
|
||||
template<class T, class Policies = typename interval_lib::default_policies<T>::type > class interval;
|
||||
|
||||
/* arithmetic operators involving intervals */
|
||||
template <class T, class Policies> interval<T, Policies> operator+(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> operator-(const interval<T, Policies>& x);
|
||||
|
||||
template <class T, class Policies> interval<T, Policies> operator+(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> operator+(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> interval<T, Policies> operator+(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> interval<T, Policies> operator-(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> operator-(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> interval<T, Policies> operator-(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> interval<T, Policies> operator*(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> operator*(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> interval<T, Policies> operator*(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> interval<T, Policies> operator/(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> operator/(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> interval<T, Policies> operator/(const T& r, const interval<T, Policies>& x);
|
||||
|
||||
/* algebraic functions: sqrt, abs, square, pow, nth_root */
|
||||
template <class T, class Policies> interval<T, Policies> abs(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> sqrt(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> square(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> pow(const interval<T, Policies>& x, int y);
|
||||
template <class T, class Policies> interval<T, Policies> nth_root(const interval<T, Policies>& x, int y);
|
||||
|
||||
/* transcendental functions: exp, log */
|
||||
template <class T, class Policies> interval<T, Policies> exp(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> log(const interval<T, Policies>& x);
|
||||
|
||||
/* fmod, for trigonometric function argument reduction (see below) */
|
||||
template <class T, class Policies> interval<T, Policies> fmod(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> fmod(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> interval<T, Policies> fmod(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
/* trigonometric functions */
|
||||
template <class T, class Policies> interval<T, Policies> sin(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> cos(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> tan(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> asin(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> acos(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> atan(const interval<T, Policies>& x);
|
||||
|
||||
/* hyperbolic trigonometric functions */
|
||||
template <class T, class Policies> interval<T, Policies> sinh(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> cosh(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> tanh(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> asinh(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> acosh(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> interval<T, Policies> atanh(const interval<T, Policies>& x);
|
||||
|
||||
/* min, max external functions (NOT std::min/max, see below) */
|
||||
template <class T, class Policies> interval<T, Policies> max(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> max(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> interval<T, Policies> max(const T& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> min(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> min(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> interval<T, Policies> min(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
/* bounds-related interval functions */
|
||||
template <class T, class Policies> T lower(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> T upper(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> T width(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> T median(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> T norm(const interval<T, Policies>& x);
|
||||
|
||||
/* bounds-related interval functions */
|
||||
template <class T, class Policies> bool empty(const interval<T, Policies>& b);
|
||||
template <class T, class Policies> bool singleton(const interval<T, Policies>& x);
|
||||
template <class T, class Policies> bool equal(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool in(const T& r, const interval<T, Policies>& b);
|
||||
template <class T, class Policies> bool zero_in(const interval<T, Policies>& b);
|
||||
template <class T, class Policies> bool subset(const interval<T, Policies>& a, const interval<T, Policies>& b);
|
||||
template <class T, class Policies> bool proper_subset(const interval<T, Policies>& a, const interval<T, Policies>& b);
|
||||
template <class T, class Policies> bool overlap(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
|
||||
/* set manipulation interval functions */
|
||||
template <class T, class Policies> interval<T, Policies> intersect(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> hull(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> hull(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> interval<T, Policies> hull(const T& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> interval<T, Policies> hull(const T& x, const T& y);
|
||||
template <class T, class Policies> std::pair<interval<T, Policies>, interval<T, Policies> > bisect(const interval<T, Policies>& x);
|
||||
|
||||
/* interval comparison operators */
|
||||
template<class T, class Policies> bool operator<(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template<class T, class Policies> bool operator<(const interval<T, Policies>& x, const T& y);
|
||||
template<class T, class Policies> bool operator<(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template<class T, class Policies> bool operator<=(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template<class T, class Policies> bool operator<=(const interval<T, Policies>& x, const T& y);
|
||||
template<class T, class Policies> bool operator<=(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template<class T, class Policies> bool operator>(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template<class T, class Policies> bool operator>(const interval<T, Policies>& x, const T& y);
|
||||
template<class T, class Policies> bool operator>(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template<class T, class Policies> bool operator>=(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template<class T, class Policies> bool operator>=(const interval<T, Policies>& x, const T& y);
|
||||
template<class T, class Policies> bool operator>=(const T& x, const interval<T, Policies>& y);
|
||||
</pre>
|
||||
<pre>
|
||||
template<class T, class Policies> bool operator==(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template<class T, class Policies> bool operator==(const interval<T, Policies>& x, const T& y);
|
||||
template<class T, class Policies> bool operator==(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template<class T, class Policies> bool operator!=(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template<class T, class Policies> bool operator!=(const interval<T, Policies>& x, const T& y);
|
||||
template<class T, class Policies> bool operator!=(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
namespace interval_lib {
|
||||
|
||||
template<class T, class Policies> interval<T, Policies> division_part1(const interval<T, Policies>& x, const interval<T, Policies& y, bool& b);
|
||||
template<class T, class Policies> interval<T, Policies> division_part2(const interval<T, Policies>& x, const interval<T, Policies& y, bool b = true);
|
||||
template<class T, class Policies> interval<T, Policies> multiplicative_inverse(const interval<T, Policies>& x);
|
||||
|
||||
template<class I> I add(const typename I::base_type& x, const typename I::base_type& y);
|
||||
template<class I> I sub(const typename I::base_type& x, const typename I::base_type& y);
|
||||
template<class I> I mul(const typename I::base_type& x, const typename I::base_type& y);
|
||||
template<class I> I div(const typename I::base_type& x, const typename I::base_type& y);
|
||||
|
||||
} // namespace interval_lib
|
||||
|
||||
} // namespace numeric
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2><a name="interval" id="interval"></a>Template class
|
||||
<code>interval</code></h2>The public interface of the template class
|
||||
interval itself is kept at a simplest minimum:
|
||||
<pre>
|
||||
template <class T, class Policies = typename interval_lib::default_policies<T>::type>
|
||||
class interval
|
||||
{
|
||||
public:
|
||||
typedef T base_type;
|
||||
typedef Policies traits_type;
|
||||
|
||||
interval();
|
||||
interval(T const &v);
|
||||
template<class T1> interval(T1 const &v);
|
||||
interval(T const &l, T const &u);
|
||||
template<class T1, class T2> interval(T1 const &l, T2 const &u);
|
||||
interval(interval<T, Policies> const &r);
|
||||
template<class Policies1> interval(interval<T, Policies1> const &r);
|
||||
template<class T1, class Policies1> interval(interval<T1, Policies1> const &r);
|
||||
|
||||
interval &operator=(T const &v);
|
||||
template<class T1> interval &operator=(T1 const &v);
|
||||
interval &operator=(interval<T, Policies> const &r);
|
||||
template<class Policies1> interval &operator=(interval<T, Policies1> const &r);
|
||||
template<class T1, class Policies1> interval &operator=(interval<T1, Policies1> const &r);
|
||||
|
||||
void assign(T const &l, T const &u);
|
||||
|
||||
T const &lower() const;
|
||||
T const &upper() const;
|
||||
|
||||
static interval empty();
|
||||
static interval whole();
|
||||
static interval hull(T const &x, T const &y);
|
||||
|
||||
interval& operator+= (T const &r);
|
||||
interval& operator-= (T const &r);
|
||||
interval& operator*= (T const &r);
|
||||
interval& operator/= (T const &r);
|
||||
interval& operator+= (interval const &r);
|
||||
interval& operator-= (interval const &r);
|
||||
interval& operator*= (interval const &r);
|
||||
interval& operator/= (interval const &r);
|
||||
};
|
||||
</pre>
|
||||
|
||||
<p>The constructors create an interval enclosing their arguments. If there
|
||||
are two arguments, the first one is assumed to be the left bound and the
|
||||
second one is the right bound. Consequently, the arguments need to be
|
||||
ordered. If the property !(l <= u) is not respected, the checking policy
|
||||
will be used to create an empty interval. If no argument is given, the
|
||||
created interval is the singleton zero.</p>
|
||||
|
||||
<p>If the type of the arguments is the same as the base number type, the
|
||||
values are directly used for the bounds. If it is not the same type, the
|
||||
library will use the rounding policy in order to convert the arguments
|
||||
(<code>conv_down</code> and <code>conv_up</code>) and create an enclosing
|
||||
interval. When the argument is an interval with a different policy, the
|
||||
input interval is checked in order to correctly propagate its emptiness (if
|
||||
empty).</p>
|
||||
|
||||
<p>The assignment operators behave similarly, except they obviously take
|
||||
one argument only. There is also an <code>assign</code> function in order
|
||||
to directly change the bounds of an interval. It behaves like the
|
||||
two-arguments constructors if the bounds are not ordered. There is no
|
||||
assign function that directly takes an interval or only one number as a
|
||||
parameter; just use the assignment operators in such a case.</p>
|
||||
|
||||
<p>The type of the bounds and the policies of the interval type define the
|
||||
set of values the intervals contain. E.g. with the default policies,
|
||||
intervals are subsets of the set of real numbers. The static functions
|
||||
<code>empty</code> and <code>whole</code> produce the intervals/subsets
|
||||
that are respectively the empty subset and the whole set. They are static
|
||||
member functions rather than global functions because they cannot guess
|
||||
their return types. Likewise for <code>hull</code>. <code>empty</code> and
|
||||
<code>whole</code> involve the checking policy in order to get the bounds
|
||||
of the resulting intervals.</p>
|
||||
|
||||
<h2><a name="opers" id="opers"></a>Operations and Functions</h2>
|
||||
|
||||
<p>Some of the following functions expect <code>min</code> and
|
||||
<code>max</code> to be defined for the base type. Those are the only
|
||||
requirements for the <code>interval</code> class (but the policies can have
|
||||
other requirements).</p>
|
||||
|
||||
<h4>Operators <code>+</code> <code>-</code> <code>*</code> <code>/</code>
|
||||
<code>+=</code> <code>-=</code> <code>*=</code> <code>/=</code></h4>
|
||||
|
||||
<p>The basic operations are the unary minus and the binary <code>+</code>
|
||||
<code>-</code> <code>*</code> <code>/</code>. The unary minus takes an
|
||||
interval and returns an interval. The binary operations take two intervals,
|
||||
or one interval and a number, and return an interval. If an argument is a
|
||||
number instead of an interval, you can expect the result to be the same as
|
||||
if the number was first converted to an interval. This property will be
|
||||
true for all the following functions and operators.</p>
|
||||
|
||||
<p>There are also some assignment operators <code>+=</code> <code>-=</code>
|
||||
<code>*=</code> <code>/=</code>. There is not much to say: <code>x op=
|
||||
y</code> is equivalent to <code>x = x op y</code>. If an exception is
|
||||
thrown during the computations, the l-value is not modified (but it may be
|
||||
corrupt if an exception is thrown by the base type during an
|
||||
assignment).</p>
|
||||
|
||||
<p>The operators <code>/</code> and <code>/=</code> will try to produce an
|
||||
empty interval if the denominator is exactly zero. If the denominator
|
||||
contains zero (but not only zero), the result will be the smallest interval
|
||||
containing the set of division results; so one of its bound will be
|
||||
infinite, but it may not be the whole interval.</p>
|
||||
|
||||
<h4><code>lower</code> <code>upper</code> <code>median</code>
|
||||
<code>width</code> <code>norm</code></h4>
|
||||
|
||||
<p><code>lower</code>, <code>upper</code>, <code>median</code> respectively
|
||||
compute the lower bound, the upper bound, and the median number of an
|
||||
interval (<code>(lower+upper)/2</code> rounded to nearest).
|
||||
<code>width</code> computes the width of an interval
|
||||
(<code>upper-lower</code> rounded toward plus infinity). <code>norm</code>
|
||||
computes an upper bound of the interval in absolute value; it is a
|
||||
mathematical norm (hence the name) similar to the absolute value for real
|
||||
numbers.</p>
|
||||
|
||||
<h4><code>min</code> <code>max</code> <code>abs</code> <code>square</code>
|
||||
<code>pow</code> <code>nth_root</code> <code>division_part?</code>
|
||||
<code>multiplicative_inverse</code></h4>
|
||||
|
||||
<p>The functions <code>min</code>, <code>max</code> and <code>abs</code>
|
||||
are also defined. Please do not mistake them for the functions defined in
|
||||
the standard library (aka <code>a<b?a:b</code>, <code>a>b?a:b</code>,
|
||||
<code>a<0?-a:a</code>). These functions are compatible with the
|
||||
elementary property of interval arithmetic. For example,
|
||||
max([<i>a</i>,<i>b</i>], [<i>c</i>,<i>d</i>]) = {max(<i>x</i>,<i>y</i>)
|
||||
such that <i>x</i> in [<i>a</i>,<i>b</i>] and <i>y</i> in
|
||||
[<i>c</i>,<i>d</i>]}. They are not defined in the <code>std</code>
|
||||
namespace but in the boost namespace in order to avoid conflict with the
|
||||
other definitions.</p>
|
||||
|
||||
<p>The <code>square</code> function is quite particular. As you can expect
|
||||
from its name, it computes the square of its argument. The reason this
|
||||
function is provided is: <code>square(x)</code> is not <code>x*x</code> but
|
||||
only a subset when <code>x</code> contains zero. For example, [-2,2]*[-2,2]
|
||||
= [-4,4] but [-2,2]² = [0,4]; the result is a smaller interval.
|
||||
Consequently, <code>square(x)</code> should be used instead of
|
||||
<code>x*x</code> because of its better accuracy and a small performance
|
||||
improvement.</p>
|
||||
|
||||
<p>As for <code>square</code>, <code>pow</code> provides an efficient and
|
||||
more accurate way to compute the integer power of an interval. Please note:
|
||||
when the power is 0 and the interval is not empty, the result is 1, even if
|
||||
the input interval contains 0. <code>nth_root</code> computes the integer root
|
||||
of an interval (<code>nth_root(pow(x,k),k)</code> encloses <code>x</code> or
|
||||
<code>abs(x)</code> depending on whether <code>k</code> is odd or even).
|
||||
The behavior of <code>nth_root</code> is not defined if the integer argument is
|
||||
not positive. <code>multiplicative_inverse</code> computes
|
||||
<code>1/x</code>.</p>
|
||||
|
||||
<p>The functions <code>division_part1</code> and
|
||||
<code>division_part2</code> are useful when the user expects the division
|
||||
to return disjoint intervals if necessary. For example, the narrowest
|
||||
closed set containing [2,3] / [-2,1] is not ]-∞,∞[ but the union
|
||||
of ]-∞,-1] and [2,∞[. When the result of the division is
|
||||
representable by only one interval, <code>division_part1</code> returns
|
||||
this interval and sets the boolean reference to <code>false</code>.
|
||||
However, if the result needs two intervals, <code>division_part1</code>
|
||||
returns the negative part and sets the boolean reference to
|
||||
<code>true</code>; a call to <code>division_part2</code> is now needed to
|
||||
get the positive part. This second function can take the boolean returned
|
||||
by the first function as last argument. If this bool is not given, its
|
||||
value is assumed to be true and the behavior of the function is then
|
||||
undetermined if the division does not produce a second interval.</p>
|
||||
|
||||
<h4><code>intersect</code> <code>hull</code> <code>overlap</code>
|
||||
<code>in</code> <code>zero_in</code> <code>subset</code>
|
||||
<code>proper_subset</code> <code>empty</code> <code>singleton</code>
|
||||
<code>equal</code></h4>
|
||||
|
||||
<p><code>intersect</code> computes the set intersection of two closed sets,
|
||||
<code>hull</code> computes the smallest interval which contains the two
|
||||
parameters; those parameters can be numbers or intervals. If one of the
|
||||
arguments is an invalid number or an empty interval, the function will only
|
||||
use the other argument to compute the resulting interval (if allowed by the
|
||||
checking policy).</p>
|
||||
|
||||
<p>There is no union function since the union of two intervals is not an
|
||||
interval if they do not overlap. If they overlap, the <code>hull</code>
|
||||
function computes the union.</p>
|
||||
|
||||
<p>The function <code>overlap</code> tests if two intervals have some
|
||||
common subset. <code>in</code> tests if a number is in an interval;
|
||||
<code>zero_in</code> is a variant which tests if zero is in the interval.
|
||||
<code>subset</code> tests if the first interval is a subset of the second;
|
||||
and <code>proper_subset</code> tests if it is a proper subset.
|
||||
<code>empty</code> and <code>singleton</code> test if an interval is empty
|
||||
or is a singleton. Finally, <code>equal</code> tests if two intervals are
|
||||
equal.</p>
|
||||
|
||||
<h4><code>sqrt</code> <code>log</code> <code>exp</code> <code>sin</code>
|
||||
<code>cos</code> <code>tan</code> <code>asin</code> <code>acos</code>
|
||||
<code>atan</code> <code>sinh</code> <code>cosh</code> <code>tanh</code>
|
||||
<code>asinh</code> <code>acosh</code> <code>atanh</code>
|
||||
<code>fmod</code></h4>
|
||||
|
||||
<p>The functions <code>sqrt</code>, <code>log</code>, <code>exp</code>,
|
||||
<code>sin</code>, <code>cos</code>, <code>tan</code>, <code>asin</code>,
|
||||
<code>acos</code>, <code>atan</code>, <code>sinh</code>, <code>cosh</code>,
|
||||
<code>tanh</code>, <code>asinh</code>, <code>acosh</code>,
|
||||
<code>atanh</code> are also defined. There is not much to say; these
|
||||
functions extend the traditional functions to the intervals and respect the
|
||||
basic property of interval arithmetic. They use the <a href=
|
||||
"checking.htm">checking</a> policy to produce empty intervals when the
|
||||
input interval is strictly outside of the domain of the function.</p>
|
||||
|
||||
<p>The function <code>fmod(interval x, interval y)</code> expects the lower
|
||||
bound of <code>y</code> to be strictly positive and returns an interval
|
||||
<code>z</code> such as <code>0 <= z.lower() < y.upper()</code> and
|
||||
such as <code>z</code> is a superset of <code>x-n*y</code> (with
|
||||
<code>n</code> being an integer). So, if the two arguments are positive
|
||||
singletons, this function <code>fmod(interval, interval)</code> will behave
|
||||
like the traditional function <code>fmod(double, double)</code>.</p>
|
||||
|
||||
<p>Please note that <code>fmod</code> does not respect the inclusion
|
||||
property of arithmetic interval. For example, the result of
|
||||
<code>fmod</code>([13,17],[7,8]) should be [0,8] (since it must contain
|
||||
[0,3] and [5,8]). But this answer is not really useful when the purpose is
|
||||
to restrict an interval in order to compute a periodic function. It is the
|
||||
reason why <code>fmod</code> will answer [5,10].</p>
|
||||
|
||||
<h4><code>add</code> <code>sub</code> <code>mul</code>
|
||||
<code>div</code></h4>
|
||||
|
||||
<p>These four functions take two numbers and return the enclosing interval
|
||||
for the operations. It avoids converting a number to an interval before an
|
||||
operation, it can result in a better code with poor optimizers.</p>
|
||||
|
||||
<h3>Constants</h3>
|
||||
|
||||
<p>Some constants are hidden in the
|
||||
<code>boost::numeric::interval_lib</code> namespace. They need to be
|
||||
explicitely templated by the interval type. The functions are
|
||||
<code>pi<I>()</code>, <code>pi_half<I>()</code> and
|
||||
<code>pi_twice<I>()</code>, and they return an object of interval
|
||||
type <code>I</code>. Their respective values are π, π/2 and
|
||||
2π.</p>
|
||||
|
||||
<h3>Exception throwing</h3>
|
||||
|
||||
<p>The interval class and all the functions defined around this class never
|
||||
throw any exceptions by themselves. However, it does not mean that an
|
||||
operation will never throw an exception. For example, let's consider the
|
||||
copy constructor. As explained before, it is the default copy constructor
|
||||
generated by the compiler. So it will not throw an exception if the copy
|
||||
constructor of the base type does not throw an exception.</p>
|
||||
|
||||
<p>The same situation applies to all the functions: exceptions will only be
|
||||
thrown if the base type or one of the two policies throws an exception.</p>
|
||||
|
||||
<h2 id="interval_lib">Interval Support Library</h2>
|
||||
|
||||
<p>The interval support library consists of a collection of classes that
|
||||
can be used and combined to fabricate almost various commonly-needed
|
||||
interval policies. In contrast to the basic classes and functions which are
|
||||
used in conjunction with <code>interval<T></code> (and the default
|
||||
policies as the implicit second template parameter in this type), which
|
||||
belong simply to the namespace <code>boost</code>, these components belong
|
||||
to the namespace <code>boost::numeric::interval_lib</code>.</p>
|
||||
|
||||
<p>We merely give the synopsis here and defer each section to a separate
|
||||
web page since it is only intended for the advanced user. This allows to
|
||||
expand on each topic with examples, without unduly stretching the limits of
|
||||
this document.</p>
|
||||
|
||||
<h4>Synopsis</h4>
|
||||
<pre>
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace interval_lib {
|
||||
|
||||
<span style=
|
||||
"color: #FF0000">/* built-in rounding policy and its specializations */</span>
|
||||
template <class T> struct rounded_math;
|
||||
template <> struct rounded_math<float>;
|
||||
template <> struct rounded_math<double>;
|
||||
template <> struct rounded_math<long double>;
|
||||
|
||||
<span style=
|
||||
"color: #FF0000">/* built-in rounding construction blocks */</span>
|
||||
template <class T> struct rounding_control;
|
||||
|
||||
template <class T, class Rounding = rounding_control<T> > struct rounded_arith_exact;
|
||||
template <class T, class Rounding = rounding_control<T> > struct rounded_arith_std;
|
||||
template <class T, class Rounding = rounding_control<T> > struct rounded_arith_opp;
|
||||
|
||||
template <class T, class Rounding> struct rounded_transc_dummy;
|
||||
template <class T, class Rounding = rounded_arith_exact<T> > struct rounded_transc_exact;
|
||||
template <class T, class Rounding = rounded_arith_std <T> > struct rounded_transc_std;
|
||||
template <class T, class Rounding = rounded_arith_opp <T> > struct rounded_transc_opp;
|
||||
|
||||
template <class Rounding> struct save_state;
|
||||
template <class Rounding> struct save_state_nothing;
|
||||
|
||||
<span style="color: #FF0000">/* built-in checking policies */</span>
|
||||
template <class T> struct checking_base;
|
||||
template <class T, class Checking = checking_base<T>, class Exception = exception_create_empty> struct checking_no_empty;
|
||||
template <class T, class Checking = checking_base<T> > struct checking_no_nan;
|
||||
template <class T, class Checking = checking_base<T>, class Exception = exception_invalid_number> struct checking_catch_nan;
|
||||
template <class T> struct checking_strict;
|
||||
|
||||
<span style=
|
||||
"color: #FF0000">/* some metaprogramming to manipulate interval policies */</span>
|
||||
template <class Rounding, class Checking> struct policies;
|
||||
template <class OldInterval, class NewRounding> struct change_rounding;
|
||||
template <class OldInterval, class NewChecking> struct change_checking;
|
||||
template <class OldInterval> struct unprotect;
|
||||
|
||||
<span style=
|
||||
"color: #FF0000">/* constants, need to be explicitly templated */</span>
|
||||
template<class I> I pi();
|
||||
template<class I> I pi_half();
|
||||
template<class I> I pi_twice();
|
||||
|
||||
<span style="color: #FF0000">/* interval explicit comparison functions:
|
||||
* the mode can be cer=certainly or pos=possibly,
|
||||
* the function lt=less_than, gt=greater_than, le=less_than_or_equal_to, ge=greater_than_or_equal_to
|
||||
* eq=equal_to, ne= not_equal_to */</span>
|
||||
template <class T, class Policies> bool cerlt(const interval<T, Policies>& x, const interval<T, Policies>& 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);
|
||||
|
||||
template <class T, class Policies> bool cerle(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool cerle(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool cerle(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> bool cergt(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool cergt(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool cergt(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> bool cerge(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool cerge(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool cerge(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> bool cereq(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool cereq(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool cereq(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> bool cerne(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool cerne(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool cerne(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> bool poslt(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool poslt(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool poslt(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> bool posle(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool posle(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool posle(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> bool posgt(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool posgt(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool posgt(const T& x, const interval<T, Policies> & y);
|
||||
|
||||
template <class T, class Policies> bool posge(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool posge(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool posge(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> bool poseq(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool poseq(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool poseq(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
template <class T, class Policies> bool posne(const interval<T, Policies>& x, const interval<T, Policies>& y);
|
||||
template <class T, class Policies> bool posne(const interval<T, Policies>& x, const T& y);
|
||||
template <class T, class Policies> bool posne(const T& x, const interval<T, Policies>& y);
|
||||
|
||||
<span style="color: #FF0000">/* comparison namespaces */</span>
|
||||
namespace compare {
|
||||
namespace certain;
|
||||
namespace possible;
|
||||
namespace lexicographic;
|
||||
namespace set;
|
||||
namespace tribool;
|
||||
} // namespace compare
|
||||
|
||||
} // namespace interval_lib
|
||||
} // namespace numeric
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<p>Each component of the interval support library is detailed in its own
|
||||
page.</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="comparisons.htm">Comparisons</a></li>
|
||||
|
||||
<li><a href="rounding.htm">Rounding</a></li>
|
||||
|
||||
<li><a href="checking.htm">Checking</a></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="dangers">Common Pitfalls and Dangers</h2>
|
||||
|
||||
<h4>Comparisons</h4>
|
||||
|
||||
<p>One of the biggest problems is probably the correct use of the
|
||||
comparison functions and operators. First, functions and operators do not
|
||||
try to know if two intervals are the same mathematical object. So, if the
|
||||
comparison used is "certain", then <code>x != x</code> is always true
|
||||
unless <code>x</code> is a singleton interval; and the same problem arises
|
||||
with <code>cereq</code> and <code>cerne</code>.</p>
|
||||
|
||||
<p>Another misleading interpretation of the comparison is: you cannot
|
||||
always expect [a,b] < [c,d] to be !([a,b] >= [c,d]) since the
|
||||
comparison is not necessarily total. Equality and less comparison should be
|
||||
seen as two distincts relational operators. However the default comparison
|
||||
operators do respect this property since they throw an exception whenever
|
||||
[a,b] and [c,d] overlap.</p>
|
||||
|
||||
<h4>Interval values and references</h4>
|
||||
|
||||
<p>This problem is a corollary of the previous problem with <code>x !=
|
||||
x</code>. All the functions of the library only consider the value of an
|
||||
interval and not the reference of an interval. In particular, you should
|
||||
not expect (unless <code>x</code> is a singleton) the following values to
|
||||
be equal: <code>x/x</code> and 1, <code>x*x</code> and
|
||||
<code>square(x)</code>, <code>x-x</code> and 0, etc. So the main cause of
|
||||
wide intervals is that interval arithmetic does not identify different
|
||||
occurrences of the same variable. So, whenever possible, the user has to
|
||||
rewrite the formulas to eliminate multiple occurences of the same variable.
|
||||
For example, <code>square(x)-2*x</code> is far less precise than
|
||||
<code>square(x-1)-1</code>.</p>
|
||||
|
||||
<h4>Unprotected rounding</h4>
|
||||
|
||||
<p>As explained in <a href="rounding.htm#perf">this section</a>, a good way
|
||||
to speed up computations when the base type is a basic floating-point type
|
||||
is to unprotect the intervals at the hot spots of the algorithm. This
|
||||
method is safe and really an improvement for interval computations. But
|
||||
please remember that any basic floating-point operation executed inside the
|
||||
unprotection blocks will probably have an undefined behavior (but only for
|
||||
the current thread). And do not forget to create a rounding object as
|
||||
explained in the <a href="rounding.htm#perfexp">example</a>.</p>
|
||||
|
||||
<h2 id="rationale">Rationale</h2>
|
||||
|
||||
<p>The purpose of this library is to provide an efficient and generalized
|
||||
way to deal with interval arithmetic through the use of a templatized class
|
||||
<code>boost::numeric::interval</code>. The big contention for which we provide a
|
||||
rationale is the format of this class template.</p>
|
||||
|
||||
<p>It would have been easier to provide a class interval whose base type is
|
||||
double. Or to follow <code>std::complex</code> and allow only
|
||||
specializations for <code>float</code>, <code>double</code>, and <code>long
|
||||
double</code>. We decided not to do this to allow intervals on custom
|
||||
types, e.g. fixed-precision bigfloat library types (MPFR, etc), rational
|
||||
numbers, and so on.</p>
|
||||
|
||||
<p><strong>Policy design.</strong> Although it was tempting to make it a
|
||||
class template with only one template argument, the diversity of uses for
|
||||
an interval arithmetic practically forced us to use policies. The behavior
|
||||
of this class can be fixed by two policies. These policies are packaged
|
||||
into a single policy class, rather than making <code>interval</code> with
|
||||
three template parameters. This is both for ease of use (the policy class
|
||||
can be picked by default) and for readability.</p>
|
||||
|
||||
<p>The first policy provides all the mathematical functions on the base
|
||||
type needed to define the functions on the interval type. The second one
|
||||
sets the way exceptional cases encountered during computations are
|
||||
handled.</p>
|
||||
|
||||
<p>We could foresee situations where any combination of these policies
|
||||
would be appropriate. Moreover, we wanted to enable the user of the library
|
||||
to reuse the <code>interval</code> class template while at the same time
|
||||
choosing his own behavior. See this <a href="guide.htm">page</a> for some
|
||||
examples.</p>
|
||||
|
||||
<p><strong>Rounding policy.</strong> The library provides specialized
|
||||
implementations of the rounding policy for the primitive types float and
|
||||
double. In order for these implementations to be correct and fast, the
|
||||
library needs to work a lot with rounding modes. Some processors are
|
||||
directly dealt with and some mechanisms are provided in order to speed up
|
||||
the computations. It seems to be heavy and hazardous optimizations for a
|
||||
gain of only a few computer cycles; but in reality, the speed-up factor can
|
||||
easily go past 2 or 3 depending on the computer. Moreover, these
|
||||
optimizations do not impact the interface in any major way (with the design
|
||||
we have chosen, everything can be added by specialization or by passing
|
||||
different template parameters).</p>
|
||||
|
||||
<p><strong>Pred/succ.</strong> In a previous version, two functions
|
||||
<code>pred</code> and <code>succ</code>, with various corollaries like
|
||||
<code>widen</code>, were supplied. The intent was to enlarge the interval
|
||||
by one ulp (as little as possible), e.g. to ensure the inclusion property.
|
||||
Since making interval a template of T, we could not define <i>ulp</i> for a
|
||||
random parameter. In turn, rounding policies let us eliminate entirely the
|
||||
use of ulp while making the intervals tighter (if a result is a
|
||||
representable singleton, there is no use to widen the interval). We decided
|
||||
to drop those functions.</p>
|
||||
|
||||
<p><strong>Specialization of <code>std::less</code>.</strong> Since the
|
||||
operator <code><</code> depends on the comparison namespace locally
|
||||
chosen by the user, it is not possible to correctly specialize
|
||||
<code>std::less</code>. So you have to explicitely provide such a class to
|
||||
all the algorithms and templates that could require it (for example,
|
||||
<code>std::map</code>).</p>
|
||||
|
||||
<p><strong>Input/output.</strong> The interval library does not include I/O
|
||||
operators. Printing an interval value allows a lot of customization: some
|
||||
people may want to output the bounds, others may want to display the median
|
||||
and the width of intervals, and so on. The example file io.cpp shows some
|
||||
possibilities and may serve as a foundation in order for the user to define
|
||||
her own operators.</p>
|
||||
|
||||
<p><strong>Mixed operations with integers.</strong> When using and reusing
|
||||
template codes, it is common there are operations like <code>2*x</code>.
|
||||
However, the library does not provide them by default because the
|
||||
conversion from <code>int</code> to the base number type is not always
|
||||
correct (think about the conversion from a 32bit integer to a single
|
||||
precision floating-point number). So the functions have been put in a
|
||||
separate header and the user needs to include them explicitely if she wants
|
||||
to benefit from these mixed operators. Another point, there is no mixed
|
||||
comparison operators due to the technical way they are defined.</p>
|
||||
|
||||
<p><strong>Interval-aware functions.</strong> All the functions defined by
|
||||
the library are obviously aware they manipulate intervals and they do it
|
||||
accordingly to general interval arithmetic principles. Consequently they
|
||||
may have a different behavior than the one commonly encountered with
|
||||
functions not interval-aware. For example, <code>max</code> is defined by
|
||||
canonical set extension and the result is not always one of the two
|
||||
arguments (if the intervals do not overlap, then the result is one of the
|
||||
two intervals).</p>
|
||||
|
||||
<p>This behavior is different from <code>std::max</code> which returns a
|
||||
reference on one of its arguments. So if the user expects a reference to be
|
||||
returned, she should use <code>std::max</code> since it is exactly what
|
||||
this function does. Please note that <code>std::max</code> will throw an
|
||||
exception when the intervals overlap. This behavior does not predate the
|
||||
one described by the C++ standard since the arguments are not "equivalent"
|
||||
and it allows to have an equivalence between <code>a <= b</code> and
|
||||
<code>&b == &std::max(a,b)</code>(some particular cases may be
|
||||
implementation-defined). However it is different from the one described by
|
||||
SGI since it does not return the first argument even if "neither is greater
|
||||
than the other".</p>
|
||||
|
||||
<h2 id="acks">History and Acknowledgments</h2>
|
||||
|
||||
<p>This library was mostly inspired by previous work from Jens Maurer. Some
|
||||
discussions about his work are reproduced <a href=
|
||||
"http://www.mscs.mu.edu/%7Egeorgec/IFAQ/maurer1.html">here</a>. Jeremy Siek
|
||||
and Maarten Keijzer provided some rounding control for MSVC and Sparc
|
||||
platforms.</p>
|
||||
|
||||
<p>Guillaume Melquiond, Hervé Brönnimann and Sylvain Pion
|
||||
started from the library left by Jens and added the policy design.
|
||||
Guillaume and Sylvain worked hard on the code, especially the porting and
|
||||
mostly tuning of the rounding modes to the different architectures.
|
||||
Guillaume did most of the coding, while Sylvain and Hervé have
|
||||
provided some useful comments in order for this library to be written.
|
||||
Hervé reorganized and wrote chapters of the documentation based on
|
||||
Guillaume's great starting point.</p>
|
||||
|
||||
<p>This material is partly based upon work supported by the National
|
||||
Science Foundation under NSF CAREER Grant CCR-0133599. Any opinions,
|
||||
findings and conclusions or recommendations expressed in this material are
|
||||
those of the author(s) and do not necessarily reflect the views of the
|
||||
National Science Foundation (NSF).</p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-25<!--webbot bot="Timestamp" endspan i-checksum="12174" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University<br>
|
||||
Copyright © 2003-2006 Guillaume Melquiond, ENS Lyon</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,176 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Numbers Requirements</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1>Numbers Requirements</h1>
|
||||
|
||||
<p>What we call "number" is the base type of the <code>interval</code>
|
||||
class. The interval library expect a lot of properties from this base type
|
||||
in order to respect the inclusion property. All these properties are
|
||||
already detailed in the other sections of this documentation; but we will
|
||||
try to summarize them here.</p>
|
||||
|
||||
<h3>Ordering</h3>
|
||||
|
||||
<p>The numbers need to be supplied with an ordering. This ordering
|
||||
expresses itself by the operators <code>< <= => > == !=</code>.
|
||||
It must be a total order (reflexivity, antisymmetry, transitivity, and each
|
||||
pair of numbers is ordered). So <code>complex<T></code> will not be a
|
||||
good candidate for the base type; if you need the inclusion property of
|
||||
interval property, you should use <code>complex< interval<T>
|
||||
></code> in place of <code>interval< complex<T> ></code>
|
||||
(but unfortunately, <code>complex</code> only provides specialization).</p>
|
||||
|
||||
<p>Please note that invalid numbers are not concerned by the order; it can
|
||||
even be conceptually better if a comparison with these invalid numbers is
|
||||
always <code>false</code> (except for <code>!=</code>). If your checking
|
||||
policy uses <code>interval_lib::checking_base</code> and your base type
|
||||
contains invalid numbers, then this property is needed:
|
||||
<code>nan!=nan</code> (here <code>nan</code> is an invalid number). If this
|
||||
property is not present, then you should not use <code>checking_base</code>
|
||||
directly.</p>
|
||||
|
||||
<p>Interval arithmetic involves a lot of comparison to zero. By default,
|
||||
they are done by comparing the numbers to
|
||||
<code>static_cast<T>(0)</code>. However, if the format of the numbers
|
||||
allows some faster comparisons when dealing with zero, the template
|
||||
functions in the <code>interval_lib::user</code> namespace can be
|
||||
specialized:</p>
|
||||
<pre>
|
||||
namespace user {
|
||||
template<class T> inline bool is_zero(T const &v) { return v == static_cast<T>(0); }
|
||||
template<class T> inline bool is_neg (T const &v) { return v < static_cast<T>(0); }
|
||||
template<class T> inline bool is_pos (T const &v) { return v > static_cast<T>(0); }
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Numeric limits</h3>
|
||||
|
||||
<p>Another remark about the checking policy. It normally is powerful enough
|
||||
to handle the exceptional behavior that the basic type could induce; in
|
||||
particular infinite and invalid numbers (thanks to the four functions
|
||||
<code>pos_inf</code>, <code>neg_inf</code>, <code>nan</code> and
|
||||
<code>is_nan</code>). However, if you use
|
||||
<code>interval_lib::checking_base</code> (and the default checking policy
|
||||
uses it), your base type should have a correctly specialized
|
||||
<code>std::numeric_limits<T></code>. In particular, the values
|
||||
<code>has_infinity</code> and <code>has_quiet_NaN</code>, and the functions
|
||||
<code>infinity</code> and <code>quiet_NaN</code> should be accordingly
|
||||
defined.</p>
|
||||
|
||||
<p>So, to summarize, if you do not rely on the default policy and do not
|
||||
use <code>interval_lib::checking_base</code>, it is not necessary to have a
|
||||
specialization of the numeric limits for your base type.</p>
|
||||
|
||||
<h3>Mathematical properties</h3>
|
||||
|
||||
<p>Ensuring the numbers are correctly ordered is not enough. The basic
|
||||
operators should also respect some properties depending on the order. Here
|
||||
they are:</p>
|
||||
|
||||
<ul>
|
||||
<li>0 ≤ <i>x</i> ⇒ -<i>x</i> ≤ 0</li>
|
||||
|
||||
<li><i>x</i> ≤ <i>y</i> ⇒ -<i>y</i> ≤ -<i>x</i></li>
|
||||
|
||||
<li><i>x</i> ≤ <i>y</i> ⇒ <i>x</i>+<i>z</i> ≤
|
||||
<i>y</i>+<i>z</i></li>
|
||||
|
||||
<li><i>x</i> ≤ <i>y</i> and <i>z</i> ≥ 0 ⇒
|
||||
<i>x</i>×<i>z</i> ≤ <i>y</i>×<i>z</i></li>
|
||||
|
||||
<li>0 < <i>x</i> ≤ <i>y</i> ⇒ 0 < 1/<i>y</i> ≤
|
||||
1/<i>x</i></li>
|
||||
</ul>
|
||||
|
||||
<p>The previous properties are also used (and enough) for <code>abs</code>,
|
||||
<code>square</code> and <code>pow</code>. For all the transcendental
|
||||
functions (including <code>sqrt</code>), other properties are needed. These
|
||||
functions should have the same properties than the corresponding real
|
||||
functions. For example, the expected properties for <code>cos</code>
|
||||
are:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>cos</code> is defined for all the valid numbers;</li>
|
||||
|
||||
<li>it is 2π-periodic;</li>
|
||||
|
||||
<li><code>cos</code>(2π-<i>x</i>) is equal to
|
||||
<code>cos</code>(<i>x</i>);</li>
|
||||
|
||||
<li><code>cos</code> is a decreasing function on [0,2π].</li>
|
||||
</ul>
|
||||
|
||||
<h3>Rounding</h3>
|
||||
|
||||
<p>If you work with a base type and no inexact result is ever computed, you
|
||||
can skip the rest of this paragraph. You can also skip it if you are not
|
||||
interested in the inclusion property (if approximate results are enough).
|
||||
If you are still reading, it is probably because you want to know the basic
|
||||
properties the rounding policy should validate.</p>
|
||||
|
||||
<p>Whichever operation or function you consider, the following property
|
||||
should be respected: <code>f_down(x,y) <= f(x,y) <= f_up(x,y)</code>.
|
||||
Here, <code>f</code> denotes the infinitely precise function computed and
|
||||
<code>f_down</code> and <code>f_up</code> are functions which return
|
||||
possibly inexact values but of the correct type (the base type). If
|
||||
possible, they should try to return the nearest representable value, but it
|
||||
is not always easy.</p>
|
||||
|
||||
<h3>Constants</h3>
|
||||
|
||||
<p>In order for the trigonometric functions to correctly work, the library
|
||||
need to know the value of the π constant (and also π/2 and 2π).
|
||||
Since these constants may not be representable in the base type, the
|
||||
library does not have to know the exact value: a lower bound and an upper
|
||||
bound are enough. If these values are not provided by the user, the default
|
||||
values will be used: they are integer values (so π is bounded by 3 and
|
||||
4).</p>
|
||||
|
||||
<h3>Operators and conversions</h3>
|
||||
|
||||
<p>As explained at the beginning, the comparison operators should be
|
||||
defined for the base type. The rounding policy defines a lot of functions
|
||||
used by the interval library. So the arithmetic operators do not need to be
|
||||
defined for the base type (unless required by one of the predefined
|
||||
classes). However, there is an exception: the unary minus need to be
|
||||
defined. Moreover, this operator should only provide exact results; it is
|
||||
the reason why the rounding policy does not provide some negation
|
||||
functions.</p>
|
||||
|
||||
<p>The conversion from <code>int</code> to the base type needs to be
|
||||
defined (only a few values need to be available: -1, 0, 1, 2). The
|
||||
conversion the other way around is provided by the rounding policy
|
||||
(<code>int_down</code> and <code>int_up</code> members); and no other
|
||||
conversion is strictly needed. However, it may be valuable to provide as
|
||||
much conversions as possible in the rounding policy (<code>conv_down</code>
|
||||
and <code>conv_up</code> members) in order to benefit from interval
|
||||
conversions.</p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University<br>
|
||||
Copyright © 2004 Guillaume Melquiond</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Policies</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1>Policies</h1>
|
||||
|
||||
<p>The <code>interval</code> template requires two arguments. The first
|
||||
corresponds to the base type chosen for the bounds. And the second defines
|
||||
the <a href="rounding.htm">rounding</a> and <a href=
|
||||
"checking.htm">checking</a> behaviors of the newly constructed class. This
|
||||
second argument is not mandatory but may need some customizations. In order
|
||||
to ease the manipulations, some helper templates are provided in
|
||||
<code>interval/policies.hpp</code>.</p>
|
||||
<pre>
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace interval_lib {
|
||||
|
||||
template<class Rounding, class Checking>
|
||||
struct policies {
|
||||
typedef Rounding rounding;
|
||||
typedef Checking checking;
|
||||
};
|
||||
|
||||
template<class OldInterval, class NewRounding>
|
||||
struct change_rounding {
|
||||
typedef ... type;
|
||||
};
|
||||
|
||||
template<class OldInterval, class NewChecking>
|
||||
struct change_checking {
|
||||
typedef ... type;
|
||||
};
|
||||
|
||||
template<class OldInterval>
|
||||
struct unprotect {
|
||||
typedef ... type;
|
||||
};
|
||||
|
||||
} // namespace interval_lib
|
||||
} // namespace numeric
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<p>The <code>policies</code> template should be used whenever the user
|
||||
needs to define a policy structure for an <code>interval</code> class.
|
||||
<code>change_rounding</code> and <code>change_checking</code> can be used
|
||||
to get the type of a new interval by changing one of the policies of an old
|
||||
interval; the new type is available thanks to the type definition
|
||||
<code>type</code>. Finally, <code>unprotect</code> looks like
|
||||
<code>change_rounding</code> and directly changes the rounding of an
|
||||
interval to its unprotected version (a better explanation is available
|
||||
<a href="rounding.htm#perfexp">here</a>).</p>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,632 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Rounding Policies</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1>Rounding Policies</h1>
|
||||
|
||||
<p>In order to be as general as possible, the library uses a class to
|
||||
compute all the necessary functions rounded upward or downward. This class
|
||||
is the first parameter of <code>policies</code>, it is also the type named
|
||||
<code>rounding</code> in the policy definition of
|
||||
<code>interval</code>.</p>
|
||||
|
||||
<p>By default, it is <code>interval_lib::rounded_math<T></code>. The
|
||||
class <code>interval_lib::rounded_math</code> is already specialized for
|
||||
the standard floating types (<code>float</code> , <code>double</code> and
|
||||
<code>long double</code>). So if the base type of your intervals is not one
|
||||
of these, a good solution would probably be to provide a specialization of
|
||||
this class. But if the default specialization of
|
||||
<code>rounded_math<T></code> for <code>float</code>,
|
||||
<code>double</code>, or <code>long double</code> is not what you seek, or
|
||||
you do not want to specialize
|
||||
<code>interval_lib::rounded_math<T></code> (say because you prefer to
|
||||
work in your own namespace) you can also define your own rounding policy
|
||||
and pass it directly to <code>interval_lib::policies</code>.</p>
|
||||
|
||||
<h2>Requirements</h2>
|
||||
|
||||
<p>Here comes what the class is supposed to provide. The domains are
|
||||
written next to their respective functions (as you can see, the functions
|
||||
do not have to worry about invalid values, but they have to handle infinite
|
||||
arguments).</p>
|
||||
<pre>
|
||||
/* Rounding requirements */
|
||||
struct rounding {
|
||||
// default constructor, destructor
|
||||
rounding();
|
||||
~rounding();
|
||||
// mathematical operations
|
||||
T add_down(T, T); // [-∞;+∞][-∞;+∞]
|
||||
T add_up (T, T); // [-∞;+∞][-∞;+∞]
|
||||
T sub_down(T, T); // [-∞;+∞][-∞;+∞]
|
||||
T sub_up (T, T); // [-∞;+∞][-∞;+∞]
|
||||
T mul_down(T, T); // [-∞;+∞][-∞;+∞]
|
||||
T mul_up (T, T); // [-∞;+∞][-∞;+∞]
|
||||
T div_down(T, T); // [-∞;+∞]([-∞;+∞]-{0})
|
||||
T div_up (T, T); // [-∞;+∞]([-∞;+∞]-{0})
|
||||
T sqrt_down(T); // ]0;+∞]
|
||||
T sqrt_up (T); // ]0;+∞]
|
||||
T exp_down(T); // [-∞;+∞]
|
||||
T exp_up (T); // [-∞;+∞]
|
||||
T log_down(T); // ]0;+∞]
|
||||
T log_up (T); // ]0;+∞]
|
||||
T cos_down(T); // [0;2π]
|
||||
T cos_up (T); // [0;2π]
|
||||
T tan_down(T); // ]-π/2;π/2[
|
||||
T tan_up (T); // ]-π/2;π/2[
|
||||
T asin_down(T); // [-1;1]
|
||||
T asin_up (T); // [-1;1]
|
||||
T acos_down(T); // [-1;1]
|
||||
T acos_up (T); // [-1;1]
|
||||
T atan_down(T); // [-∞;+∞]
|
||||
T atan_up (T); // [-∞;+∞]
|
||||
T sinh_down(T); // [-∞;+∞]
|
||||
T sinh_up (T); // [-∞;+∞]
|
||||
T cosh_down(T); // [-∞;+∞]
|
||||
T cosh_up (T); // [-∞;+∞]
|
||||
T tanh_down(T); // [-∞;+∞]
|
||||
T tanh_up (T); // [-∞;+∞]
|
||||
T asinh_down(T); // [-∞;+∞]
|
||||
T asinh_up (T); // [-∞;+∞]
|
||||
T acosh_down(T); // [1;+∞]
|
||||
T acosh_up (T); // [1;+∞]
|
||||
T atanh_down(T); // [-1;1]
|
||||
T atanh_up (T); // [-1;1]
|
||||
T median(T, T); // [-∞;+∞][-∞;+∞]
|
||||
T int_down(T); // [-∞;+∞]
|
||||
T int_up (T); // [-∞;+∞]
|
||||
// conversion functions
|
||||
T conv_down(U);
|
||||
T conv_up (U);
|
||||
// unprotected rounding class
|
||||
typedef ... unprotected_rounding;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<p>The constructor and destructor of the rounding class have a very
|
||||
important semantic requirement: they are responsible for setting and
|
||||
resetting the rounding modes of the computation on T. For instance, if T is
|
||||
a standard floating point type and floating point computation is performed
|
||||
according to the Standard IEEE 754, the constructor can save the current
|
||||
rounding state, each <code>_up</code> (resp. <code>_down</code>) function
|
||||
will round up (resp. down), and the destructor will restore the saved
|
||||
rounding state. Indeed this is the behavior of the default rounding
|
||||
policy.</p>
|
||||
|
||||
<p>The meaning of all the mathematical functions up until
|
||||
<code>atanh_up</code> is clear: each function returns number representable
|
||||
in the type <code>T</code> which is a lower bound (for <code>_down</code>)
|
||||
or upper bound (for <code>_up</code>) on the true mathematical result of
|
||||
the corresponding function. The function <code>median</code> computes the
|
||||
average of its two arguments rounded to its nearest representable number.
|
||||
The functions <code>int_down</code> and <code>int_up</code> compute the
|
||||
nearest integer smaller or bigger than their argument. Finally,
|
||||
<code>conv_down</code> and <code>conv_up</code> are responsible of the
|
||||
conversions of values of other types to the base number type: the first one
|
||||
must round down the value and the second one must round it up.</p>
|
||||
|
||||
<p>The type <code>unprotected_rounding</code> allows to remove all
|
||||
controls. For reasons why one might to do this, see the <a href=
|
||||
"#Protection">protection</a> paragraph below.</p>
|
||||
|
||||
<h2>Overview of the provided classes</h2>
|
||||
|
||||
<p>A lot of classes are provided. The classes are organized by level. At
|
||||
the bottom is the class <code>rounding_control</code>. At the next level
|
||||
come <code>rounded_arith_exact</code>, <code>rounded_arith_std</code> and
|
||||
<code>rounded_arith_opp</code>. Then there are
|
||||
<code>rounded_transc_dummy</code>, <code>rounded_transc_exact</code>,
|
||||
<code>rounded_transc_std</code> and <code>rounded_transc_opp</code>. And
|
||||
finally are <code>save_state</code> and <code>save_state_nothing</code>.
|
||||
Each of these classes provide a set of members that are required by the
|
||||
classes of the next level. For example, a <code>rounded_transc_...</code>
|
||||
class needs the members of a <code>rounded_arith_...</code> class.</p>
|
||||
|
||||
<p>When they exist in two versions <code>_std</code> and <code>_opp</code>,
|
||||
the first one does switch the rounding mode each time, and the second one
|
||||
tries to keep it oriented toward plus infinity. The main purpose of the
|
||||
<code>_opp</code> version is to speed up the computations through the use
|
||||
of the "opposite trick" (see the <a href="#perf">performance notes</a>).
|
||||
This version requires the rounding mode to be upward before entering any
|
||||
computation functions of the class. It guarantees that the rounding mode
|
||||
will still be upward at the exit of the functions.</p>
|
||||
|
||||
<p>Please note that it is really a very bad idea to mix the
|
||||
<code>_opp</code> version with the <code>_std</code> since they do not have
|
||||
compatible properties.</p>
|
||||
|
||||
<p>There is a third version named <code>_exact</code> which computes the
|
||||
functions without changing the rounding mode. It is an "exact" version
|
||||
because it is intended for a base type that produces exact results.</p>
|
||||
|
||||
<p>The last version is the <code>_dummy</code> version. It does not do any
|
||||
computations but still produces compatible results.</p>
|
||||
|
||||
<p>Please note that it is possible to use the "exact" version for an
|
||||
inexact base type, e.g. <code>float</code> or <code>double</code>. In that
|
||||
case, the inclusion property is no longer guaranteed, but this can be
|
||||
useful to speed up the computation when the inclusion property is not
|
||||
desired strictly. For instance, in computer graphics, a small error due to
|
||||
floating-point roundoff is acceptable as long as an approximate version of
|
||||
the inclusion property holds.</p>
|
||||
|
||||
<p>Here comes what each class defines. Later, when they will be described
|
||||
more thoroughly, these members will not be repeated. Please come back here
|
||||
in order to see them. Inheritance is also used to avoid repetitions.</p>
|
||||
<pre>
|
||||
template <class T>
|
||||
struct rounding_control
|
||||
{
|
||||
typedef ... rounding_mode;
|
||||
void set_rounding_mode(rounding_mode);
|
||||
void get_rounding_mode(rounding_mode&);
|
||||
void downward ();
|
||||
void upward ();
|
||||
void to_nearest();
|
||||
T to_int(T);
|
||||
T force_rounding(T);
|
||||
};
|
||||
|
||||
template <class T, class Rounding>
|
||||
struct rounded_arith_... : Rounding
|
||||
{
|
||||
void init();
|
||||
T add_down(T, T);
|
||||
T add_up (T, T);
|
||||
T sub_down(T, T);
|
||||
T sub_up (T, T);
|
||||
T mul_down(T, T);
|
||||
T mul_up (T, T);
|
||||
T div_down(T, T);
|
||||
T div_up (T, T);
|
||||
T sqrt_down(T);
|
||||
T sqrt_up (T);
|
||||
T median(T, T);
|
||||
T int_down(T);
|
||||
T int_up (T);
|
||||
};
|
||||
|
||||
template <class T, class Rounding>
|
||||
struct rounded_transc_... : Rounding
|
||||
{
|
||||
T exp_down(T);
|
||||
T exp_up (T);
|
||||
T log_down(T);
|
||||
T log_up (T);
|
||||
T cos_down(T);
|
||||
T cos_up (T);
|
||||
T tan_down(T);
|
||||
T tan_up (T);
|
||||
T asin_down(T);
|
||||
T asin_up (T);
|
||||
T acos_down(T);
|
||||
T acos_up (T);
|
||||
T atan_down(T);
|
||||
T atan_up (T);
|
||||
T sinh_down(T);
|
||||
T sinh_up (T);
|
||||
T cosh_down(T);
|
||||
T cosh_up (T);
|
||||
T tanh_down(T);
|
||||
T tanh_up (T);
|
||||
T asinh_down(T);
|
||||
T asinh_up (T);
|
||||
T acosh_down(T);
|
||||
T acosh_up (T);
|
||||
T atanh_down(T);
|
||||
T atanh_up (T);
|
||||
};
|
||||
|
||||
template <class Rounding>
|
||||
struct save_state_... : Rounding
|
||||
{
|
||||
save_state_...();
|
||||
~save_state_...();
|
||||
typedef ... unprotected_rounding;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
<pre>
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace interval_lib {
|
||||
|
||||
<span style="color: #FF0000">/* basic rounding control */</span>
|
||||
template <class T> struct rounding_control;
|
||||
|
||||
<span style="color: #FF0000">/* arithmetic functions rounding */</span>
|
||||
template <class T, class Rounding = rounding_control<T> > struct rounded_arith_exact;
|
||||
template <class T, class Rounding = rounding_control<T> > struct rounded_arith_std;
|
||||
template <class T, class Rounding = rounding_control<T> > struct rounded_arith_opp;
|
||||
|
||||
<span style="color: #FF0000">/* transcendental functions rounding */</span>
|
||||
template <class T, class Rounding> struct rounded_transc_dummy;
|
||||
template <class T, class Rounding = rounded_arith_exact<T> > struct rounded_transc_exact;
|
||||
template <class T, class Rounding = rounded_arith_std<T> > struct rounded_transc_std;
|
||||
template <class T, class Rounding = rounded_arith_opp<T> > struct rounded_transc_opp;
|
||||
|
||||
<span style="color: #FF0000">/* rounding-state-saving classes */</span>
|
||||
template <class Rounding> struct save_state;
|
||||
template <class Rounding> struct save_state_nothing;
|
||||
|
||||
<span style="color: #FF0000">/* default policy for type T */</span>
|
||||
template <class T> struct rounded_math;
|
||||
template <> struct rounded_math<float>;
|
||||
template <> struct rounded_math<double>;
|
||||
|
||||
<span style=
|
||||
"color: #FF0000">/* some metaprogramming to convert a protected to unprotected rounding */</span>
|
||||
template <class I> struct unprotect;
|
||||
|
||||
} // namespace interval_lib
|
||||
} // namespace numeric
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2>Description of the provided classes</h2>
|
||||
|
||||
<p>We now describe each class in the order they appear in the definition of
|
||||
a rounding policy (this outermost-to-innermost order is the reverse order
|
||||
from the synopsis).</p>
|
||||
|
||||
<h3 id="Protection">Protection control</h3>
|
||||
|
||||
<p>Protection refers to the fact that the interval operations will be
|
||||
surrounded by rounding mode controls. Unprotecting a class means to remove
|
||||
all the rounding controls. Each rounding policy provides a type
|
||||
<code>unprotected_rounding</code>. The required type
|
||||
<code>unprotected_rounding</code> gives another rounding class that enables
|
||||
to work when nested inside rounding. For example, the first three lines
|
||||
below should all produce the same result (because the first operation is
|
||||
the rounding constructor, and the last is its destructor, which take care
|
||||
of setting the rounding modes); and the last line is allowed to have an
|
||||
undefined behavior (since no rounding constructor or destructor is ever
|
||||
called).</p>
|
||||
<pre>
|
||||
T c; { rounding rnd; c = rnd.add_down(a, b); }
|
||||
T c; { rounding rnd1; { rounding rnd2; c = rnd2.add_down(a, b); } }
|
||||
T c; { rounding rnd1; { rounding::unprotected_rounding rnd2; c = rnd2.add_down(a, b); } }
|
||||
T d; { rounding::unprotected_rounding rnd; d = rnd.add_down(a, b); }
|
||||
</pre>
|
||||
|
||||
<p>Naturally <code>rounding::unprotected_rounding</code> may simply be
|
||||
<code>rounding</code> itself. But it can improve performance if it is a
|
||||
simplified version with empty constructor and destructor. In order to avoid
|
||||
undefined behaviors, in the library, an object of type
|
||||
<code>rounding::unprotected_rounding</code> is guaranteed to be created
|
||||
only when an object of type <code>rounding</code> is already alive. See the
|
||||
<a href="#perf">performance notes</a> for some additional details.</p>
|
||||
|
||||
<p>The support library defines a metaprogramming class template
|
||||
<code>unprotect</code> which takes an interval type <code>I</code> and
|
||||
returns an interval type <code>unprotect<I>::type</code> where the
|
||||
rounding policy has been unprotected. Some information about the types:
|
||||
<code>interval<T, interval_lib::policies<Rounding, _>
|
||||
>::traits_type::rounding</code> <b>is</b> the same type as
|
||||
<code>Rounding</code>, and <code>unprotect<interval<T,
|
||||
interval_lib::policies<Rounding, _> > >::type</code> <b>is</b>
|
||||
the same type as <code>interval<T,
|
||||
interval_lib::policies<Rounding::unprotected, _> ></code>.</p>
|
||||
|
||||
<h3>State saving</h3>
|
||||
|
||||
<p>First comes <code>save_state</code>. This class is responsible for
|
||||
saving the current rounding mode and calling init in its constructor, and
|
||||
for restoring the saved rounding mode in its destructor. This class also
|
||||
defines the <code>unprotected_rounding</code> type.</p>
|
||||
|
||||
<p>If the rounding mode does not require any state-saving or
|
||||
initialization, <code>save_state_nothing</code> can be used instead of
|
||||
<code>save_state</code>.</p>
|
||||
|
||||
<h3>Transcendental functions</h3>
|
||||
|
||||
<p>The classes <code>rounded_transc_exact</code>,
|
||||
<code>rounded_transc_std</code> and <code>rounded_transc_opp</code> expect
|
||||
the std namespace to provide the functions exp log cos tan acos asin atan
|
||||
cosh sinh tanh acosh asinh atanh. For the <code>_std</code> and
|
||||
<code>_opp</code> versions, all these functions should respect the current
|
||||
rounding mode fixed by a call to downward or upward.</p>
|
||||
|
||||
<p><strong>Please note:</strong> Unfortunately, the latter is rarely the
|
||||
case. It is the reason why a class <code>rounded_transc_dummy</code> is
|
||||
provided which does not depend on the functions from the std namespace.
|
||||
There is no magic, however. The functions of
|
||||
<code>rounded_transc_dummy</code> do not compute anything. They only return
|
||||
valid values. For example, <code>cos_down</code> always returns -1. In this
|
||||
way, we do verify the inclusion property for the default implementation,
|
||||
even if this has strictly no value for the user. In order to have useful
|
||||
values, another policy should be used explicitely, which will most likely
|
||||
lead to a violation of the inclusion property. In this way, we ensure that
|
||||
the violation is clearly pointed out to the user who then knows what he
|
||||
stands against. This class could have been used as the default
|
||||
transcendental rounding class, but it was decided it would be better for
|
||||
the compilation to fail due to missing declarations rather than succeed
|
||||
thanks to valid but unusable functions.</p>
|
||||
|
||||
<h3>Basic arithmetic functions</h3>
|
||||
|
||||
<p>The classes <code>rounded_arith_std</code> and
|
||||
<code>rounded_arith_opp</code> expect the operators + - * / and the
|
||||
function <code>std::sqrt</code> to respect the current rounding mode.</p>
|
||||
|
||||
<p>The class <code>rounded_arith_exact</code> requires
|
||||
<code>std::floor</code> and <code>std::ceil</code> to be defined since it
|
||||
can not rely on <code>to_int</code>.</p>
|
||||
|
||||
<h3>Rounding control</h3>
|
||||
|
||||
<p>The functions defined by each of the previous classes did not need any
|
||||
explanation. For example, the behavior of <code>add_down</code> is to
|
||||
compute the sum of two numbers rounded downward. For
|
||||
<code>rounding_control</code>, the situation is a bit more complex.</p>
|
||||
|
||||
<p>The basic function is <code>force_rounding</code> which returns its
|
||||
argument correctly rounded accordingly to the current rounding mode if it
|
||||
was not already the case. This function is necessary to handle delayed
|
||||
rounding. Indeed, depending on the way the computations are done, the
|
||||
intermediate results may be internally stored in a more precise format and
|
||||
it can lead to a wrong rounding. So the function enforces the rounding.
|
||||
<a href="#extreg">Here</a> is an example of what happens when the rounding
|
||||
is not enforced.</p>
|
||||
|
||||
<p>The function <code>get_rounding_mode</code> returns the current rounding
|
||||
mode, <code>set_rounding_mode</code> sets the rounding mode back to a
|
||||
previous value returned by <code>get_rounding_mode</code>.
|
||||
<code>downward</code>, <code>upward</code> and <code>to_nearest</code> sets
|
||||
the rounding mode in one of the three directions. This rounding mode should
|
||||
be global to all the functions that use the type <code>T</code>. For
|
||||
example, after a call to <code>downward</code>,
|
||||
<code>force_rounding(x+y)</code> is expected to return the sum rounded
|
||||
toward -∞.</p>
|
||||
|
||||
<p>The function <code>to_int</code> computes the nearest integer
|
||||
accordingly to the current rounding mode.</p>
|
||||
|
||||
<p>The non-specialized version of <code>rounding_control</code> does not do
|
||||
anything. The functions for the rounding mode are empty, and
|
||||
<code>to_int</code> and <code>force_rounding</code> are identity functions.
|
||||
The <code>pi_</code> constant functions return suitable integers (for
|
||||
example, <code>pi_up</code> returns <code>T(4)</code>).</p>
|
||||
|
||||
<p>The class template <code>rounding_control</code> is specialized for
|
||||
<code>float</code>, <code>double</code> and <code>long double</code> in
|
||||
order to best use the floating point unit of the computer.</p>
|
||||
|
||||
<h2>Template class <tt>rounded_math</tt></h2>
|
||||
|
||||
<p>The default policy (aka <code>rounded_math<T></code>) is simply
|
||||
defined as:</p>
|
||||
<pre>
|
||||
template <class T> struct rounded_math<T> : save_state_nothing<rounded_arith_exact<T> > {};
|
||||
</pre>
|
||||
|
||||
<p>and the specializations for <code>float</code>, <code>double</code> and
|
||||
<code>long double</code> use <code>rounded_arith_opp</code>, as in:</p>
|
||||
<pre>
|
||||
template <> struct rounded_math<float> : save_state<rounded_arith_opp<float> > {};
|
||||
template <> struct rounded_math<double> : save_state<rounded_arith_opp<double> > {};
|
||||
template <> struct rounded_math<long double> : save_state<rounded_arith_opp<long double> > {};
|
||||
</pre>
|
||||
|
||||
<h2 id="perf">Performance Issues</h2>
|
||||
|
||||
<p>This paragraph deals mostly with the performance of the library with
|
||||
intervals using the floating-point unit (FPU) of the computer. Let's
|
||||
consider the sum of [<i>a</i>,<i>b</i>] and [<i>c</i>,<i>d</i>] as an
|
||||
example. The result is [<code>down</code>(<i>a</i>+<i>c</i>),
|
||||
<code>up</code>(<i>b</i>+<i>d</i>)], where <code>down</code> and
|
||||
<code>up</code> indicate the rounding mode needed.</p>
|
||||
|
||||
<h3>Rounding Mode Switch</h3>
|
||||
|
||||
<p>If the FPU is able to use a different rounding mode for each operation,
|
||||
there is no problem. For example, it's the case for the Alpha processor:
|
||||
each floating-point instruction can specify a different rounding mode.
|
||||
However, the IEEE-754 Standard does not require such a behavior. So most of
|
||||
the FPUs only provide some instructions to set the rounding mode for all
|
||||
subsequent operations. And generally, these instructions need to flush the
|
||||
pipeline of the FPU.</p>
|
||||
|
||||
<p>In this situation, the time needed to sum [<i>a</i>,<i>b</i>] and
|
||||
[<i>c</i>,<i>d</i>] is far worse than the time needed to calculate
|
||||
<i>a</i>+<i>b</i> and <i>c</i>+<i>d</i> since the two additions cannot be
|
||||
parallelized. Consequently, the objective is to diminish the number of
|
||||
rounding mode switches.</p>
|
||||
|
||||
<p>If this library is not used to provide exact computations, but only for
|
||||
pair arithmetic, the solution is quite simple: do not use rounding. In that
|
||||
case, doing the sum [<i>a</i>,<i>b</i>] and [<i>c</i>,<i>d</i>] will be as
|
||||
fast as computing <i>a</i>+<i>b</i> and <i>c</i>+<i>d</i>. Everything is
|
||||
perfect.</p>
|
||||
|
||||
<p>However, if exact computations are required, such a solution is totally
|
||||
unthinkable. So, are we penniless? No, there is still a trick available.
|
||||
Indeed, down(<i>a</i>+<i>c</i>) = -up(-<i>a</i>-<i>c</i>) if the unary
|
||||
minus is an exact operation. It is now possible to calculate the whole sum
|
||||
with the same rounding mode. Generally, the cost of the mode switching is
|
||||
worse than the cost of the sign changes.</p>
|
||||
|
||||
<h4>Speeding up consecutive operations</h4>
|
||||
|
||||
<p>The interval addition is not the only operation; most of the interval
|
||||
operations can be computed by setting the rounding direction of the FPU
|
||||
only once. So the operations of the floating point rounding policy assume
|
||||
that the direction is correctly set. This assumption is usually not true in
|
||||
a program (the user and the standard library expect the rounding direction
|
||||
to be to nearest), so these operations have to be enclosed in a shell that
|
||||
sets the floating point environment. This protection is done by the
|
||||
constructor and destructor of the rounding policy.</p>
|
||||
|
||||
<p>Les us now consider the case of two consecutive interval additions:
|
||||
[<i>a</i>,<i>b</i>] + [<i>c</i>,<i>d</i>] + [<i>e</i>,<i>f</i>]. The
|
||||
generated code should look like:</p>
|
||||
<pre>
|
||||
init_rounding_mode(); // rounding object construction during the first addition
|
||||
t1 = -(-a - c);
|
||||
t2 = b + d;
|
||||
restore_rounding_mode(); // rounding object destruction
|
||||
init_rounding_mode(); // rounding object construction during the second addition
|
||||
x = -(-t1 - e);
|
||||
y = t2 + f;
|
||||
restore_rounding_mode(); // rounding object destruction
|
||||
// the result is the interval [x,y]
|
||||
</pre>
|
||||
|
||||
<p>Between the two operations, the rounding direction is restored, and then
|
||||
initialized again. Ideally, compilers should be able to optimize this
|
||||
useless code away. But unfortunately they are not, and this slows the code
|
||||
down by an order of magnitude. In order to avoid this bottleneck, the user
|
||||
can tell to the interval operations that they do not need to be protected
|
||||
anymore. It will then be up to the user to protect the interval
|
||||
computations. The compiler will then be able to generate such a code:</p>
|
||||
<pre>
|
||||
init_rounding_mode(); // done by the user
|
||||
x = -(-a - c - e);
|
||||
y = b + d + f;
|
||||
restore_rounding_mode(); // done by the user
|
||||
</pre>
|
||||
|
||||
<p>The user will have to create a rounding object. And as long as this
|
||||
object is alive, unprotected versions of the interval operations can be
|
||||
used. They are selected by using an interval type with a specific rounding
|
||||
policy. If the initial interval type is <code>I</code>, then
|
||||
<code>I::traits_type::rounding</code> is the type of the rounding object,
|
||||
and <code>interval_lib::unprotect<I>::type</code> is the type of the
|
||||
unprotected interval type.</p>
|
||||
|
||||
<p>Because the rounding mode of the FPU is changed during the life of the
|
||||
rounding object, any arithmetic floating point operation that does not
|
||||
involve the interval library can lead to unexpected results. And
|
||||
reciprocally, using unprotected interval operation when no rounding object
|
||||
is alive will produce intervals that are not guaranteed anymore to contain
|
||||
the real result.</p>
|
||||
|
||||
<h4 id="perfexp">Example</h4>
|
||||
|
||||
<p>Here is an example of Horner's scheme to compute the value of a polynom.
|
||||
The rounding mode switches are disabled for the whole computation.</p>
|
||||
<pre>
|
||||
// I is an interval class, the polynom is a simple array
|
||||
template<class I>
|
||||
I horner(const I& x, const I p[], int n) {
|
||||
|
||||
// save and initialize the rounding mode
|
||||
typename I::traits_type::rounding rnd;
|
||||
|
||||
// define the unprotected version of the interval type
|
||||
typedef typename boost::numeric::interval_lib::unprotect<I>::type R;
|
||||
|
||||
const R& a = x;
|
||||
R y = p[n - 1];
|
||||
for(int i = n - 2; i >= 0; i--) {
|
||||
y = y * a + (const R&)(p[i]);
|
||||
}
|
||||
return y;
|
||||
|
||||
// restore the rounding mode with the destruction of rnd
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Please note that a rounding object is specially created in order to
|
||||
protect all the interval computations. Each interval of type I is converted
|
||||
in an interval of type R before any operations. If this conversion is not
|
||||
done, the result is still correct, but the interest of this whole
|
||||
optimization has disappeared. Whenever possible, it is good to convert to
|
||||
<code>const R&</code> instead of <code>R</code>: indeed, the function
|
||||
could already be called inside an unprotection block so the types
|
||||
<code>R</code> and <code>I</code> would be the same interval, no need for a
|
||||
conversion.</p>
|
||||
|
||||
<h4>Uninteresting remark</h4>
|
||||
|
||||
<p>It was said at the beginning that the Alpha processors can use a
|
||||
specific rounding mode for each operation. However, due to the instruction
|
||||
format, the rounding toward plus infinity is not available. Only the
|
||||
rounding toward minus infinity can be used. So the trick using the change
|
||||
of sign becomes essential, but there is no need to save and restore the
|
||||
rounding mode on both sides of an operation.</p>
|
||||
|
||||
<h3 id="extreg">Extended Registers</h3>
|
||||
|
||||
<p>There is another problem besides the cost of the rounding mode switch.
|
||||
Some FPUs use extended registers (for example, float computations will be
|
||||
done with double registers, or double computations with long double
|
||||
registers). Consequently, many problems can arise.</p>
|
||||
|
||||
<p>The first one is due to to the extended precision of the mantissa. The
|
||||
rounding is also done on this extended precision. And consequently, we
|
||||
still have down(<i>a</i>+<i>b</i>) = -up(-<i>a</i>-<i>b</i>) in the
|
||||
extended registers. But back to the standard precision, we now have
|
||||
down(<i>a</i>+<i>b</i>) < -up(-<i>a</i>-<i>b</i>) instead of an
|
||||
equality. A solution could be not to use this method. But there still are
|
||||
other problems, with the comparisons between numbers for example.</p>
|
||||
|
||||
<p>Naturally, there is also a problem with the extended precision of the
|
||||
exponent. To illustrate this problem, let <i>m</i> be the biggest number
|
||||
before +<i>inf</i>. If we calculate 2*[<i>m</i>,<i>m</i>], the answer
|
||||
should be [<i>m</i>,<i>inf</i>]. But due to the extended registers, the FPU
|
||||
will first store [<i>2m</i>,<i>2m</i>] and then convert it to
|
||||
[<i>inf</i>,<i>inf</i>] at the end of the calculus (when the rounding mode
|
||||
is toward +<i>inf</i>). So the answer is no more accurate.</p>
|
||||
|
||||
<p>There is only one solution: to force the FPU to convert the extended
|
||||
values back to standard precision after each operation. Some FPUs provide
|
||||
an instruction able to do this conversion (for example the PowerPC
|
||||
processors). But for the FPUs that do not provide it (the x86 processors),
|
||||
the only solution is to write the values to memory and read them back. Such
|
||||
an operation is obviously very expensive.</p>
|
||||
|
||||
<h2>Some Examples</h2>
|
||||
|
||||
<p>Here come several cases:</p>
|
||||
|
||||
<ul>
|
||||
<li>if you need precise computations with the <code>float</code> or
|
||||
<code>double</code> types, use the default
|
||||
<code>rounded_math<T></code>;</li>
|
||||
|
||||
<li>for fast wide intervals without any rounding nor precision, use
|
||||
<code>save_state_nothing<rounded_transc_exact<T>
|
||||
></code>;</li>
|
||||
|
||||
<li>for an exact type (like int or rational with a little help for
|
||||
infinite and NaN values) without support for transcendental functions,
|
||||
the solution could be
|
||||
<code>save_state_nothing<rounded_transc_dummy<T,
|
||||
rounded_arith_exact<T> > ></code> or directly
|
||||
<code>save_state_nothing<rounded_arith_exact<T>
|
||||
></code>;</li>
|
||||
|
||||
<li>if it is a more complex case than the previous ones, the best thing
|
||||
is probably to directly define your own policy.</li>
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University<br>
|
||||
Copyright © 2004-2005 Guillaume Melquiond, ENS Lyon</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Interval-TODO.htm</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1>TODO list for the Interval Arithmetic library</h1>
|
||||
|
||||
<h2>Comments from the review process</h2>
|
||||
|
||||
<ul>
|
||||
<li>It would be nice to have a 100% portable Rounding policy class based
|
||||
on LIA-1 only, with no additional requirement such as IEEE 754 or even
|
||||
more.</li>
|
||||
|
||||
<li>For pi and other constants, we should fetch them from the Math
|
||||
constants library when it is ready.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Various items</h2>
|
||||
|
||||
<ul>
|
||||
<li>Support the <code>-mfpmath=sse</code> option of g++ for Pentium IV
|
||||
optimized code. This requires a different rounding policy class.</li>
|
||||
|
||||
<li>Have an optimized specialization of
|
||||
<code>interval<double></code> using SSE2 instructions? Tricky.</li>
|
||||
|
||||
<li>Write a traits specialization for <code>interval<MPFR></code>,
|
||||
and other non-built-in number types.</li>
|
||||
|
||||
<li>Have a robust implementation of transcendental functions over the
|
||||
built-in floating point types (e.g. using MPFR)?</li>
|
||||
|
||||
<li>Safe conversions from <code>interval<double></code> to
|
||||
<code>interval<float></code>? Requires partial specialization.</li>
|
||||
|
||||
<li>It would be nice to use the expression template mechanism to
|
||||
automatically use the more efficient unprotected rounding mode version
|
||||
for small subexpressions (although you can do bigger expressions by
|
||||
hand).</li>
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
||||
"../../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
||||
height="31" width="88"></a></p>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-12-24<!--webbot bot="Timestamp" endspan i-checksum="12172" --></p>
|
||||
|
||||
<p><i>Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé
|
||||
Brönnimann, Polytechnic University</i></p>
|
||||
|
||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href=
|
||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,208 @@
|
||||
/* Boost example/filter.cpp
|
||||
* two examples of filters for computing the sign of a determinant
|
||||
* the second filter is based on an idea presented in
|
||||
* "Interval arithmetic yields efficient dynamic filters for computational
|
||||
* geometry" by Brönnimann, Burnikel and Pion, 2001
|
||||
*
|
||||
* Copyright 2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace dummy {
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
using namespace interval_lib;
|
||||
typedef save_state<rounded_arith_opp<double> > R;
|
||||
typedef checking_no_nan<double, checking_no_empty<double> > P;
|
||||
typedef interval<double, policies<R, P> > I;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
class vector {
|
||||
T* ptr;
|
||||
public:
|
||||
vector(int d) { ptr = (T*)malloc(sizeof(T) * d); }
|
||||
~vector() { free(ptr); }
|
||||
const T& operator[](int i) const { return ptr[i]; }
|
||||
T& operator[](int i) { return ptr[i]; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class matrix {
|
||||
int dim;
|
||||
T* ptr;
|
||||
public:
|
||||
matrix(int d): dim(d) { ptr = (T*)malloc(sizeof(T) * dim * dim); }
|
||||
~matrix() { free(ptr); }
|
||||
int get_dim() const { return dim; }
|
||||
void assign(const matrix<T> &a) { memcpy(ptr, a.ptr, sizeof(T) * dim * dim); }
|
||||
const T* operator[](int i) const { return &(ptr[i * dim]); }
|
||||
T* operator[](int i) { return &(ptr[i * dim]); }
|
||||
};
|
||||
|
||||
typedef dummy::I I_dbl;
|
||||
|
||||
/* compute the sign of a determinant using an interval LU-decomposition; the
|
||||
function answers 1 or -1 if the determinant is positive or negative (and
|
||||
more importantly, the result must be provable), or 0 if the algorithm was
|
||||
unable to get a correct sign */
|
||||
int det_sign_algo1(const matrix<double> &a) {
|
||||
int dim = a.get_dim();
|
||||
vector<int> p(dim);
|
||||
for(int i = 0; i < dim; i++) p[i] = i;
|
||||
int sig = 1;
|
||||
I_dbl::traits_type::rounding rnd;
|
||||
typedef boost::numeric::interval_lib::unprotect<I_dbl>::type I;
|
||||
matrix<I> u(dim);
|
||||
for(int i = 0; i < dim; i++) {
|
||||
const double* line1 = a[i];
|
||||
I* line2 = u[i];
|
||||
for(int j = 0; j < dim; j++)
|
||||
line2[j] = line1[j];
|
||||
}
|
||||
// computation of L and U
|
||||
for(int i = 0; i < dim; i++) {
|
||||
// partial pivoting
|
||||
{
|
||||
int pivot = i;
|
||||
double max = 0;
|
||||
for(int j = i; j < dim; j++) {
|
||||
const I &v = u[p[j]][i];
|
||||
if (zero_in(v)) continue;
|
||||
double m = norm(v);
|
||||
if (m > max) { max = m; pivot = j; }
|
||||
}
|
||||
if (max == 0) return 0;
|
||||
if (pivot != i) {
|
||||
sig = -sig;
|
||||
int tmp = p[i];
|
||||
p[i] = p[pivot];
|
||||
p[pivot] = tmp;
|
||||
}
|
||||
}
|
||||
// U[i,?]
|
||||
{
|
||||
I *line1 = u[p[i]];
|
||||
const I &pivot = line1[i];
|
||||
if (boost::numeric::interval_lib::cerlt(pivot, 0.)) sig = -sig;
|
||||
for(int k = i + 1; k < dim; k++) {
|
||||
I *line2 = u[p[k]];
|
||||
I fact = line2[i] / pivot;
|
||||
for(int j = i + 1; j < dim; j++) line2[j] -= fact * line1[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* compute the sign of a determinant using a floating-point LU-decomposition
|
||||
and an a posteriori interval validation; the meaning of the answer is the
|
||||
same as previously */
|
||||
int det_sign_algo2(const matrix<double> &a) {
|
||||
int dim = a.get_dim();
|
||||
vector<int> p(dim);
|
||||
for(int i = 0; i < dim; i++) p[i] = i;
|
||||
int sig = 1;
|
||||
matrix<double> lui(dim);
|
||||
{
|
||||
// computation of L and U
|
||||
matrix<double> lu(dim);
|
||||
lu.assign(a);
|
||||
for(int i = 0; i < dim; i++) {
|
||||
// partial pivoting
|
||||
{
|
||||
int pivot = i;
|
||||
double max = std::abs(lu[p[i]][i]);
|
||||
for(int j = i + 1; j < dim; j++) {
|
||||
double m = std::abs(lu[p[j]][i]);
|
||||
if (m > max) { max = m; pivot = j; }
|
||||
}
|
||||
if (max == 0) return 0;
|
||||
if (pivot != i) {
|
||||
sig = -sig;
|
||||
int tmp = p[i];
|
||||
p[i] = p[pivot];
|
||||
p[pivot] = tmp;
|
||||
}
|
||||
}
|
||||
// L[?,i] and U[i,?]
|
||||
{
|
||||
double *line1 = lu[p[i]];
|
||||
double pivot = line1[i];
|
||||
if (pivot < 0) sig = -sig;
|
||||
for(int k = i + 1; k < dim; k++) {
|
||||
double *line2 = lu[p[k]];
|
||||
double fact = line2[i] / pivot;
|
||||
line2[i] = fact;
|
||||
for(int j = i + 1; j < dim; j++) line2[j] -= line1[j] * fact;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// computation of approximate inverses: Li and Ui
|
||||
for(int j = 0; j < dim; j++) {
|
||||
for(int i = j + 1; i < dim; i++) {
|
||||
double *line = lu[p[i]];
|
||||
double s = - line[j];
|
||||
for(int k = j + 1; k < i; k++) s -= line[k] * lui[k][j];
|
||||
lui[i][j] = s;
|
||||
}
|
||||
lui[j][j] = 1 / lu[p[j]][j];
|
||||
for(int i = j - 1; i >= 0; i--) {
|
||||
double *line = lu[p[i]];
|
||||
double s = 0;
|
||||
for(int k = i + 1; k <= j; k++) s -= line[k] * lui[k][j];
|
||||
lui[i][j] = s / line[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// norm of PAUiLi-I computed with intervals
|
||||
{
|
||||
I_dbl::traits_type::rounding rnd;
|
||||
typedef boost::numeric::interval_lib::unprotect<I_dbl>::type I;
|
||||
vector<I> m1(dim);
|
||||
vector<I> m2(dim);
|
||||
for(int i = 0; i < dim; i++) {
|
||||
for(int j = 0; j < dim; j++) m1[j] = 0;
|
||||
const double *l1 = a[p[i]];
|
||||
for(int j = 0; j < dim; j++) {
|
||||
double v = l1[j]; // PA[i,j]
|
||||
double *l2 = lui[j]; // Ui[j,?]
|
||||
for(int k = j; k < dim; k++) {
|
||||
using boost::numeric::interval_lib::mul;
|
||||
m1[k] += mul<I>(v, l2[k]); // PAUi[i,k]
|
||||
}
|
||||
}
|
||||
for(int j = 0; j < dim; j++) m2[j] = m1[j]; // PAUi[i,j] * Li[j,j]
|
||||
for(int j = 1; j < dim; j++) {
|
||||
const I &v = m1[j]; // PAUi[i,j]
|
||||
double *l2 = lui[j]; // Li[j,?]
|
||||
for(int k = 0; k < j; k++)
|
||||
m2[k] += v * l2[k]; // PAUiLi[i,k]
|
||||
}
|
||||
m2[i] -= 1; // PAUiLi-I
|
||||
double ss = 0;
|
||||
for(int i = 0; i < dim; i++) ss = rnd.add_up(ss, norm(m2[i]));
|
||||
if (ss >= 1) return 0;
|
||||
}
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int dim = 20;
|
||||
matrix<double> m(dim);
|
||||
for(int i = 0; i < dim; i++) for(int j = 0; j < dim; j++)
|
||||
m[i][j] = /*1 / (i-j-0.001)*/ cos(1+i*sin(1 + j)) /*1./(1+i+j)*/;
|
||||
|
||||
// compute the sign of the determinant of a "strange" matrix with the two
|
||||
// algorithms, the first should fail and the second succeed
|
||||
std::cout << det_sign_algo1(m) << " " << det_sign_algo2(m) << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/* Boost example/findroot_demo.cpp
|
||||
* find zero points of some function by dichotomy
|
||||
*
|
||||
* Copyright 2000 Jens Maurer
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* The idea and the 2D function are based on RVInterval,
|
||||
* which contains the following copyright notice:
|
||||
|
||||
This file is copyrighted 1996 by Ronald Van Iwaarden.
|
||||
|
||||
Permission is hereby granted, without written agreement and
|
||||
without license or royalty fees, to use, copy, modify, and
|
||||
distribute this software and its documentation for any
|
||||
purpose, subject to the following conditions:
|
||||
|
||||
The above license notice and this permission notice shall
|
||||
appear in all copies or substantial portions of this software.
|
||||
|
||||
The name "RVInterval" cannot be used for any modified form of
|
||||
this software that does not originate from the authors.
|
||||
Nevertheless, the name "RVInterval" may and should be used to
|
||||
designate the optimization software implemented and described
|
||||
in this package, even if embedded in any other system, as long
|
||||
as any portion of this code remains.
|
||||
|
||||
The authors specifically disclaim any warranties, including,
|
||||
but not limited to, the implied warranties of merchantability
|
||||
and fitness for a particular purpose. The software provided
|
||||
hereunder is on an "as is" basis, and the authors have no
|
||||
obligation to provide maintenance, support, updates,
|
||||
enhancements, or modifications. In no event shall the authors
|
||||
be liable to any party for direct, indirect, special,
|
||||
incidental, or consequential damages arising out of the use of
|
||||
this software and its documentation.
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp> // must be first for <limits> workaround
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
template<class T>
|
||||
struct test_func2d
|
||||
{
|
||||
T operator()(T x, T y) const
|
||||
{
|
||||
return sin(x)*cos(y) - exp(x*y)/45.0 * (pow(x+y, 2)+100.0) -
|
||||
cos(sin(y))*y/4.0;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct test_func1d
|
||||
{
|
||||
T operator()(T x) const
|
||||
{
|
||||
return sin(x)/(x*x+1.0);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct test_func1d_2
|
||||
{
|
||||
T operator()(T x) const
|
||||
{
|
||||
using std::sqrt;
|
||||
return sqrt(x*x-1.0);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Function, class I>
|
||||
void find_zeros(std::ostream & os, Function f, I searchrange)
|
||||
{
|
||||
std::list<I> l, done;
|
||||
l.push_back(searchrange);
|
||||
while(!l.empty()) {
|
||||
I range = l.front();
|
||||
l.pop_front();
|
||||
I val = f(range);
|
||||
if (zero_in(val)) {
|
||||
if(width(range) < 1e-6) {
|
||||
os << range << '\n';
|
||||
continue;
|
||||
}
|
||||
// there's still a solution hidden somewhere
|
||||
std::pair<I,I> p = bisect(range);
|
||||
l.push_back(p.first);
|
||||
l.push_back(p.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::ostream &operator<<(std::ostream &os, const std::pair<T, T> &x) {
|
||||
os << "(" << x.first << ", " << x.second << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template<class T, class Policies>
|
||||
std::ostream &operator<<(std::ostream &os,
|
||||
const boost::numeric::interval<T, Policies> &x) {
|
||||
os << "[" << x.lower() << ", " << x.upper() << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
static const double epsilon = 5e-3;
|
||||
|
||||
template<class Function, class I>
|
||||
void find_zeros(std::ostream & os, Function f, I rx, I ry)
|
||||
{
|
||||
typedef std::pair<I, I> rectangle;
|
||||
typedef std::deque<rectangle> container;
|
||||
container l, done;
|
||||
// l.reserve(50);
|
||||
l.push_back(std::make_pair(rx, ry));
|
||||
for(int i = 1; !l.empty(); ++i) {
|
||||
rectangle rect = l.front();
|
||||
l.pop_front();
|
||||
I val = f(rect.first, rect.second);
|
||||
if (zero_in(val)) {
|
||||
if(width(rect.first) < epsilon && width(rect.second) < epsilon) {
|
||||
os << median(rect.first) << " " << median(rect.second) << " "
|
||||
<< lower(rect.first) << " " << upper(rect.first) << " "
|
||||
<< lower(rect.second) << " " << upper(rect.second)
|
||||
<< '\n';
|
||||
} else {
|
||||
if(width(rect.first) > width(rect.second)) {
|
||||
std::pair<I,I> p = bisect(rect.first);
|
||||
l.push_back(std::make_pair(p.first, rect.second));
|
||||
l.push_back(std::make_pair(p.second, rect.second));
|
||||
} else {
|
||||
std::pair<I,I> p = bisect(rect.second);
|
||||
l.push_back(std::make_pair(rect.first, p.first));
|
||||
l.push_back(std::make_pair(rect.first, p.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(i % 10000 == 0)
|
||||
std::cerr << "\rIteration " << i << ", l.size() = " << l.size();
|
||||
}
|
||||
std::cerr << '\n';
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
using namespace interval_lib;
|
||||
|
||||
typedef interval<double,
|
||||
policies<save_state<rounded_transc_opp<double> >,
|
||||
checking_base<double> > > I;
|
||||
|
||||
std::cout << "Zero points of sin(x)/(x*x+1)\n";
|
||||
find_zeros(std::cout, test_func1d<I>(), I(-11, 10));
|
||||
std::cout << "Zero points of sqrt(x*x-1)\n";
|
||||
find_zeros(std::cout, test_func1d_2<I>(), I(-5, 6));
|
||||
std::cout << "Zero points of Van Iwaarden's 2D function\n";
|
||||
std::ofstream f("func2d.data");
|
||||
find_zeros(f, test_func2d<I>(), I(-20, 20), I(-20, 20));
|
||||
std::cout << "Use gnuplot, command 'plot \"func2d.data\" with dots' to plot\n";
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/* Boost example/horner.cpp
|
||||
* example of unprotecting rounding for a whole function computation
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <iostream>
|
||||
|
||||
// I is an interval class, the polynom is a simple array
|
||||
template<class I>
|
||||
I horner(const I& x, const I p[], int n) {
|
||||
|
||||
// initialize and restore the rounding mode
|
||||
typename I::traits_type::rounding rnd;
|
||||
|
||||
// define the unprotected version of the interval type
|
||||
typedef typename boost::numeric::interval_lib::unprotect<I>::type R;
|
||||
|
||||
const R& a = x;
|
||||
R y = p[n - 1];
|
||||
for(int i = n - 2; i >= 0; i--) {
|
||||
y = y * a + (const R&)(p[i]);
|
||||
}
|
||||
return y;
|
||||
|
||||
// restore the rounding mode with the destruction of rnd
|
||||
}
|
||||
|
||||
template<class T, class Policies>
|
||||
std::ostream &operator<<(std::ostream &os,
|
||||
const boost::numeric::interval<T, Policies> &x) {
|
||||
os << "[" << x.lower() << ", " << x.upper() << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
typedef boost::numeric::interval<double> I;
|
||||
I p[3] = { -1.0, 0, 1.0 };
|
||||
I x = 1.0;
|
||||
std::cout << horner(x, p, 3) << std::endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/* Boost examples/io.cpp
|
||||
* show some exampleso of i/o operators
|
||||
* thanks to all the people who commented on this point, particularly on
|
||||
* the Boost mailing-list
|
||||
*
|
||||
* Copyright 2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <boost/io/ios_state.hpp>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
namespace io_std {
|
||||
|
||||
template<class T, class Policies, class CharType, class CharTraits>
|
||||
std::basic_ostream<CharType, CharTraits> &operator<<
|
||||
(std::basic_ostream<CharType, CharTraits> &stream,
|
||||
const boost::numeric::interval<T, Policies> &value)
|
||||
{
|
||||
if (empty(value)) {
|
||||
return stream << "[]";
|
||||
} else {
|
||||
return stream << '[' << lower(value) << ',' << upper(value) << ']';
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace io_std
|
||||
|
||||
namespace io_sngl {
|
||||
|
||||
template<class T, class Policies, class CharType, class CharTraits>
|
||||
std::basic_ostream<CharType, CharTraits> &operator<<
|
||||
(std::basic_ostream<CharType, CharTraits> &stream,
|
||||
const boost::numeric::interval<T, Policies> &value)
|
||||
{
|
||||
if (empty(value)) {
|
||||
return stream << "[]";
|
||||
} else if (singleton(value)) {
|
||||
return stream << '[' << lower(value) << ']';
|
||||
} else {
|
||||
return stream << '[' << lower(value) << ',' << upper(value) << ']';
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace io_sngl
|
||||
|
||||
namespace io_wdth {
|
||||
|
||||
template<class T, class Policies, class CharType, class CharTraits>
|
||||
std::basic_ostream<CharType, CharTraits> &operator<<
|
||||
(std::basic_ostream<CharType, CharTraits> &stream,
|
||||
const boost::numeric::interval<T, Policies> &value)
|
||||
{
|
||||
if (empty(value)) {
|
||||
return stream << "nothing";
|
||||
} else {
|
||||
return stream << median(value) << " ± " << width(value) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace io_wdth
|
||||
|
||||
namespace io_prec {
|
||||
|
||||
template<class T, class Policies, class CharType, class CharTraits>
|
||||
std::basic_ostream<CharType, CharTraits> &operator<<
|
||||
(std::basic_ostream<CharType, CharTraits> &stream,
|
||||
const boost::numeric::interval<T, Policies> &value)
|
||||
{
|
||||
if (empty(value)) {
|
||||
return stream << "nothing";
|
||||
} else if (singleton(value)) {
|
||||
boost::io::ios_precision_saver state(stream, std::numeric_limits<T>::digits10);
|
||||
return stream << lower(value);
|
||||
} else if (zero_in(value)) {
|
||||
return stream << "0~";
|
||||
} else {
|
||||
const T rel = width(value) / norm(value);
|
||||
int range = - (int)std::log10(rel);
|
||||
boost::io::ios_precision_saver state(stream, range);
|
||||
return stream << median(value);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace io_prec
|
||||
|
||||
namespace io_wide {
|
||||
|
||||
template<class T, class Policies, class CharType, class CharTraits>
|
||||
std::basic_ostream<CharType, CharTraits> &operator<<
|
||||
(std::basic_ostream<CharType, CharTraits> &stream,
|
||||
const boost::numeric::interval<T, Policies> &value)
|
||||
{
|
||||
if (empty(value)) {
|
||||
return stream << "nothing";
|
||||
} else if (singleton(value)) {
|
||||
boost::io::ios_precision_saver state(stream, std::numeric_limits<T>::digits10);
|
||||
return stream << lower(value);
|
||||
} else if (zero_in(value)) {
|
||||
return stream << "0~";
|
||||
} else {
|
||||
std::streamsize p = stream.precision();
|
||||
// FIXME poor man's power of 10, only up to 1E-15
|
||||
p = (p > 15) ? 15 : p - 1;
|
||||
double eps = 1.0; for(; p > 0; --p) { eps /= 10; }
|
||||
T eps2 = static_cast<T>(eps / 2) * norm(value);
|
||||
boost::numeric::interval<T, Policies> r = widen(value, eps2);
|
||||
return stream << '[' << lower(r) << ',' << upper(r) << ']';
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace io_wide
|
||||
|
||||
template<class T, class Policies, class CharType, class CharTraits> inline
|
||||
std::basic_istream<CharType, CharTraits> &operator>>
|
||||
(std::basic_istream<CharType, CharTraits> &stream,
|
||||
boost::numeric::interval<T, Policies> &value)
|
||||
{
|
||||
T l, u;
|
||||
char c = 0;
|
||||
stream >> c;
|
||||
if (c == '[') {
|
||||
stream >> l >> c;
|
||||
if (c == ',') stream >> u >> c; else u = l;
|
||||
if (c != ']') stream.setstate(stream.failbit);
|
||||
} else {
|
||||
stream.putback(c);
|
||||
stream >> l;
|
||||
u = l;
|
||||
}
|
||||
if (stream)
|
||||
value.assign(l, u);
|
||||
else
|
||||
value = boost::numeric::interval<T, Policies>::empty();
|
||||
return stream;
|
||||
}
|
||||
|
||||
// Test program
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
using namespace interval_lib;
|
||||
|
||||
typedef interval<double,
|
||||
policies<rounded_math<double>,
|
||||
checking_base<double> > > I;
|
||||
|
||||
I tab[] = { I::empty(), I(1,1), I(1,2), I(-1,1), I(12.34,12.35),
|
||||
I(1234.56,1234.57), I(123456.78, 123456.79), I::empty() };
|
||||
unsigned int len = sizeof(tab) / sizeof(I);
|
||||
std::cout << "Enter an interval: (it will be the last shown)\n";
|
||||
std::cin >> tab[len - 1];
|
||||
|
||||
for(unsigned int i = 0; i < len; ++i) {
|
||||
{ using namespace io_std; std::cout << tab[i] << '\n'; }
|
||||
{ using namespace io_sngl; std::cout << tab[i] << '\n'; }
|
||||
{ using namespace io_wdth; std::cout << tab[i] << '\n'; }
|
||||
{ using namespace io_prec; std::cout << tab[i] << '\n'; }
|
||||
{ using namespace io_wide; std::cout << tab[i] << '\n'; }
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/* Boost example/newton-raphson.cpp
|
||||
* Newton iteration for intervals
|
||||
*
|
||||
* Copyright 2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
template <class I> I f(const I& x)
|
||||
{ return x * (x - 1.) * (x - 2.) * (x - 3.) * (x - 4.); }
|
||||
template <class I> I f_diff(const I& x)
|
||||
{ return (((5. * x - 40.) * x + 105.) * x - 100.) * x + 24.; }
|
||||
|
||||
static const double max_width = 1e-10;
|
||||
static const double alpha = 0.75;
|
||||
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
using namespace interval_lib;
|
||||
|
||||
// First method: no empty intervals
|
||||
|
||||
typedef interval<double> I1_aux;
|
||||
typedef unprotect<I1_aux>::type I1;
|
||||
|
||||
std::vector<I1> newton_raphson(const I1& xs) {
|
||||
std::vector<I1> l, res;
|
||||
I1 vf, vd, x, x1, x2;
|
||||
l.push_back(xs);
|
||||
while (!l.empty()) {
|
||||
x = l.back();
|
||||
l.pop_back();
|
||||
bool x2_used;
|
||||
double xx = median(x);
|
||||
vf = f<I1>(xx);
|
||||
vd = f_diff<I1>(x);
|
||||
if (zero_in(vf) && zero_in(vd)) {
|
||||
x1 = I1::whole();
|
||||
x2_used = false;
|
||||
} else {
|
||||
x1 = xx - division_part1(vf, vd, x2_used);
|
||||
if (x2_used) x2 = xx - division_part2(vf, vd);
|
||||
}
|
||||
if (overlap(x1, x)) x1 = intersect(x, x1);
|
||||
else if (x2_used) { x1 = x2; x2_used = false; }
|
||||
else continue;
|
||||
if (x2_used) {
|
||||
if (overlap(x2, x)) x2 = intersect(x, x2);
|
||||
else x2_used = false;
|
||||
}
|
||||
if (x2_used && width(x2) > width(x1)) std::swap(x1, x2);
|
||||
if (!zero_in(f(x1))) {
|
||||
if (x2_used) { x1 = x2; x2_used = false; }
|
||||
else continue;
|
||||
}
|
||||
if (width(x1) < max_width) res.push_back(x1);
|
||||
else if (width(x1) > alpha * width(x)) {
|
||||
std::pair<I1, I1> p = bisect(x);
|
||||
if (zero_in(f(p.first))) l.push_back(p.first);
|
||||
x2 = p.second;
|
||||
x2_used = true;
|
||||
} else l.push_back(x1);
|
||||
if (x2_used && zero_in(f(x2))) {
|
||||
if (width(x2) < max_width) res.push_back(x2);
|
||||
else l.push_back(x2);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Second method: with empty intervals
|
||||
|
||||
typedef change_checking<I1_aux, checking_no_nan<double> >::type I2_aux;
|
||||
typedef unprotect<I2_aux>::type I2;
|
||||
|
||||
std::vector<I2> newton_raphson(const I2& xs) {
|
||||
std::vector<I2> l, res;
|
||||
I2 vf, vd, x, x1, x2;
|
||||
l.push_back(xs);
|
||||
while (!l.empty()) {
|
||||
x = l.back();
|
||||
l.pop_back();
|
||||
double xx = median(x);
|
||||
vf = f<I2>(xx);
|
||||
vd = f_diff<I2>(x);
|
||||
if (zero_in(vf) && zero_in(vd)) {
|
||||
x1 = x;
|
||||
x2 = I2::empty();
|
||||
} else {
|
||||
bool x2_used;
|
||||
x1 = intersect(x, xx - division_part1(vf, vd, x2_used));
|
||||
x2 = intersect(x, xx - division_part2(vf, vd, x2_used));
|
||||
}
|
||||
if (width(x2) > width(x1)) std::swap(x1, x2);
|
||||
if (empty(x1) || !zero_in(f(x1))) {
|
||||
if (!empty(x2)) { x1 = x2; x2 = I2::empty(); }
|
||||
else continue;
|
||||
}
|
||||
if (width(x1) < max_width) res.push_back(x1);
|
||||
else if (width(x1) > alpha * width(x)) {
|
||||
std::pair<I2, I2> p = bisect(x);
|
||||
if (zero_in(f(p.first))) l.push_back(p.first);
|
||||
x2 = p.second;
|
||||
} else l.push_back(x1);
|
||||
if (!empty(x2) && zero_in(f(x2))) {
|
||||
if (width(x2) < max_width) res.push_back(x2);
|
||||
else l.push_back(x2);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class T, class Policies>
|
||||
std::ostream &operator<<(std::ostream &os,
|
||||
const boost::numeric::interval<T, Policies> &x) {
|
||||
os << "[" << x.lower() << ", " << x.upper() << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
{
|
||||
I1_aux::traits_type::rounding rnd;
|
||||
std::vector<I1> res = newton_raphson(I1(-1, 5.1));
|
||||
std::cout << "Results: " << std::endl << std::setprecision(12);
|
||||
for(std::vector<I1>::const_iterator i = res.begin(); i != res.end(); ++i)
|
||||
std::cout << " " << *i << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
{
|
||||
I2_aux::traits_type::rounding rnd;
|
||||
std::vector<I2> res = newton_raphson(I2(-1, 5.1));
|
||||
std::cout << "Results: " << std::endl << std::setprecision(12);
|
||||
for(std::vector<I2>::const_iterator i = res.begin(); i != res.end(); ++i)
|
||||
std::cout << " " << *i << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/* Boost example/rational.cpp
|
||||
* example program of how to use interval< rational<> >
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond, Sylvain Pion
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
// it would have been enough to only include:
|
||||
// <boost/numeric/interval.hpp>
|
||||
// but it's a bit overkill to include processor intrinsics
|
||||
// and transcendental functions, so we do it by ourselves
|
||||
|
||||
#include <boost/numeric/interval/interval.hpp> // base class
|
||||
#include <boost/numeric/interval/rounded_arith.hpp> // default arithmetic rounding policy
|
||||
#include <boost/numeric/interval/checking.hpp> // default checking policy
|
||||
#include <boost/numeric/interval/arith.hpp> // += *= -= etc
|
||||
#include <boost/numeric/interval/policies.hpp> // default policy
|
||||
|
||||
#include <boost/rational.hpp>
|
||||
#include <iostream>
|
||||
|
||||
typedef boost::rational<int> Rat;
|
||||
typedef boost::numeric::interval<Rat> Interval;
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Interval& r) {
|
||||
os << "[" << r.lower() << "," << r.upper() << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
Rat p(2, 3), q(3, 4);
|
||||
Interval z(4, 5);
|
||||
Interval a(p, q);
|
||||
a += z;
|
||||
z *= q;
|
||||
a -= p;
|
||||
a /= q;
|
||||
std::cout << z << std::endl;
|
||||
std::cout << a << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/* Boost example/transc.cpp
|
||||
* how to use an external library (GMP/MPFR in this case) in order to
|
||||
* get correct transcendental functions on intervals
|
||||
*
|
||||
* Copyright 2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
//extern "C" {
|
||||
#include <gmp.h>
|
||||
#include <mpfr.h>
|
||||
//}
|
||||
#include <iostream>
|
||||
|
||||
struct full_rounding:
|
||||
boost::numeric::interval_lib::rounded_arith_opp<double>
|
||||
{
|
||||
private:
|
||||
typedef int mpfr_func(mpfr_t, const __mpfr_struct*, mp_rnd_t);
|
||||
double invoke_mpfr(double x, mpfr_func f, mp_rnd_t r) {
|
||||
mpfr_t xx;
|
||||
mpfr_init_set_d(xx, x, GMP_RNDN);
|
||||
f(xx, xx, r);
|
||||
double res = mpfr_get_d(xx, r);
|
||||
mpfr_clear(xx);
|
||||
return res;
|
||||
}
|
||||
public:
|
||||
# define GENR_FUNC(name) \
|
||||
double name##_down(double x) { return invoke_mpfr(x, mpfr_##name, GMP_RNDD); } \
|
||||
double name##_up (double x) { return invoke_mpfr(x, mpfr_##name, GMP_RNDU); }
|
||||
GENR_FUNC(exp)
|
||||
GENR_FUNC(log)
|
||||
GENR_FUNC(sin)
|
||||
GENR_FUNC(cos)
|
||||
GENR_FUNC(tan)
|
||||
GENR_FUNC(asin)
|
||||
GENR_FUNC(acos)
|
||||
GENR_FUNC(atan)
|
||||
GENR_FUNC(sinh)
|
||||
GENR_FUNC(cosh)
|
||||
GENR_FUNC(tanh)
|
||||
GENR_FUNC(asinh)
|
||||
GENR_FUNC(acosh)
|
||||
GENR_FUNC(atanh)
|
||||
};
|
||||
|
||||
namespace dummy {
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
using namespace interval_lib;
|
||||
typedef save_state<full_rounding> R;
|
||||
typedef checking_strict<double> P;
|
||||
typedef interval<double, policies<R, P> > I;
|
||||
};
|
||||
|
||||
typedef dummy::I I;
|
||||
|
||||
template<class os_t>
|
||||
os_t& operator<<(os_t &os, const I &a) {
|
||||
os << '[' << a.lower() << ',' << a.upper() << ']';
|
||||
return os;
|
||||
}
|
||||
|
||||
int main() {
|
||||
I x(0.5, 2.5);
|
||||
std::cout << "x = " << x << std::endl;
|
||||
std::cout.precision(16);
|
||||
# define GENR_TEST(name) \
|
||||
std::cout << #name "(x) = " << name(x) << std::endl
|
||||
GENR_TEST(exp);
|
||||
GENR_TEST(log);
|
||||
GENR_TEST(sin);
|
||||
GENR_TEST(cos);
|
||||
GENR_TEST(tan);
|
||||
GENR_TEST(asin);
|
||||
GENR_TEST(acos);
|
||||
GENR_TEST(atan);
|
||||
GENR_TEST(sinh);
|
||||
GENR_TEST(cosh);
|
||||
GENR_TEST(tanh);
|
||||
GENR_TEST(asinh);
|
||||
GENR_TEST(acosh);
|
||||
GENR_TEST(atanh);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"key": "numeric/interval",
|
||||
"name": "Interval",
|
||||
"authors": [
|
||||
"Guillaume Melquiond",
|
||||
"Hervé Brönnimann",
|
||||
"Sylvain Pion"
|
||||
],
|
||||
"description": "Extends the usual arithmetic functions to mathematical intervals.",
|
||||
"documentation": "doc/interval.htm",
|
||||
"category": [
|
||||
"Math"
|
||||
],
|
||||
"maintainers": [
|
||||
"Sylvain Pion <Sylvain.Pion -at- sophia.inria.fr>",
|
||||
"Herve Bronnimann <hbr -at- poly.edu>",
|
||||
"Guillaume Melquiond <guillaume.melquiond -at- ens-lyon.fr>"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
# Boost Interval Library test Jamfile
|
||||
#
|
||||
# Copyright 2003 Guillaume Melquiond
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or
|
||||
# copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
project
|
||||
:
|
||||
source-location $(BOOST_ROOT)
|
||||
:
|
||||
requirements
|
||||
# Enable dynamic rounding on Tru64 (Alpha CPU).
|
||||
<toolset>hp_cxx,<os>OSF:<cflags>"-fprm d"
|
||||
<toolset>gcc,<os>OSF:<cflags>-mfp-rounding-mode=d
|
||||
;
|
||||
|
||||
# bring in rules for testing
|
||||
import testing ;
|
||||
|
||||
{
|
||||
test-suite numeric/interval :
|
||||
[ compile libs/numeric/interval/test/integer.cpp ]
|
||||
|
||||
[ run libs/numeric/interval/test/add.cpp ]
|
||||
[ run libs/numeric/interval/test/det.cpp ]
|
||||
[ run libs/numeric/interval/test/fmod.cpp ]
|
||||
[ run libs/numeric/interval/test/msvc_x64_flags.cpp ]
|
||||
[ run libs/numeric/interval/test/mul.cpp ]
|
||||
[ run libs/numeric/interval/test/overflow.cpp ]
|
||||
[ run libs/numeric/interval/test/pi.cpp ]
|
||||
[ run libs/numeric/interval/test/pow.cpp ]
|
||||
|
||||
[ run libs/numeric/interval/test/cmp.cpp
|
||||
../../../test/build//boost_test_exec_monitor/<link>static ]
|
||||
[ run libs/numeric/interval/test/cmp_exn.cpp
|
||||
../../../test/build//boost_test_exec_monitor/<link>static ]
|
||||
[ run libs/numeric/interval/test/cmp_exp.cpp
|
||||
../../../test/build//boost_test_exec_monitor/<link>static ]
|
||||
[ run libs/numeric/interval/test/cmp_lex.cpp
|
||||
../../../test/build//boost_test_exec_monitor/<link>static ]
|
||||
[ run libs/numeric/interval/test/cmp_set.cpp
|
||||
../../../test/build//boost_test_exec_monitor/<link>static ]
|
||||
[ run libs/numeric/interval/test/cmp_tribool.cpp
|
||||
../../../test/build//boost_test_exec_monitor/<link>static ]
|
||||
[ run libs/numeric/interval/test/test_float.cpp
|
||||
../../../test/build//boost_test_exec_monitor/<link>static ]
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/* Boost test/add.cpp
|
||||
* test with symbolic operations if the addition algorithm is correct
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval/interval.hpp>
|
||||
#include <boost/numeric/interval/arith.hpp>
|
||||
#include <boost/numeric/interval/rounding.hpp>
|
||||
#include <boost/numeric/interval/rounded_arith.hpp>
|
||||
#include <boost/numeric/interval/utility.hpp>
|
||||
#include <boost/numeric/interval/policies.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
typedef enum { EXPR_VAR, EXPR_NEG, EXPR_UP, EXPR_DOWN, EXPR_ADD, EXPR_SUB } e_type;
|
||||
|
||||
struct expr;
|
||||
struct pexpr {
|
||||
expr *ptr;
|
||||
expr* operator->() { return ptr; }
|
||||
pexpr(expr *p = NULL): ptr(p) { }
|
||||
};
|
||||
|
||||
struct expr {
|
||||
e_type type;
|
||||
int var;
|
||||
pexpr e;
|
||||
pexpr e1, e2;
|
||||
};
|
||||
|
||||
pexpr var(int v) {
|
||||
pexpr e = new expr;
|
||||
e->type = EXPR_VAR;
|
||||
e->var = v;
|
||||
return e;
|
||||
}
|
||||
|
||||
pexpr operator+(pexpr, pexpr);
|
||||
pexpr operator-(pexpr, pexpr);
|
||||
pexpr operator-(pexpr);
|
||||
|
||||
pexpr operator+(pexpr a, pexpr b) {
|
||||
if (a->type == EXPR_NEG) return b - a->e;
|
||||
if (b->type == EXPR_NEG) return a - b->e;
|
||||
if (a->type == EXPR_VAR && b->type == EXPR_VAR && a->var > b->var) return b + a;
|
||||
pexpr c = new expr;
|
||||
c->type = EXPR_ADD;
|
||||
c->e1 = a;
|
||||
c->e2 = b;
|
||||
return c;
|
||||
}
|
||||
|
||||
pexpr operator-(pexpr a, pexpr b) {
|
||||
if (b->type == EXPR_NEG) return a + b->e;
|
||||
pexpr c = new expr;
|
||||
c->type = EXPR_SUB;
|
||||
c->e1 = a;
|
||||
c->e2 = b;
|
||||
return c;
|
||||
}
|
||||
|
||||
pexpr down(pexpr a) {
|
||||
pexpr e = new expr;
|
||||
e->type = EXPR_DOWN;
|
||||
e->e = a;
|
||||
return e;
|
||||
}
|
||||
|
||||
pexpr up(pexpr a) {
|
||||
pexpr e = new expr;
|
||||
e->type = EXPR_UP;
|
||||
e->e = a;
|
||||
return e;
|
||||
}
|
||||
|
||||
pexpr operator-(pexpr a) {
|
||||
if (a->type == EXPR_NEG) return a->e;
|
||||
if (a->type == EXPR_UP) return down(-a->e);
|
||||
if (a->type == EXPR_DOWN) return up(-a->e);
|
||||
if (a->type == EXPR_SUB) return a->e2 - a->e1;
|
||||
if (a->type == EXPR_ADD) return -a->e1 - a->e2;
|
||||
pexpr e = new expr;
|
||||
e->type = EXPR_NEG;
|
||||
e->e = a;
|
||||
return e;
|
||||
}
|
||||
|
||||
bool operator==(pexpr a, pexpr b) {
|
||||
if (a->type != b->type) return false;
|
||||
if (a->type == EXPR_VAR) return a->var == b->var;
|
||||
if (a->type == EXPR_DOWN || a->type == EXPR_UP || a->type == EXPR_NEG)
|
||||
return a->e == b->e;
|
||||
return a->e1 == b->e1 && a->e2 == b->e2;
|
||||
}
|
||||
|
||||
bool operator<=(pexpr, pexpr) { return true; }
|
||||
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace interval_lib {
|
||||
|
||||
template<>
|
||||
struct rounding_control<pexpr> {
|
||||
typedef enum { RND_U, RND_M, RND_D } rounding_mode;
|
||||
static rounding_mode mode;
|
||||
rounding_control() { mode = RND_M; }
|
||||
void get_rounding_mode(rounding_mode& m) { m = mode; }
|
||||
void set_rounding_mode(rounding_mode m) { mode = m; }
|
||||
void upward() { mode = RND_U; }
|
||||
void downward() { mode = RND_D; }
|
||||
pexpr force_rounding(pexpr a) {
|
||||
switch (mode) {
|
||||
case RND_U: return up(a);
|
||||
case RND_D: return down(a);
|
||||
default: throw "Unset rounding mode";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
rounding_control<pexpr>::rounding_mode rounding_control<pexpr>::mode = RND_M;
|
||||
|
||||
} // namespace interval_lib
|
||||
} // namespace numeric
|
||||
} // namespace boost
|
||||
|
||||
template<class I>
|
||||
bool test_neg() {
|
||||
I a(var(0), var(1));
|
||||
return equal(-a, I(-var(1), -var(0)));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_add() {
|
||||
I a(var(0), var(1)), b(var(2), var(3));
|
||||
return equal(a + b, I(down(var(0) + var(2)), up(var(1) + var(3))));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_add1() {
|
||||
I a(var(0), var(1));
|
||||
return equal(a + var(2), I(down(var(0) + var(2)), up(var(1) + var(2))));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_add2() {
|
||||
I a(var(0), var(1));
|
||||
return equal(var(2) + a, I(down(var(0) + var(2)), up(var(1) + var(2))));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_sub() {
|
||||
I a(var(0), var(1)), b(var(2), var(3));
|
||||
return equal(a - b, I(down(var(0) - var(3)), up(var(1) - var(2))));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_sub1() {
|
||||
I a(var(0), var(1));
|
||||
return equal(a - var(2), I(down(var(0) - var(2)), up(var(1) - var(2))));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_sub2() {
|
||||
I a(var(0), var(1));
|
||||
return equal(var(2) - a, I(down(var(2) - var(1)), up(var(2) - var(0))));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_addeq() {
|
||||
I a(var(0), var(1)), b(var(2), var(3));
|
||||
return equal(a += b, I(down(var(0) + var(2)), up(var(1) + var(3))));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_addeq1() {
|
||||
I a(var(0), var(1));
|
||||
return equal(a += var(2), I(down(var(0) + var(2)), up(var(1) + var(2))));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_subeq() {
|
||||
I a(var(0), var(1)), b(var(2), var(3));
|
||||
return equal(a -= b, I(down(var(0) - var(3)), up(var(1) - var(2))));
|
||||
}
|
||||
|
||||
template<class I>
|
||||
bool test_subeq1() {
|
||||
I a(var(0), var(1));
|
||||
return equal(a -= var(2), I(down(var(0) - var(2)), up(var(1) - var(2))));
|
||||
}
|
||||
|
||||
struct my_checking
|
||||
{
|
||||
static pexpr pos_inf() { throw; }
|
||||
static pexpr neg_inf() { throw; }
|
||||
static pexpr nan() { throw; }
|
||||
static bool is_nan(const pexpr&) { return false; }
|
||||
static pexpr empty_lower() { throw; }
|
||||
static pexpr empty_upper() { throw; }
|
||||
static bool is_empty(const pexpr&, const pexpr&) { return false; }
|
||||
};
|
||||
|
||||
template<class Rounding>
|
||||
struct my_interval {
|
||||
private:
|
||||
typedef boost::numeric::interval_lib::save_state<Rounding> my_rounding;
|
||||
typedef boost::numeric::interval_lib::policies<my_rounding, my_checking> my_policies;
|
||||
public:
|
||||
typedef boost::numeric::interval<pexpr, my_policies> type;
|
||||
};
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
typedef my_interval<boost::numeric::interval_lib::rounded_arith_std<pexpr> >::type I1;
|
||||
typedef my_interval<boost::numeric::interval_lib::rounded_arith_opp<pexpr> >::type I2;
|
||||
BOOST_CHECK((test_neg<I1>()));
|
||||
BOOST_CHECK((test_neg<I2>()));
|
||||
BOOST_CHECK((test_add<I1>()));
|
||||
BOOST_CHECK((test_add<I2>()));
|
||||
BOOST_CHECK((test_add1<I1>()));
|
||||
BOOST_CHECK((test_add1<I2>()));
|
||||
BOOST_CHECK((test_add2<I1>()));
|
||||
BOOST_CHECK((test_add2<I2>()));
|
||||
BOOST_CHECK((test_sub<I1>()));
|
||||
BOOST_CHECK((test_sub<I2>()));
|
||||
BOOST_CHECK((test_sub1<I1>()));
|
||||
BOOST_CHECK((test_sub1<I2>()));
|
||||
BOOST_CHECK((test_sub2<I1>()));
|
||||
BOOST_CHECK((test_sub2<I2>()));
|
||||
BOOST_CHECK((test_addeq<I1>()));
|
||||
BOOST_CHECK((test_addeq<I2>()));
|
||||
BOOST_CHECK((test_addeq1<I1>()));
|
||||
BOOST_CHECK((test_addeq1<I2>()));
|
||||
BOOST_CHECK((test_subeq<I1>()));
|
||||
BOOST_CHECK((test_subeq<I2>()));
|
||||
BOOST_CHECK((test_subeq1<I1>()));
|
||||
BOOST_CHECK((test_subeq1<I2>()));
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/* Boost test/bugs.hpp
|
||||
* Handles namespace resolution quirks in older compilers and braindead
|
||||
* warnings [Herve, June 3rd 2003]
|
||||
*
|
||||
* Copyright 2002-2003 Hervé Brönnimann
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// Borland compiler complains about unused variables a bit easily and
|
||||
// incorrectly
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
namespace detail {
|
||||
|
||||
template <class T> inline void ignore_unused_variable_warning(const T&) { }
|
||||
|
||||
inline void ignore_warnings() {
|
||||
# ifdef BOOST_NUMERIC_INTERVAL_CONSTANTS_HPP
|
||||
using namespace boost::numeric::interval_lib::constants;
|
||||
ignore_unused_variable_warning( pi_f_l );
|
||||
ignore_unused_variable_warning( pi_f_u );
|
||||
ignore_unused_variable_warning( pi_d_l );
|
||||
ignore_unused_variable_warning( pi_d_u );
|
||||
# endif
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// Some compilers are broken with respect to name resolution
|
||||
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || defined( __BORLANDC__)
|
||||
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
using namespace interval_lib;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,215 @@
|
||||
/* Boost test/cmp.cpp
|
||||
* test standard comparison functions
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "cmp_header.hpp"
|
||||
|
||||
// comparisons between [1,2] and [3,4]
|
||||
|
||||
static void test_12_34() {
|
||||
const I a(1,2), b(3,4);
|
||||
|
||||
BOOST_CHECK(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(b > a);
|
||||
BOOST_CHECK(b >= a);
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(!(b <= a));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,3] and [2,4]
|
||||
|
||||
static void test_13_24() {
|
||||
const I a(1,3), b(2,4);
|
||||
|
||||
BOOST_C_EXN(a < b);
|
||||
BOOST_C_EXN(a <= b);
|
||||
BOOST_C_EXN(a > b);
|
||||
BOOST_C_EXN(a >= b);
|
||||
|
||||
BOOST_C_EXN(b < a);
|
||||
BOOST_C_EXN(b <= a);
|
||||
BOOST_C_EXN(b > a);
|
||||
BOOST_C_EXN(b >= a);
|
||||
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and [2,3]
|
||||
|
||||
static void test_12_23() {
|
||||
const I a(1,2), b(2,3);
|
||||
|
||||
BOOST_C_EXN(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_C_EXN(a >= b);
|
||||
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_C_EXN(b <= a);
|
||||
BOOST_C_EXN(b > a);
|
||||
BOOST_CHECK(b >= a);
|
||||
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 0
|
||||
|
||||
static void test_12_0() {
|
||||
const I a(1,2);
|
||||
const int b = 0;
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(!(a <= b));
|
||||
BOOST_CHECK(a > b);
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 1
|
||||
|
||||
static void test_12_1() {
|
||||
const I a(1,2);
|
||||
const int b = 1;
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_C_EXN(a <= b);
|
||||
BOOST_C_EXN(a > b);
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 2
|
||||
|
||||
static void test_12_2() {
|
||||
const I a(1,2);
|
||||
const int b = 2;
|
||||
|
||||
BOOST_C_EXN(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_C_EXN(a >= b);
|
||||
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 3
|
||||
|
||||
static void test_12_3() {
|
||||
const I a(1,2);
|
||||
const int b = 3;
|
||||
|
||||
BOOST_CHECK(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and [1,2]
|
||||
|
||||
static void test_12_12() {
|
||||
const I a(1,2), b(1,2);
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,1] and [1,1]
|
||||
|
||||
static void test_11_11() {
|
||||
const I a(1,1), b(1,1);
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,1] and 1
|
||||
|
||||
static void test_11_1() {
|
||||
const I a(1,1);
|
||||
const int b = 1;
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
test_12_34();
|
||||
test_13_24();
|
||||
test_12_23();
|
||||
test_12_0();
|
||||
test_12_1();
|
||||
test_12_2();
|
||||
test_12_3();
|
||||
test_12_12();
|
||||
test_11_11();
|
||||
test_11_1();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/* Boost test/cmp_exn.cpp
|
||||
* test policies with respect to exception throwing
|
||||
*
|
||||
* Copyright 2004 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval/interval.hpp>
|
||||
#include <boost/numeric/interval/checking.hpp>
|
||||
#include <boost/numeric/interval/compare.hpp>
|
||||
#include <boost/numeric/interval/policies.hpp>
|
||||
#include <boost/numeric/interval/compare/tribool.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
struct my_checking
|
||||
{
|
||||
static int nan() { return -1; }
|
||||
static bool is_nan(int x) { return x < 0; }
|
||||
static int empty_lower() { return -1; }
|
||||
static int empty_upper() { return -1; }
|
||||
static bool is_empty(int l, int u) { return l == -1 && u == -1; }
|
||||
};
|
||||
|
||||
struct empty_class {};
|
||||
|
||||
typedef boost::numeric::interval_lib::policies< empty_class, my_checking >
|
||||
my_policies;
|
||||
|
||||
typedef boost::numeric::interval<int, my_policies> I;
|
||||
|
||||
#define BOOST_C_EXN(e) \
|
||||
BOOST_CHECK_THROW(e, boost::numeric::interval_lib::comparison_error)
|
||||
|
||||
static void test_cer()
|
||||
{
|
||||
I const a(I::empty()), b(1,2);
|
||||
int const c = 0, d = my_checking::nan();
|
||||
using namespace boost::numeric::interval_lib::compare::certain;
|
||||
|
||||
BOOST_C_EXN(a < b);
|
||||
BOOST_C_EXN(a <= b);
|
||||
BOOST_C_EXN(a > b);
|
||||
BOOST_C_EXN(a >= b);
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
BOOST_C_EXN(b < a);
|
||||
BOOST_C_EXN(b <= a);
|
||||
BOOST_C_EXN(b > a);
|
||||
BOOST_C_EXN(b >= a);
|
||||
BOOST_C_EXN(b == a);
|
||||
BOOST_C_EXN(b != a);
|
||||
|
||||
BOOST_C_EXN(a < c);
|
||||
BOOST_C_EXN(a <= c);
|
||||
BOOST_C_EXN(a > c);
|
||||
BOOST_C_EXN(a >= c);
|
||||
BOOST_C_EXN(a == c);
|
||||
BOOST_C_EXN(a != c);
|
||||
BOOST_C_EXN(b < d);
|
||||
BOOST_C_EXN(b <= d);
|
||||
BOOST_C_EXN(b > d);
|
||||
BOOST_C_EXN(b >= d);
|
||||
BOOST_C_EXN(b == d);
|
||||
BOOST_C_EXN(b != d);
|
||||
}
|
||||
|
||||
static void test_def()
|
||||
{
|
||||
I const a(I::empty()), b(1,2);
|
||||
int const c = 0, d = my_checking::nan();
|
||||
|
||||
BOOST_C_EXN(a < b);
|
||||
BOOST_C_EXN(a <= b);
|
||||
BOOST_C_EXN(a > b);
|
||||
BOOST_C_EXN(a >= b);
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
BOOST_C_EXN(b < a);
|
||||
BOOST_C_EXN(b <= a);
|
||||
BOOST_C_EXN(b > a);
|
||||
BOOST_C_EXN(b >= a);
|
||||
BOOST_C_EXN(b == a);
|
||||
BOOST_C_EXN(b != a);
|
||||
|
||||
BOOST_C_EXN(a < c);
|
||||
BOOST_C_EXN(a <= c);
|
||||
BOOST_C_EXN(a > c);
|
||||
BOOST_C_EXN(a >= c);
|
||||
BOOST_C_EXN(a == c);
|
||||
BOOST_C_EXN(a != c);
|
||||
BOOST_C_EXN(b < d);
|
||||
BOOST_C_EXN(b <= d);
|
||||
BOOST_C_EXN(b > d);
|
||||
BOOST_C_EXN(b >= d);
|
||||
BOOST_C_EXN(b == d);
|
||||
BOOST_C_EXN(b != d);
|
||||
}
|
||||
|
||||
static void test_lex()
|
||||
{
|
||||
I const a(I::empty()), b(1,2);
|
||||
int const c = 0, d = my_checking::nan();
|
||||
using namespace boost::numeric::interval_lib::compare::lexicographic;
|
||||
|
||||
BOOST_C_EXN(a < b);
|
||||
BOOST_C_EXN(a <= b);
|
||||
BOOST_C_EXN(a > b);
|
||||
BOOST_C_EXN(a >= b);
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
BOOST_C_EXN(b < a);
|
||||
BOOST_C_EXN(b <= a);
|
||||
BOOST_C_EXN(b > a);
|
||||
BOOST_C_EXN(b >= a);
|
||||
BOOST_C_EXN(b == a);
|
||||
BOOST_C_EXN(b != a);
|
||||
|
||||
BOOST_C_EXN(a < c);
|
||||
BOOST_C_EXN(a <= c);
|
||||
BOOST_C_EXN(a > c);
|
||||
BOOST_C_EXN(a >= c);
|
||||
BOOST_C_EXN(a == c);
|
||||
BOOST_C_EXN(a != c);
|
||||
BOOST_C_EXN(b < d);
|
||||
BOOST_C_EXN(b <= d);
|
||||
BOOST_C_EXN(b > d);
|
||||
BOOST_C_EXN(b >= d);
|
||||
BOOST_C_EXN(b == d);
|
||||
BOOST_C_EXN(b != d);
|
||||
}
|
||||
|
||||
static void test_pos()
|
||||
{
|
||||
I const a(I::empty()), b(1,2);
|
||||
int const c = 0, d = my_checking::nan();
|
||||
using namespace boost::numeric::interval_lib::compare::possible;
|
||||
|
||||
BOOST_C_EXN(a < b);
|
||||
BOOST_C_EXN(a <= b);
|
||||
BOOST_C_EXN(a > b);
|
||||
BOOST_C_EXN(a >= b);
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
BOOST_C_EXN(b < a);
|
||||
BOOST_C_EXN(b <= a);
|
||||
BOOST_C_EXN(b > a);
|
||||
BOOST_C_EXN(b >= a);
|
||||
BOOST_C_EXN(b == a);
|
||||
BOOST_C_EXN(b != a);
|
||||
|
||||
BOOST_C_EXN(a < c);
|
||||
BOOST_C_EXN(a <= c);
|
||||
BOOST_C_EXN(a > c);
|
||||
BOOST_C_EXN(a >= c);
|
||||
BOOST_C_EXN(a == c);
|
||||
BOOST_C_EXN(a != c);
|
||||
BOOST_C_EXN(b < d);
|
||||
BOOST_C_EXN(b <= d);
|
||||
BOOST_C_EXN(b > d);
|
||||
BOOST_C_EXN(b >= d);
|
||||
BOOST_C_EXN(b == d);
|
||||
BOOST_C_EXN(b != d);
|
||||
}
|
||||
|
||||
static void test_set()
|
||||
{
|
||||
I const a(I::empty()), b(1,2);
|
||||
int const c = 0;
|
||||
using namespace boost::numeric::interval_lib::compare::set;
|
||||
|
||||
BOOST_C_EXN(a < c);
|
||||
BOOST_C_EXN(a <= c);
|
||||
BOOST_C_EXN(a > c);
|
||||
BOOST_C_EXN(a >= c);
|
||||
BOOST_C_EXN(a == c);
|
||||
BOOST_C_EXN(a != c);
|
||||
BOOST_C_EXN(b < c);
|
||||
BOOST_C_EXN(b <= c);
|
||||
BOOST_C_EXN(b > c);
|
||||
BOOST_C_EXN(b >= c);
|
||||
BOOST_C_EXN(b == c);
|
||||
BOOST_C_EXN(b != c);
|
||||
}
|
||||
|
||||
static void test_tri()
|
||||
{
|
||||
I const a(I::empty()), b(1,2);
|
||||
int const c = 0, d = my_checking::nan();
|
||||
using namespace boost::numeric::interval_lib::compare::tribool;
|
||||
|
||||
BOOST_C_EXN(a < b);
|
||||
BOOST_C_EXN(a <= b);
|
||||
BOOST_C_EXN(a > b);
|
||||
BOOST_C_EXN(a >= b);
|
||||
BOOST_C_EXN(a == b);
|
||||
BOOST_C_EXN(a != b);
|
||||
BOOST_C_EXN(b < a);
|
||||
BOOST_C_EXN(b <= a);
|
||||
BOOST_C_EXN(b > a);
|
||||
BOOST_C_EXN(b >= a);
|
||||
BOOST_C_EXN(b == a);
|
||||
BOOST_C_EXN(b != a);
|
||||
|
||||
BOOST_C_EXN(a < c);
|
||||
BOOST_C_EXN(a <= c);
|
||||
BOOST_C_EXN(a > c);
|
||||
BOOST_C_EXN(a >= c);
|
||||
BOOST_C_EXN(a == c);
|
||||
BOOST_C_EXN(a != c);
|
||||
BOOST_C_EXN(b < d);
|
||||
BOOST_C_EXN(b <= d);
|
||||
BOOST_C_EXN(b > d);
|
||||
BOOST_C_EXN(b >= d);
|
||||
BOOST_C_EXN(b == d);
|
||||
BOOST_C_EXN(b != d);
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
test_cer();
|
||||
test_def();
|
||||
test_lex();
|
||||
test_pos();
|
||||
test_set();
|
||||
test_tri();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
/* Boost test/cmp_exp.cpp
|
||||
* test explicit comparison functions
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "cmp_header.hpp"
|
||||
|
||||
// comparisons between [1,2] and [3,4]
|
||||
|
||||
static void test_12_34() {
|
||||
const I a(1,2), b(3,4);
|
||||
|
||||
BOOST_CHECK(cerlt(a, b));
|
||||
BOOST_CHECK(cerle(a, b));
|
||||
BOOST_CHECK(!cergt(a, b));
|
||||
BOOST_CHECK(!cerge(a, b));
|
||||
|
||||
BOOST_CHECK(!cerlt(b, a));
|
||||
BOOST_CHECK(!cerle(b, a));
|
||||
BOOST_CHECK(cergt(b, a));
|
||||
BOOST_CHECK(cerge(b, a));
|
||||
|
||||
BOOST_CHECK(poslt(a, b));
|
||||
BOOST_CHECK(posle(a, b));
|
||||
BOOST_CHECK(!posgt(a, b));
|
||||
BOOST_CHECK(!posge(a, b));
|
||||
|
||||
BOOST_CHECK(!poslt(b, a));
|
||||
BOOST_CHECK(!posle(b, a));
|
||||
BOOST_CHECK(posgt(b, a));
|
||||
BOOST_CHECK(posge(b, a));
|
||||
|
||||
BOOST_CHECK(!cereq(a, b));
|
||||
BOOST_CHECK(cerne(a, b));
|
||||
BOOST_CHECK(!poseq(a, b));
|
||||
BOOST_CHECK(posne(a, b));
|
||||
|
||||
BOOST_CHECK(!cereq(b, a));
|
||||
BOOST_CHECK(cerne(b, a));
|
||||
BOOST_CHECK(!poseq(b, a));
|
||||
BOOST_CHECK(posne(b, a));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,3] and [2,4]
|
||||
|
||||
static void test_13_24() {
|
||||
const I a(1,3), b(2,4);
|
||||
|
||||
BOOST_CHECK(!cerlt(a, b));
|
||||
BOOST_CHECK(!cerle(a, b));
|
||||
BOOST_CHECK(!cergt(a, b));
|
||||
BOOST_CHECK(!cerge(a, b));
|
||||
|
||||
BOOST_CHECK(!cerlt(b, a));
|
||||
BOOST_CHECK(!cerle(b, a));
|
||||
BOOST_CHECK(!cergt(b, a));
|
||||
BOOST_CHECK(!cerge(b, a));
|
||||
|
||||
BOOST_CHECK(poslt(a, b));
|
||||
BOOST_CHECK(posle(a, b));
|
||||
BOOST_CHECK(posgt(a, b));
|
||||
BOOST_CHECK(posge(a, b));
|
||||
|
||||
BOOST_CHECK(poslt(b, a));
|
||||
BOOST_CHECK(posle(b, a));
|
||||
BOOST_CHECK(posgt(b, a));
|
||||
BOOST_CHECK(posge(b, a));
|
||||
|
||||
BOOST_CHECK(!cereq(a, b));
|
||||
BOOST_CHECK(!cerne(a, b));
|
||||
BOOST_CHECK(poseq(a, b));
|
||||
BOOST_CHECK(posne(a, b));
|
||||
|
||||
BOOST_CHECK(!cereq(b, a));
|
||||
BOOST_CHECK(!cerne(b, a));
|
||||
BOOST_CHECK(poseq(b, a));
|
||||
BOOST_CHECK(posne(b, a));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and [2,3]
|
||||
|
||||
static void test_12_23() {
|
||||
const I a(1,2), b(2,3);
|
||||
|
||||
BOOST_CHECK(!cerlt(a, b));
|
||||
BOOST_CHECK(cerle(a, b));
|
||||
BOOST_CHECK(!cergt(a, b));
|
||||
BOOST_CHECK(!cerge(a, b));
|
||||
|
||||
BOOST_CHECK(!cerlt(b, a));
|
||||
BOOST_CHECK(!cerle(b, a));
|
||||
BOOST_CHECK(!cergt(b, a));
|
||||
BOOST_CHECK(cerge(b, a));
|
||||
|
||||
BOOST_CHECK(poslt(a, b));
|
||||
BOOST_CHECK(posle(a, b));
|
||||
BOOST_CHECK(!posgt(a, b));
|
||||
BOOST_CHECK(posge(a, b));
|
||||
|
||||
BOOST_CHECK(!poslt(b, a));
|
||||
BOOST_CHECK(posle(b, a));
|
||||
BOOST_CHECK(posgt(b, a));
|
||||
BOOST_CHECK(posge(b, a));
|
||||
|
||||
BOOST_CHECK(!cereq(a, b));
|
||||
BOOST_CHECK(!cerne(a, b));
|
||||
BOOST_CHECK(poseq(a, b));
|
||||
BOOST_CHECK(posne(a, b));
|
||||
|
||||
BOOST_CHECK(!cereq(b, a));
|
||||
BOOST_CHECK(!cerne(b, a));
|
||||
BOOST_CHECK(poseq(b, a));
|
||||
BOOST_CHECK(posne(b, a));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 0
|
||||
|
||||
static void test_12_0() {
|
||||
const I a(1,2);
|
||||
const int b = 0;
|
||||
|
||||
BOOST_CHECK(!cerlt(a, b));
|
||||
BOOST_CHECK(!cerle(a, b));
|
||||
BOOST_CHECK(cergt(a, b));
|
||||
BOOST_CHECK(cerge(a, b));
|
||||
|
||||
BOOST_CHECK(cerlt(b, a));
|
||||
BOOST_CHECK(cerle(b, a));
|
||||
BOOST_CHECK(!cergt(b, a));
|
||||
BOOST_CHECK(!cerge(b, a));
|
||||
|
||||
BOOST_CHECK(!poslt(a, b));
|
||||
BOOST_CHECK(!posle(a, b));
|
||||
BOOST_CHECK(posgt(a, b));
|
||||
BOOST_CHECK(posge(a, b));
|
||||
|
||||
BOOST_CHECK(poslt(b, a));
|
||||
BOOST_CHECK(posle(b, a));
|
||||
BOOST_CHECK(!posgt(b, a));
|
||||
BOOST_CHECK(!posge(b, a));
|
||||
|
||||
BOOST_CHECK(!cereq(a, b));
|
||||
BOOST_CHECK(cerne(a, b));
|
||||
BOOST_CHECK(!poseq(a, b));
|
||||
BOOST_CHECK(posne(a, b));
|
||||
|
||||
BOOST_CHECK(!cereq(b, a));
|
||||
BOOST_CHECK(cerne(b, a));
|
||||
BOOST_CHECK(!poseq(b, a));
|
||||
BOOST_CHECK(posne(b, a));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 1
|
||||
|
||||
static void test_12_1() {
|
||||
const I a(1,2);
|
||||
const int b = 1;
|
||||
|
||||
BOOST_CHECK(!cerlt(a, b));
|
||||
BOOST_CHECK(!cerle(a, b));
|
||||
BOOST_CHECK(!cergt(a, b));
|
||||
BOOST_CHECK(cerge(a, b));
|
||||
|
||||
BOOST_CHECK(!cerlt(b, a));
|
||||
BOOST_CHECK(cerle(b, a));
|
||||
BOOST_CHECK(!cergt(b, a));
|
||||
BOOST_CHECK(!cerge(b, a));
|
||||
|
||||
BOOST_CHECK(!poslt(a, b));
|
||||
BOOST_CHECK(posle(a, b));
|
||||
BOOST_CHECK(posgt(a, b));
|
||||
BOOST_CHECK(posge(a, b));
|
||||
|
||||
BOOST_CHECK(poslt(b, a));
|
||||
BOOST_CHECK(posle(b, a));
|
||||
BOOST_CHECK(!posgt(b, a));
|
||||
BOOST_CHECK(posge(b, a));
|
||||
|
||||
BOOST_CHECK(!cereq(a, b));
|
||||
BOOST_CHECK(!cerne(a, b));
|
||||
BOOST_CHECK(poseq(a, b));
|
||||
BOOST_CHECK(posne(a, b));
|
||||
|
||||
BOOST_CHECK(!cereq(b, a));
|
||||
BOOST_CHECK(!cerne(b, a));
|
||||
BOOST_CHECK(poseq(b, a));
|
||||
BOOST_CHECK(posne(b, a));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 2
|
||||
|
||||
static void test_12_2() {
|
||||
const I a(1,2);
|
||||
const int b = 2;
|
||||
|
||||
BOOST_CHECK(!cerlt(a, b));
|
||||
BOOST_CHECK(cerle(a, b));
|
||||
BOOST_CHECK(!cergt(a, b));
|
||||
BOOST_CHECK(!cerge(a, b));
|
||||
|
||||
BOOST_CHECK(!cerlt(b, a));
|
||||
BOOST_CHECK(!cerle(b, a));
|
||||
BOOST_CHECK(!cergt(b, a));
|
||||
BOOST_CHECK(cerge(b, a));
|
||||
|
||||
BOOST_CHECK(poslt(a, b));
|
||||
BOOST_CHECK(posle(a, b));
|
||||
BOOST_CHECK(!posgt(a, b));
|
||||
BOOST_CHECK(posge(a, b));
|
||||
|
||||
BOOST_CHECK(!poslt(b, a));
|
||||
BOOST_CHECK(posle(b, a));
|
||||
BOOST_CHECK(posgt(b, a));
|
||||
BOOST_CHECK(posge(b, a));
|
||||
|
||||
BOOST_CHECK(!cereq(a, b));
|
||||
BOOST_CHECK(!cerne(a, b));
|
||||
BOOST_CHECK(poseq(a, b));
|
||||
BOOST_CHECK(posne(a, b));
|
||||
|
||||
BOOST_CHECK(!cereq(b, a));
|
||||
BOOST_CHECK(!cerne(b, a));
|
||||
BOOST_CHECK(poseq(b, a));
|
||||
BOOST_CHECK(posne(b, a));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 3
|
||||
|
||||
static void test_12_3() {
|
||||
const I a(1,2);
|
||||
const int b = 3;
|
||||
|
||||
BOOST_CHECK(cerlt(a, b));
|
||||
BOOST_CHECK(cerle(a, b));
|
||||
BOOST_CHECK(!cergt(a, b));
|
||||
BOOST_CHECK(!cerge(a, b));
|
||||
|
||||
BOOST_CHECK(!cerlt(b, a));
|
||||
BOOST_CHECK(!cerle(b, a));
|
||||
BOOST_CHECK(cergt(b, a));
|
||||
BOOST_CHECK(cerge(b, a));
|
||||
|
||||
BOOST_CHECK(poslt(a, b));
|
||||
BOOST_CHECK(posle(a, b));
|
||||
BOOST_CHECK(!posgt(a, b));
|
||||
BOOST_CHECK(!posge(a, b));
|
||||
|
||||
BOOST_CHECK(!poslt(b, a));
|
||||
BOOST_CHECK(!posle(b, a));
|
||||
BOOST_CHECK(posgt(b, a));
|
||||
BOOST_CHECK(posge(b, a));
|
||||
|
||||
BOOST_CHECK(!cereq(a, b));
|
||||
BOOST_CHECK(cerne(a, b));
|
||||
BOOST_CHECK(!poseq(a, b));
|
||||
BOOST_CHECK(posne(a, b));
|
||||
|
||||
BOOST_CHECK(!cereq(b, a));
|
||||
BOOST_CHECK(cerne(b, a));
|
||||
BOOST_CHECK(!poseq(b, a));
|
||||
BOOST_CHECK(posne(b, a));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void test_12_12() {
|
||||
const I a(1,2), b(1,2);
|
||||
BOOST_CHECK(!cereq(a, b));
|
||||
BOOST_CHECK(!cerne(a, b));
|
||||
BOOST_CHECK(poseq(a, b));
|
||||
BOOST_CHECK(posne(a, b));
|
||||
BOOST_CHECK(!cereq(b, a));
|
||||
BOOST_CHECK(!cerne(b, a));
|
||||
BOOST_CHECK(poseq(b, a));
|
||||
BOOST_CHECK(posne(b, a));
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void test_11_11() {
|
||||
const I a(1,1), b(1,1);
|
||||
BOOST_CHECK(cereq(a, b));
|
||||
BOOST_CHECK(!cerne(a, b));
|
||||
BOOST_CHECK(poseq(a, b));
|
||||
BOOST_CHECK(!posne(a, b));
|
||||
BOOST_CHECK(cereq(b, a));
|
||||
BOOST_CHECK(!cerne(b, a));
|
||||
BOOST_CHECK(poseq(b, a));
|
||||
BOOST_CHECK(!posne(b, a));
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void test_11_1() {
|
||||
const I a(1,1);
|
||||
const int b = 1;
|
||||
BOOST_CHECK(cereq(a, b));
|
||||
BOOST_CHECK(!cerne(a, b));
|
||||
BOOST_CHECK(poseq(a, b));
|
||||
BOOST_CHECK(!posne(a, b));
|
||||
BOOST_CHECK(cereq(b, a));
|
||||
BOOST_CHECK(!cerne(b, a));
|
||||
BOOST_CHECK(poseq(b, a));
|
||||
BOOST_CHECK(!posne(b, a));
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
test_12_34();
|
||||
test_13_24();
|
||||
test_12_23();
|
||||
test_12_0();
|
||||
test_12_1();
|
||||
test_12_2();
|
||||
test_12_3();
|
||||
test_12_12();
|
||||
test_11_11();
|
||||
test_11_1();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/* Boost test/cmp_header.hpp header file
|
||||
*
|
||||
* Copyright 2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval/interval.hpp>
|
||||
#include <boost/numeric/interval/checking.hpp>
|
||||
#include <boost/numeric/interval/compare.hpp>
|
||||
#include <boost/numeric/interval/policies.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
struct empty_class {};
|
||||
|
||||
typedef boost::numeric::interval_lib::policies
|
||||
<empty_class, boost::numeric::interval_lib::checking_base<int> >
|
||||
my_policies;
|
||||
|
||||
typedef boost::numeric::interval<int, my_policies> I;
|
||||
|
||||
#define BOOST_C_EXN(e) \
|
||||
BOOST_CHECK_THROW(e, boost::numeric::interval_lib::comparison_error)
|
||||
@@ -0,0 +1,217 @@
|
||||
/* Boost test/cmp_lex.cpp
|
||||
* test compare::lexicographic
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "cmp_header.hpp"
|
||||
|
||||
using namespace boost::numeric::interval_lib::compare::lexicographic;
|
||||
|
||||
// comparisons between [1,2] and [3,4]
|
||||
|
||||
static void test_12_34() {
|
||||
const I a(1,2), b(3,4);
|
||||
|
||||
BOOST_CHECK(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(b > a);
|
||||
BOOST_CHECK(b >= a);
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(!(b <= a));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,3] and [2,4]
|
||||
|
||||
static void test_13_24() {
|
||||
const I a(1,3), b(2,4);
|
||||
|
||||
BOOST_CHECK(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(!(b <= a));
|
||||
BOOST_CHECK(b > a);
|
||||
BOOST_CHECK(b >= a);
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and [2,3]
|
||||
|
||||
static void test_12_23() {
|
||||
const I a(1,2), b(2,3);
|
||||
|
||||
BOOST_CHECK(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(!(b <= a));
|
||||
BOOST_CHECK(b > a);
|
||||
BOOST_CHECK(b >= a);
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 0
|
||||
|
||||
static void test_12_0() {
|
||||
const I a(1,2);
|
||||
const int b = 0;
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(!(a <= b));
|
||||
BOOST_CHECK(a > b);
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 1
|
||||
|
||||
static void test_12_1() {
|
||||
const I a(1,2);
|
||||
const int b = 1;
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(!(a <= b));
|
||||
BOOST_CHECK(a > b);
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 2
|
||||
|
||||
static void test_12_2() {
|
||||
const I a(1,2);
|
||||
const int b = 2;
|
||||
|
||||
BOOST_CHECK(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 3
|
||||
|
||||
static void test_12_3() {
|
||||
const I a(1,2);
|
||||
const int b = 3;
|
||||
|
||||
BOOST_CHECK(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void test_12_12() {
|
||||
const I a(1,2), b(1,2);
|
||||
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void test_11_11() {
|
||||
const I a(1,1), b(1,1);
|
||||
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void test_11_1() {
|
||||
const I a(1,1);
|
||||
const int b = 1;
|
||||
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
test_12_34();
|
||||
test_13_24();
|
||||
test_12_23();
|
||||
test_12_0();
|
||||
test_12_1();
|
||||
test_12_2();
|
||||
test_12_3();
|
||||
test_12_12();
|
||||
test_11_11();
|
||||
test_11_1();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/* Boost test/cmp_set.cpp
|
||||
* test compare::set
|
||||
*
|
||||
* Copyright 2004 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "cmp_header.hpp"
|
||||
|
||||
using namespace boost::numeric::interval_lib::compare::set;
|
||||
|
||||
// comparisons between [1,2] and [3,4]
|
||||
|
||||
static void test_12_34() {
|
||||
const I a(1,2), b(3,4);
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(!(a <= b));
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(!(b > a));
|
||||
BOOST_CHECK(!(b >= a));
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(!(b <= a));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,3] and [2,4]
|
||||
|
||||
static void test_13_24() {
|
||||
const I a(1,3), b(2,4);
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(!(a <= b));
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(!(b <= a));
|
||||
BOOST_CHECK(!(b > a));
|
||||
BOOST_CHECK(!(b >= a));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,4] and [2,3]
|
||||
|
||||
static void test_14_23() {
|
||||
const I a(1,4), b(2,3);
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(!(a <= b));
|
||||
BOOST_CHECK(a > b);
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(b < a);
|
||||
BOOST_CHECK(b <= a);
|
||||
BOOST_CHECK(!(b > a));
|
||||
BOOST_CHECK(!(b >= a));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and [2,3]
|
||||
|
||||
static void test_12_23() {
|
||||
const I a(1,2), b(2,3);
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(!(a <= b));
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(!(b <= a));
|
||||
BOOST_CHECK(!(b > a));
|
||||
BOOST_CHECK(!(b >= a));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and empty set
|
||||
|
||||
static void test_12_E() {
|
||||
I a(1, 2), b(I::empty());
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(!(a <= b));
|
||||
BOOST_CHECK(a > b);
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(b < a);
|
||||
BOOST_CHECK(b <= a);
|
||||
BOOST_CHECK(!(b > a));
|
||||
BOOST_CHECK(!(b >= a));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between two empty sets
|
||||
|
||||
static void test_E_E() {
|
||||
I a(I::empty()), b(I::empty());
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(b <= a);
|
||||
BOOST_CHECK(!(b > a));
|
||||
BOOST_CHECK(b >= a);
|
||||
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and [1,2]
|
||||
|
||||
static void test_12_12() {
|
||||
const I a(1,2), b(1,2);
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(b <= a);
|
||||
BOOST_CHECK(!(b > a));
|
||||
BOOST_CHECK(b >= a);
|
||||
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,1] and [1,1]
|
||||
|
||||
static void test_11_11() {
|
||||
const I a(1,1), b(1,1);
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(b <= a);
|
||||
BOOST_CHECK(!(b > a));
|
||||
BOOST_CHECK(b >= a);
|
||||
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
test_12_34();
|
||||
test_13_24();
|
||||
test_14_23();
|
||||
test_12_23();
|
||||
test_12_E();
|
||||
test_E_E();
|
||||
test_12_12();
|
||||
test_11_11();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/* Boost test/cmp_tribool.cpp
|
||||
* test compare::tribool
|
||||
*
|
||||
* Copyright 2004 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "cmp_header.hpp"
|
||||
#include <boost/numeric/interval/compare/tribool.hpp>
|
||||
|
||||
using namespace boost::numeric::interval_lib::compare::tribool;
|
||||
|
||||
// comparisons between [1,2] and [3,4]
|
||||
|
||||
static void test_12_34() {
|
||||
const I a(1,2), b(3,4);
|
||||
|
||||
BOOST_CHECK(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(b > a);
|
||||
BOOST_CHECK(b >= a);
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(!(b <= a));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,3] and [2,4]
|
||||
|
||||
static void test_13_24() {
|
||||
const I a(1,3), b(2,4);
|
||||
|
||||
BOOST_CHECK(indeterminate(a < b));
|
||||
BOOST_CHECK(indeterminate(a <= b));
|
||||
BOOST_CHECK(indeterminate(a > b));
|
||||
BOOST_CHECK(indeterminate(a >= b));
|
||||
|
||||
BOOST_CHECK(indeterminate(b < a));
|
||||
BOOST_CHECK(indeterminate(b <= a));
|
||||
BOOST_CHECK(indeterminate(b > a));
|
||||
BOOST_CHECK(indeterminate(b >= a));
|
||||
|
||||
BOOST_CHECK(indeterminate(a == b));
|
||||
BOOST_CHECK(indeterminate(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and [2,3]
|
||||
|
||||
static void test_12_23() {
|
||||
const I a(1,2), b(2,3);
|
||||
|
||||
BOOST_CHECK(indeterminate(a < b));
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(indeterminate(a >= b));
|
||||
|
||||
BOOST_CHECK(!(b < a));
|
||||
BOOST_CHECK(indeterminate(b <= a));
|
||||
BOOST_CHECK(indeterminate(b > a));
|
||||
BOOST_CHECK(b >= a);
|
||||
|
||||
BOOST_CHECK(indeterminate(a == b));
|
||||
BOOST_CHECK(indeterminate(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 0
|
||||
|
||||
static void test_12_0() {
|
||||
const I a(1,2);
|
||||
const int b = 0;
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(!(a <= b));
|
||||
BOOST_CHECK(a > b);
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 1
|
||||
|
||||
static void test_12_1() {
|
||||
const I a(1,2);
|
||||
const int b = 1;
|
||||
|
||||
BOOST_CHECK(!(a < b));
|
||||
BOOST_CHECK(indeterminate(a <= b));
|
||||
BOOST_CHECK(indeterminate(a > b));
|
||||
BOOST_CHECK(a >= b);
|
||||
|
||||
BOOST_CHECK(indeterminate(a == b));
|
||||
BOOST_CHECK(indeterminate(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 2
|
||||
|
||||
static void test_12_2() {
|
||||
const I a(1,2);
|
||||
const int b = 2;
|
||||
|
||||
BOOST_CHECK(indeterminate(a < b));
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(indeterminate(a >= b));
|
||||
|
||||
BOOST_CHECK(indeterminate(a == b));
|
||||
BOOST_CHECK(indeterminate(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and 3
|
||||
|
||||
static void test_12_3() {
|
||||
const I a(1,2);
|
||||
const int b = 3;
|
||||
|
||||
BOOST_CHECK(a < b);
|
||||
BOOST_CHECK(a <= b);
|
||||
BOOST_CHECK(!(a > b));
|
||||
BOOST_CHECK(!(a >= b));
|
||||
|
||||
BOOST_CHECK(!(a == b));
|
||||
BOOST_CHECK(a != b);
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,2] and [1,2]
|
||||
|
||||
static void test_12_12() {
|
||||
const I a(1,2), b(1,2);
|
||||
|
||||
BOOST_CHECK(indeterminate(a == b));
|
||||
BOOST_CHECK(indeterminate(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,1] and [1,1]
|
||||
|
||||
static void test_11_11() {
|
||||
const I a(1,1), b(1,1);
|
||||
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
// comparisons between [1,1] and 1
|
||||
|
||||
static void test_11_1() {
|
||||
const I a(1,1);
|
||||
const int b = 1;
|
||||
|
||||
BOOST_CHECK(a == b);
|
||||
BOOST_CHECK(!(a != b));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(a);
|
||||
::detail::ignore_unused_variable_warning(b);
|
||||
# endif
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
test_12_34();
|
||||
test_13_24();
|
||||
test_12_23();
|
||||
test_12_0();
|
||||
test_12_1();
|
||||
test_12_2();
|
||||
test_12_3();
|
||||
test_12_12();
|
||||
test_11_11();
|
||||
test_11_1();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/* Boost test/det.cpp
|
||||
* test protected and unprotected rounding on an unstable determinant
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
#define size 8
|
||||
|
||||
template<class I>
|
||||
void det(I (&mat)[size][size]) {
|
||||
for(int i = 0; i < size; i++)
|
||||
for(int j = 0; j < size; j++)
|
||||
mat[i][j] = I(1) / I(i + j + 1);
|
||||
|
||||
for(int i = 0; i < size - 1; i++) {
|
||||
int m = i, n = i;
|
||||
typename I::base_type v = 0;
|
||||
for(int a = i; a < size; a++)
|
||||
for(int b = i; b < size; b++) {
|
||||
typename I::base_type w = abs(mat[a][b]).lower();
|
||||
if (w > v) { m = a; n = b; v = w; }
|
||||
}
|
||||
if (n != i)
|
||||
for(int a = 0; a < size; a++) {
|
||||
I t = mat[a][n];
|
||||
mat[a][n] = mat[a][i];
|
||||
mat[a][i] = t;
|
||||
}
|
||||
if (m != i)
|
||||
for(int b = i; b < size; b++) {
|
||||
I t = mat[m][b];
|
||||
mat[m][b] = mat[m][i];
|
||||
mat[m][i] = t;
|
||||
}
|
||||
if (((m + n) & 1) == 1) { };
|
||||
I c = mat[i][i];
|
||||
for(int j = i + 1; j < size; j++) {
|
||||
I f = mat[j][i] / c;
|
||||
for(int k = i; k < size; k++)
|
||||
mat[j][k] -= f * mat[i][k];
|
||||
}
|
||||
if (zero_in(c)) return;
|
||||
}
|
||||
}
|
||||
|
||||
namespace my_namespace {
|
||||
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
using namespace interval_lib;
|
||||
|
||||
template<class T>
|
||||
struct variants {
|
||||
typedef interval<T> I_op;
|
||||
typedef typename change_rounding<I_op, save_state<rounded_arith_std<T> > >::type I_sp;
|
||||
typedef typename unprotect<I_op>::type I_ou;
|
||||
typedef typename unprotect<I_sp>::type I_su;
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool test() {
|
||||
typedef my_namespace::variants<double> types;
|
||||
types::I_op mat_op[size][size];
|
||||
types::I_sp mat_sp[size][size];
|
||||
types::I_ou mat_ou[size][size];
|
||||
types::I_su mat_su[size][size];
|
||||
det(mat_op);
|
||||
det(mat_sp);
|
||||
{ types::I_op::traits_type::rounding rnd; det(mat_ou); }
|
||||
{ types::I_sp::traits_type::rounding rnd; det(mat_su); }
|
||||
for(int i = 0; i < size; i++)
|
||||
for(int j = 0; j < size; j++) {
|
||||
typedef types::I_op I;
|
||||
I d_op = mat_op[i][j];
|
||||
I d_sp = mat_sp[i][j];
|
||||
I d_ou = mat_ou[i][j];
|
||||
I d_su = mat_su[i][j];
|
||||
if (!(equal(d_op, d_sp) && equal(d_sp, d_ou) && equal(d_ou, d_su)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
BOOST_CHECK(test<float>());
|
||||
BOOST_CHECK(test<double>());
|
||||
BOOST_CHECK(test<long double>());
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_warnings();
|
||||
# endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Boost test/fmod.cpp
|
||||
* test the fmod with specially crafted integer intervals
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval/interval.hpp>
|
||||
#include <boost/numeric/interval/arith.hpp>
|
||||
#include <boost/numeric/interval/arith2.hpp>
|
||||
#include <boost/numeric/interval/utility.hpp>
|
||||
#include <boost/numeric/interval/checking.hpp>
|
||||
#include <boost/numeric/interval/rounding.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
struct my_rounded_arith {
|
||||
int sub_down(int x, int y) { return x - y; }
|
||||
int sub_up (int x, int y) { return x - y; }
|
||||
int mul_down(int x, int y) { return x * y; }
|
||||
int mul_up (int x, int y) { return x * y; }
|
||||
int div_down(int x, int y) {
|
||||
int q = x / y;
|
||||
return (x % y < 0) ? (q - 1) : q;
|
||||
}
|
||||
int int_down(int x) { return x; }
|
||||
};
|
||||
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
using namespace interval_lib;
|
||||
|
||||
typedef change_rounding<interval<int>, save_state_nothing<my_rounded_arith> >::type I;
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
|
||||
BOOST_CHECK(equal(fmod(I(6,9), 7), I(6,9)));
|
||||
BOOST_CHECK(equal(fmod(6, I(7,8)), I(6,6)));
|
||||
BOOST_CHECK(equal(fmod(I(6,9), I(7,8)), I(6,9)));
|
||||
|
||||
BOOST_CHECK(equal(fmod(I(13,17), 7), I(6,10)));
|
||||
BOOST_CHECK(equal(fmod(13, I(7,8)), I(5,6)));
|
||||
BOOST_CHECK(equal(fmod(I(13,17), I(7,8)), I(5,10)));
|
||||
|
||||
BOOST_CHECK(equal(fmod(I(-17,-13), 7), I(4,8)));
|
||||
BOOST_CHECK(equal(fmod(-17, I(7,8)), I(4,7)));
|
||||
BOOST_CHECK(equal(fmod(I(-17,-13), I(7,8)), I(4,11)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Boost test/integer.cpp
|
||||
* test int extension
|
||||
*
|
||||
* Copyright 2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <boost/numeric/interval/ext/integer.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
typedef boost::numeric::interval<float> I;
|
||||
|
||||
int main() {
|
||||
I x, y;
|
||||
x = 4 - (2 * y + 1) / 3;
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_warnings();
|
||||
# endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/* Boost test/msvc_x64_flags.cpp
|
||||
* Test for amd64\ieee.c(102) : Assertion failed: (mask&~(_MCW_DN|_MCW_EM|_MCW_RC))==0.
|
||||
* This happens with MSVC on x64 in Debug mode. See ticket #4964.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
boost::numeric::interval<double> i(0.0, 0.0);
|
||||
boost::numeric::interval<double> i2 = 60.0 - i;
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_warnings();
|
||||
# endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/* Boost test/mul.cpp
|
||||
* test multiplication, division, square and square root on some intervals
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
typedef boost::numeric::interval<double> I;
|
||||
|
||||
static double min BOOST_PREVENT_MACRO_SUBSTITUTION (double a, double b, double c, double d) {
|
||||
return (std::min)((std::min)(a, b), (std::min)(c, d));
|
||||
}
|
||||
|
||||
static double max BOOST_PREVENT_MACRO_SUBSTITUTION (double a, double b, double c, double d) {
|
||||
return (std::max)((std::max)(a, b), (std::max)(c, d));
|
||||
}
|
||||
|
||||
static bool test_mul(double al, double au, double bl, double bu) {
|
||||
I a(al, au), b(bl, bu);
|
||||
I c = a * b;
|
||||
return c.lower() == (min)(al*bl, al*bu, au*bl, au*bu)
|
||||
&& c.upper() == (max)(al*bl, al*bu, au*bl, au*bu);
|
||||
}
|
||||
|
||||
static bool test_mul1(double ac, double bl, double bu) {
|
||||
I a(ac), b(bl, bu);
|
||||
I c = ac * b;
|
||||
I d = b * ac;
|
||||
I e = a * b;
|
||||
return equal(c, d) && equal(d, e);
|
||||
}
|
||||
|
||||
static bool test_div(double al, double au, double bl, double bu) {
|
||||
I a(al, au), b(bl, bu);
|
||||
I c = a / b;
|
||||
return c.lower() == (min)(al/bl, al/bu, au/bl, au/bu)
|
||||
&& c.upper() == (max)(al/bl, al/bu, au/bl, au/bu);
|
||||
}
|
||||
|
||||
static bool test_div1(double al, double au, double bc) {
|
||||
I a(al, au), b(bc);
|
||||
I c = a / bc;
|
||||
I d = a / b;
|
||||
return equal(c, d);
|
||||
}
|
||||
|
||||
static bool test_div2(double ac, double bl, double bu) {
|
||||
I a(ac), b(bl, bu);
|
||||
I c = ac / b;
|
||||
I d = a / b;
|
||||
return equal(c, d);
|
||||
}
|
||||
|
||||
static bool test_square(double al, double au) {
|
||||
I a(al, au);
|
||||
I b = square(a);
|
||||
I c = a * a;
|
||||
return b.upper() == c.upper() &&
|
||||
(b.lower() == c.lower() || (c.lower() <= 0 && b.lower() == 0));
|
||||
}
|
||||
|
||||
static bool test_sqrt(double al, double au) {
|
||||
I a(al, au);
|
||||
I b = square(sqrt(a));
|
||||
return subset(abs(a), b);
|
||||
}
|
||||
|
||||
int test_main(int, char*[]) {
|
||||
BOOST_CHECK(test_mul(2, 3, 5, 7));
|
||||
BOOST_CHECK(test_mul(2, 3, -5, 7));
|
||||
BOOST_CHECK(test_mul(2, 3, -7, -5));
|
||||
BOOST_CHECK(test_mul(-2, 3, 5, 7));
|
||||
BOOST_CHECK(test_mul(-2, 3, -5, 7));
|
||||
BOOST_CHECK(test_mul(-2, 3, -7, -5));
|
||||
BOOST_CHECK(test_mul(-3, -2, 5, 7));
|
||||
BOOST_CHECK(test_mul(-3, -2, -5, 7));
|
||||
BOOST_CHECK(test_mul(-3, -2, -7, -5));
|
||||
|
||||
BOOST_CHECK(test_mul1(3, 5, 7));
|
||||
BOOST_CHECK(test_mul1(3, -5, 7));
|
||||
BOOST_CHECK(test_mul1(3, -7, -5));
|
||||
BOOST_CHECK(test_mul1(-3, 5, 7));
|
||||
BOOST_CHECK(test_mul1(-3, -5, 7));
|
||||
BOOST_CHECK(test_mul1(-3, -7, -5));
|
||||
|
||||
BOOST_CHECK(test_div(30, 42, 2, 3));
|
||||
BOOST_CHECK(test_div(30, 42, -3, -2));
|
||||
BOOST_CHECK(test_div(-30, 42, 2, 3));
|
||||
BOOST_CHECK(test_div(-30, 42, -3, -2));
|
||||
BOOST_CHECK(test_div(-42, -30, 2, 3));
|
||||
BOOST_CHECK(test_div(-42, -30, -3, -2));
|
||||
|
||||
BOOST_CHECK(test_div1(30, 42, 3));
|
||||
BOOST_CHECK(test_div1(30, 42, -3));
|
||||
BOOST_CHECK(test_div1(-30, 42, 3));
|
||||
BOOST_CHECK(test_div1(-30, 42, -3));
|
||||
BOOST_CHECK(test_div1(-42, -30, 3));
|
||||
BOOST_CHECK(test_div1(-42, -30, -3));
|
||||
|
||||
BOOST_CHECK(test_div2(30, 2, 3));
|
||||
BOOST_CHECK(test_div2(30, -3, -2));
|
||||
BOOST_CHECK(test_div2(-30, 2, 3));
|
||||
BOOST_CHECK(test_div2(-30, -3, -2));
|
||||
|
||||
BOOST_CHECK(test_square(2, 3));
|
||||
BOOST_CHECK(test_square(-2, 3));
|
||||
BOOST_CHECK(test_square(-3, 2));
|
||||
|
||||
BOOST_CHECK(test_sqrt(2, 3));
|
||||
BOOST_CHECK(test_sqrt(5, 7));
|
||||
BOOST_CHECK(test_sqrt(-1, 2));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_warnings();
|
||||
# endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/* Boost test/overflow.cpp
|
||||
* test if extended precision exponent does not disturb interval computation
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
template<class I>
|
||||
void test_one(typename I::base_type x, typename I::base_type f) {
|
||||
I y = x;
|
||||
typename I::base_type g = 1 / f;
|
||||
const int nb = 10000;
|
||||
for(int i = 0; i < nb; i++) y *= f;
|
||||
for(int i = 0; i < nb; i++) y *= g;
|
||||
BOOST_CHECK(in(x, y));
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_unused_variable_warning(nb);
|
||||
# endif
|
||||
}
|
||||
|
||||
template<class I>
|
||||
void test() {
|
||||
test_one<I>(1., 25.);
|
||||
test_one<I>(1., 0.04);
|
||||
test_one<I>(-1., 25.);
|
||||
test_one<I>(-1., 0.04);
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
test<boost::numeric::interval<float> >();
|
||||
test<boost::numeric::interval<double> >();
|
||||
//test<boost::numeric::interval<long double> >();
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_warnings();
|
||||
# endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Boost test/pi.cpp
|
||||
* test if the pi constant is correctly defined
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond, Sylvain Pion
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
|
||||
typedef boost::numeric::interval<int> I_i;
|
||||
typedef boost::numeric::interval<float> I_f;
|
||||
typedef boost::numeric::interval<double> I_d;
|
||||
typedef boost::numeric::interval<long double> I_ld;
|
||||
|
||||
using boost::numeric::interval_lib::pi;
|
||||
using boost::numeric::interval_lib::pi_half;
|
||||
using boost::numeric::interval_lib::pi_twice;
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
I_i pi_i = pi<I_i>();
|
||||
I_f pi_f = pi<I_f>();
|
||||
I_d pi_d = pi<I_d>();
|
||||
I_ld pi_ld = pi<I_ld>();
|
||||
|
||||
BOOST_CHECK(in((int) PI, pi_i));
|
||||
BOOST_CHECK(in((float) PI, pi_f));
|
||||
BOOST_CHECK(in((double)PI, pi_d));
|
||||
BOOST_CHECK(subset(pi_i, widen(I_i((int) PI), 1)));
|
||||
BOOST_CHECK(subset(pi_f, widen(I_f((float) PI), (std::numeric_limits<float> ::min)())));
|
||||
BOOST_CHECK(subset(pi_d, widen(I_d((double)PI), (std::numeric_limits<double>::min)())));
|
||||
|
||||
// We can't test the following equalities for interval<int>.
|
||||
I_f pi_f_half = pi_half<I_f>();
|
||||
I_f pi_f_twice = pi_twice<I_f>();
|
||||
|
||||
I_d pi_d_half = pi_half<I_d>();
|
||||
I_d pi_d_twice = pi_twice<I_d>();
|
||||
|
||||
I_ld pi_ld_half = pi_half<I_ld>();
|
||||
I_ld pi_ld_twice = pi_twice<I_ld>();
|
||||
|
||||
BOOST_CHECK(equal(2.0f * pi_f_half, pi_f));
|
||||
BOOST_CHECK(equal(2.0 * pi_d_half, pi_d));
|
||||
BOOST_CHECK(equal(2.0l * pi_ld_half, pi_ld));
|
||||
|
||||
BOOST_CHECK(equal(2.0f * pi_f, pi_f_twice));
|
||||
BOOST_CHECK(equal(2.0 * pi_d, pi_d_twice));
|
||||
BOOST_CHECK(equal(2.0l * pi_ld, pi_ld_twice));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Boost test/pow.cpp
|
||||
* test the pow function
|
||||
*
|
||||
* Copyright 2002-2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
bool test_pow(double al, double au, double bl, double bu, int p) {
|
||||
typedef boost::numeric::interval<double> I;
|
||||
I b = pow(I(al, au), p);
|
||||
return b.lower() == bl && b.upper() == bu;
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
BOOST_CHECK(test_pow(2, 3, 8, 27, 3));
|
||||
BOOST_CHECK(test_pow(2, 3, 16, 81, 4));
|
||||
BOOST_CHECK(test_pow(-3, 2, -27, 8, 3));
|
||||
BOOST_CHECK(test_pow(-3, 2, 0, 81, 4));
|
||||
BOOST_CHECK(test_pow(-3, -2, -27, -8, 3));
|
||||
BOOST_CHECK(test_pow(-3, -2, 16, 81, 4));
|
||||
|
||||
BOOST_CHECK(test_pow(2, 4, 1./64, 1./8, -3));
|
||||
BOOST_CHECK(test_pow(2, 4, 1./256, 1./16, -4));
|
||||
BOOST_CHECK(test_pow(-4, -2, -1./8, -1./64, -3));
|
||||
BOOST_CHECK(test_pow(-4, -2, 1./256, 1./16, -4));
|
||||
|
||||
BOOST_CHECK(test_pow(2, 3, 1, 1, 0));
|
||||
BOOST_CHECK(test_pow(-3, 2, 1, 1, 0));
|
||||
BOOST_CHECK(test_pow(-3, -2, 1, 1, 0));
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_warnings();
|
||||
# endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/* Boost test/test_float.cpp
|
||||
* test arithmetic operations on a range of intervals
|
||||
*
|
||||
* Copyright 2003 Guillaume Melquiond
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or
|
||||
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <boost/numeric/interval.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include "bugs.hpp"
|
||||
|
||||
/* All the following tests should be BOOST_CHECK; however, if a test fails,
|
||||
the probability is high that hundreds of other tests will fail, so it is
|
||||
replaced by BOOST_REQUIRE to avoid flooding the logs. */
|
||||
|
||||
template<class T, class F>
|
||||
void test_unary() {
|
||||
typedef typename F::I I;
|
||||
for(I a(-10., -9.91); a.lower() <= 10.; a += 0.3) {
|
||||
if (!F::validate(a)) continue;
|
||||
I rI = F::f_I(a);
|
||||
T rT1 = F::f_T(a.lower()), rT2 = F::f_T(a.upper()),
|
||||
rT3 = F::f_T(median(a));
|
||||
BOOST_REQUIRE(in(rT1, rI));
|
||||
BOOST_REQUIRE(in(rT2, rI));
|
||||
BOOST_REQUIRE(in(rT3, rI));
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, class F>
|
||||
void test_binary() {
|
||||
typedef typename F::I I;
|
||||
for(I a(-10., -9.91); a.lower() <= 10.; a += 0.3) {
|
||||
for(I b(-10., -9.91); b.lower() <= 10.; b += 0.3) {
|
||||
if (!F::validate(a, b)) continue;
|
||||
T al = a.lower(), au = a.upper(), bl = b.lower(), bu = b.upper();
|
||||
I rII = F::f_II(a, b);
|
||||
I rIT1 = F::f_IT(a, bl), rIT2 = F::f_IT(a, bu);
|
||||
I rTI1 = F::f_TI(al, b), rTI2 = F::f_TI(au, b);
|
||||
I rTT1 = F::f_TT(al, bl), rTT2 = F::f_TT(al, bu);
|
||||
I rTT3 = F::f_TT(au, bl), rTT4 = F::f_TT(au, bu);
|
||||
BOOST_REQUIRE(subset(rTT1, rIT1));
|
||||
BOOST_REQUIRE(subset(rTT3, rIT1));
|
||||
BOOST_REQUIRE(subset(rTT2, rIT2));
|
||||
BOOST_REQUIRE(subset(rTT4, rIT2));
|
||||
BOOST_REQUIRE(subset(rTT1, rTI1));
|
||||
BOOST_REQUIRE(subset(rTT2, rTI1));
|
||||
BOOST_REQUIRE(subset(rTT3, rTI2));
|
||||
BOOST_REQUIRE(subset(rTT4, rTI2));
|
||||
BOOST_REQUIRE(subset(rIT1, rII));
|
||||
BOOST_REQUIRE(subset(rIT2, rII));
|
||||
BOOST_REQUIRE(subset(rTI1, rII));
|
||||
BOOST_REQUIRE(subset(rTI2, rII));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define new_unary_bunch(name, op, val) \
|
||||
template<class T> \
|
||||
struct name { \
|
||||
typedef boost::numeric::interval<T> I; \
|
||||
static I f_I(const I& a) { return op(a); } \
|
||||
static T f_T(const T& a) { return op(a); } \
|
||||
static bool validate(const I& a) { return val; } \
|
||||
}
|
||||
|
||||
//#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::abs;
|
||||
using std::sqrt;
|
||||
//#endif
|
||||
|
||||
new_unary_bunch(bunch_pos, +, true);
|
||||
new_unary_bunch(bunch_neg, -, true);
|
||||
new_unary_bunch(bunch_sqrt, sqrt, a.lower() >= 0.);
|
||||
new_unary_bunch(bunch_abs, abs, true);
|
||||
|
||||
template<class T>
|
||||
void test_all_unaries() {
|
||||
BOOST_TEST_CHECKPOINT("pos"); test_unary<T, bunch_pos<T> >();
|
||||
BOOST_TEST_CHECKPOINT("neg"); test_unary<T, bunch_neg<T> >();
|
||||
BOOST_TEST_CHECKPOINT("sqrt"); test_unary<T, bunch_sqrt<T> >();
|
||||
BOOST_TEST_CHECKPOINT("abs"); test_unary<T, bunch_abs<T> >();
|
||||
}
|
||||
|
||||
#define new_binary_bunch(name, op, val) \
|
||||
template<class T> \
|
||||
struct bunch_##name { \
|
||||
typedef boost::numeric::interval<T> I; \
|
||||
static I f_II(const I& a, const I& b) { return a op b; } \
|
||||
static I f_IT(const I& a, const T& b) { return a op b; } \
|
||||
static I f_TI(const T& a, const I& b) { return a op b; } \
|
||||
static I f_TT(const T& a, const T& b) \
|
||||
{ return boost::numeric::interval_lib::name<I>(a,b); } \
|
||||
static bool validate(const I& a, const I& b) { return val; } \
|
||||
}
|
||||
|
||||
new_binary_bunch(add, +, true);
|
||||
new_binary_bunch(sub, -, true);
|
||||
new_binary_bunch(mul, *, true);
|
||||
new_binary_bunch(div, /, !zero_in(b));
|
||||
|
||||
template<class T>
|
||||
void test_all_binaries() {
|
||||
BOOST_TEST_CHECKPOINT("add"); test_binary<T, bunch_add<T> >();
|
||||
BOOST_TEST_CHECKPOINT("sub"); test_binary<T, bunch_sub<T> >();
|
||||
BOOST_TEST_CHECKPOINT("mul"); test_binary<T, bunch_mul<T> >();
|
||||
BOOST_TEST_CHECKPOINT("div"); test_binary<T, bunch_div<T> >();
|
||||
}
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
BOOST_TEST_CHECKPOINT("float tests");
|
||||
test_all_unaries<float> ();
|
||||
test_all_binaries<float> ();
|
||||
BOOST_TEST_CHECKPOINT("double tests");
|
||||
test_all_unaries<double>();
|
||||
test_all_binaries<double>();
|
||||
//BOOST_TEST_CHECKPOINT("long double tests");
|
||||
//test_all_unaries<long double>();
|
||||
//test_all_binaries<long double>();
|
||||
# ifdef __BORLANDC__
|
||||
::detail::ignore_warnings();
|
||||
# endif
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user