Squashed 'boost/' content from commit b4feb19f2

git-subtree-dir: boost
git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
Bill Somerville
2018-06-09 21:48:32 +01:00
commit 4ebe6417a5
12444 changed files with 2327021 additions and 0 deletions
+252
View File
@@ -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&amp;);
static T empty_lower();
static T empty_upper();
static bool is_empty(const T&amp;, const T&amp;);
};
</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&lt;T&gt;::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&lt;class T&gt;
struct checking_base;
template&lt;class T, class Checking = checking_base&lt;T&gt;, class Exception = exception_create_empty&lt;T&gt; &gt;
struct checking_no_empty;
template&lt;class T, class Checking = checking_base&lt;T&gt; &gt;
struct checking_no_nan;
template&lt;class T, class Checking = checking_base&lt;T&gt;, class Exception = exception_invalid_number&lt;T&gt; &gt;
struct checking_catch_nan;
template&lt;class T&gt; struct exception_create_empty { T operator()(); };
template&lt;class T&gt; 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&lt;T&gt;</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&lt;=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&lt;T&gt;</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&lt;T,
checking_no_empty&lt;T&gt; &gt;</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&lt;T, checking_no_empty&lt;T&gt; &gt;</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&lt;T&gt;</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&lt;T&gt;</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&lt;T&gt;</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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 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>
+204
View File
@@ -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>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>,
<code>&gt;=</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&lt;class T, class Policies1, class Policies2&gt;
return_type operator== (const interval&lt;T, Policies1&gt;&amp;, const interval&lt;T, Policies2&gt;&amp;);
template&lt;class T, class Policies&gt;
return_type operator== (const interval&lt;T, Policies&gt;&amp;, const T&amp;);
</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 &forall; <i>x</i> &isin; [<i>a</i>,<i>b</i>] &forall; <i>y</i>
&isin; [<i>c</i>,<i>d</i>] <code>(</code><i>x</i> <code>op</code>
y<code>)</code>, then <code>true</code></li>
<li>if &forall; <i>x</i> &isin; [<i>a</i>,<i>b</i>] &forall; <i>y</i>
&isin; [<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>&lt;boost/numeric/interval/compare/...&gt;</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>&lt;=</code> and <code>&lt;</code> are the subset
and proper subset relations; and <code>&gt;=</code> and <code>&gt;</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>&lt;boost/numeric/interval/compare/explicit.hpp&gt;</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&lt;class T, class Policies1, class Policies2&gt;
bool cerlt(const interval&lt;T, Policies1&gt;&amp; x, const interval&lt;T, Policies2&gt;&amp; y);
template&lt;class T, class Policies&gt;
bool cerlt(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template&lt;class T, class Policies&gt;
bool cerlt(const T&amp; x, const interval&lt;T, Policies&gt;&amp; 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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 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>
+211
View File
@@ -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 &lt;boost/numeric/interval.hpp&gt;
</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&lt;double&gt; 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 &gt;= 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 &gt; 0.) return 1;
if (y &lt; 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&lt;double&gt; I_aux;
I_aux::traits_type::rounding rnd;
typedef unprotect&lt;I_aux&gt;::type I;
I y = P[sz - 1];
for(int i = sz - 2; i &gt;= 0; i--)
y = y * x + P[i];
using namespace compare::certain;
if (y &gt; 0.) return 1;
if (y &lt; 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>&lt;</code>
<code>&gt;</code> <code>&lt;=</code> <code>&gt;=</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&lt;float&gt;</code> and
<code>interval&lt;double&gt;</code>.</p>
<p><b>fmod.cpp</b> defines a minimalistic version of
<code>interval&lt;int&gt;</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 &pi; (for <code>int</code>,
<code>float</code> and <code>double</code> base types) contains the number
&pi; (defined with 21 decimal digits) and if it is a subset of
[&pi;&plusmn;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&lt;double&gt;</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&ouml;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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 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>
+122
View File
@@ -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&lt;double&gt;</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&lt;T&gt;</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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;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>
+218
View File
@@ -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 &lt;boost/numeric/interval.hpp&gt;
</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>&lt;boost/numeric/interval.hpp&gt;</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>&lt;boost/numeric/interval/something.hpp&gt;</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&lt;float&gt;</code>, <code>interval&lt;double&gt;</code>
and <code>interval&lt;long double&gt;</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>&lt;&lt;</code> and
<code>&gt;&gt;</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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 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>
+13
View File
@@ -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>.&nbsp;<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>
+990
View File
@@ -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 &lt;<a href=
"../../../../boost/numeric/interval.hpp">boost/numeric/interval.hpp</a>&gt;
and principally a type which can be used as <code>interval&lt;T&gt;</code>.
In fact, this interval template is declared as
<code>interval&lt;T,Policies&gt;</code> where <code>Policies</code> is a
policy class that controls the various behaviours of the interval class;
<code>interval&lt;T&gt;</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&lt;float&gt;</code> and <code>interval&lt;double&gt;</code>
with basic arithmetic operators.</p>
<ul>
<li>x86-like hardware is supported by the library with GCC, Visual C++
&ge; 7.1, Intel compiler (&ge; 8 on Windows), CodeWarrior (&ge; 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> &le; <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: &forall; <i>x</i> &isin; [<i>a</i>,<i>b</i>], <i>f</i>(<i>x</i>)
&isin; <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 [-&infin;,+&infin;]).</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&lt;T&gt;</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&gt;y and z&gt;t, then
it should also hold that x+z &gt; 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>] &lt; [<i>c</i>,<i>d</i>] will be <i>true</i> if and
only if: &forall; <i>x</i> &isin; [<i>a</i>,<i>b</i>] &forall; <i>y</i>
&isin; [<i>c</i>,<i>d</i>], <i>x</i> &lt; <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>] &lt; [<i>c</i>,<i>d</i>] will be <i>true</i> if and
only if: &exist; <i>x</i> &isin; [<i>a</i>,<i>b</i>] &exist; <i>y</i>
&isin; [<i>c</i>,<i>d</i>], <i>x</i> &lt; <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&lt;T&gt;</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&lt;T&gt;</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>&lt;</code>, <code>&lt;=</code>,
<code>&gt;</code>, <code>&gt;=</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&lt;T&gt;</code>, all combinations of argument types
<code>T</code> and <code>interval&lt;T&gt;</code> which contain at least
one <code>interval&lt;T&gt;</code>, are considered in order to avoid a
conversion from the arguments of type <code>T</code> to a singleton of type
<code>interval&lt;T&gt;</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&lt;T, Policies&gt;</code> through the use of <code>Policies
:= boost::numeric::interval_lib::policies&lt;Rounding,Checking&gt;</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 &lt;class T&gt; 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&lt;class Rounding, class Checking&gt;
struct interval_policies;
/* template class interval; class definition can be found <a href=
"#interval">here</a> */
template&lt;class T, class Policies = typename interval_lib::default_policies&lt;T&gt;::type &gt; class interval;
/* arithmetic operators involving intervals */
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator+(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator-(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator+(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator+(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator+(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator-(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator-(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator-(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator*(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator*(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator*(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator/(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator/(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; operator/(const T&amp; r, const interval&lt;T, Policies&gt;&amp; x);
/* algebraic functions: sqrt, abs, square, pow, nth_root */
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; abs(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; sqrt(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; square(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; pow(const interval&lt;T, Policies&gt;&amp; x, int y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; nth_root(const interval&lt;T, Policies&gt;&amp; x, int y);
/* transcendental functions: exp, log */
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; exp(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; log(const interval&lt;T, Policies&gt;&amp; x);
/* fmod, for trigonometric function argument reduction (see below) */
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; fmod(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; fmod(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; fmod(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
/* trigonometric functions */
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; sin(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; cos(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; tan(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; asin(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; acos(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; atan(const interval&lt;T, Policies&gt;&amp; x);
/* hyperbolic trigonometric functions */
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; sinh(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; cosh(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; tanh(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; asinh(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; acosh(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; atanh(const interval&lt;T, Policies&gt;&amp; x);
/* min, max external functions (NOT std::min/max, see below) */
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; max(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; max(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; max(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; min(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; min(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; min(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
/* bounds-related interval functions */
template &lt;class T, class Policies&gt; T lower(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; T upper(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; T width(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; T median(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; T norm(const interval&lt;T, Policies&gt;&amp; x);
/* bounds-related interval functions */
template &lt;class T, class Policies&gt; bool empty(const interval&lt;T, Policies&gt;&amp; b);
template &lt;class T, class Policies&gt; bool singleton(const interval&lt;T, Policies&gt;&amp; x);
template &lt;class T, class Policies&gt; bool equal(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool in(const T&amp; r, const interval&lt;T, Policies&gt;&amp; b);
template &lt;class T, class Policies&gt; bool zero_in(const interval&lt;T, Policies&gt;&amp; b);
template &lt;class T, class Policies&gt; bool subset(const interval&lt;T, Policies&gt;&amp; a, const interval&lt;T, Policies&gt;&amp; b);
template &lt;class T, class Policies&gt; bool proper_subset(const interval&lt;T, Policies&gt;&amp; a, const interval&lt;T, Policies&gt;&amp; b);
template &lt;class T, class Policies&gt; bool overlap(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
/* set manipulation interval functions */
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; intersect(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; hull(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; hull(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; hull(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; interval&lt;T, Policies&gt; hull(const T&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; std::pair&lt;interval&lt;T, Policies&gt;, interval&lt;T, Policies&gt; &gt; bisect(const interval&lt;T, Policies&gt;&amp; x);
/* interval comparison operators */
template&lt;class T, class Policies&gt; bool operator&lt;(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator&lt;(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template&lt;class T, class Policies&gt; bool operator&lt;(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator&lt;=(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator&lt;=(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template&lt;class T, class Policies&gt; bool operator&lt;=(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator&gt;(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator&gt;(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template&lt;class T, class Policies&gt; bool operator&gt;(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator&gt;=(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator&gt;=(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template&lt;class T, class Policies&gt; bool operator&gt;=(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
</pre>
<pre>
template&lt;class T, class Policies&gt; bool operator==(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator==(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template&lt;class T, class Policies&gt; bool operator==(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator!=(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template&lt;class T, class Policies&gt; bool operator!=(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template&lt;class T, class Policies&gt; bool operator!=(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
namespace interval_lib {
template&lt;class T, class Policies&gt; interval&lt;T, Policies&gt; division_part1(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&amp; y, bool&amp; b);
template&lt;class T, class Policies&gt; interval&lt;T, Policies&gt; division_part2(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&amp; y, bool b = true);
template&lt;class T, class Policies&gt; interval&lt;T, Policies&gt; multiplicative_inverse(const interval&lt;T, Policies&gt;&amp; x);
template&lt;class I&gt; I add(const typename I::base_type&amp; x, const typename I::base_type&amp; y);
template&lt;class I&gt; I sub(const typename I::base_type&amp; x, const typename I::base_type&amp; y);
template&lt;class I&gt; I mul(const typename I::base_type&amp; x, const typename I::base_type&amp; y);
template&lt;class I&gt; I div(const typename I::base_type&amp; x, const typename I::base_type&amp; 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 &lt;class T, class Policies = typename interval_lib::default_policies&lt;T&gt;::type&gt;
class interval
{
public:
typedef T base_type;
typedef Policies traits_type;
interval();
interval(T const &amp;v);
template&lt;class T1&gt; interval(T1 const &amp;v);
interval(T const &amp;l, T const &amp;u);
template&lt;class T1, class T2&gt; interval(T1 const &amp;l, T2 const &amp;u);
interval(interval&lt;T, Policies&gt; const &amp;r);
template&lt;class Policies1&gt; interval(interval&lt;T, Policies1&gt; const &amp;r);
template&lt;class T1, class Policies1&gt; interval(interval&lt;T1, Policies1&gt; const &amp;r);
interval &amp;operator=(T const &amp;v);
template&lt;class T1&gt; interval &amp;operator=(T1 const &amp;v);
interval &amp;operator=(interval&lt;T, Policies&gt; const &amp;r);
template&lt;class Policies1&gt; interval &amp;operator=(interval&lt;T, Policies1&gt; const &amp;r);
template&lt;class T1, class Policies1&gt; interval &amp;operator=(interval&lt;T1, Policies1&gt; const &amp;r);
void assign(T const &amp;l, T const &amp;u);
T const &amp;lower() const;
T const &amp;upper() const;
static interval empty();
static interval whole();
static interval hull(T const &amp;x, T const &amp;y);
interval&amp; operator+= (T const &amp;r);
interval&amp; operator-= (T const &amp;r);
interval&amp; operator*= (T const &amp;r);
interval&amp; operator/= (T const &amp;r);
interval&amp; operator+= (interval const &amp;r);
interval&amp; operator-= (interval const &amp;r);
interval&amp; operator*= (interval const &amp;r);
interval&amp; operator/= (interval const &amp;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 &lt;= 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&lt;b?a:b</code>, <code>a&gt;b?a:b</code>,
<code>a&lt;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]&sup2; = [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 ]-&infin;,&infin;[ but the union
of ]-&infin;,-1] and [2,&infin;[. 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 &lt;= z.lower() &lt; 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&lt;I&gt;()</code>, <code>pi_half&lt;I&gt;()</code> and
<code>pi_twice&lt;I&gt;()</code>, and they return an object of interval
type <code>I</code>. Their respective values are &pi;, &pi;/2 and
2&pi;.</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&lt;T&gt;</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 &lt;class T&gt; struct rounded_math;
template &lt;&gt; struct rounded_math&lt;float&gt;;
template &lt;&gt; struct rounded_math&lt;double&gt;;
template &lt;&gt; struct rounded_math&lt;long double&gt;;
<span style=
"color: #FF0000">/* built-in rounding construction blocks */</span>
template &lt;class T&gt; struct rounding_control;
template &lt;class T, class Rounding = rounding_control&lt;T&gt; &gt; struct rounded_arith_exact;
template &lt;class T, class Rounding = rounding_control&lt;T&gt; &gt; struct rounded_arith_std;
template &lt;class T, class Rounding = rounding_control&lt;T&gt; &gt; struct rounded_arith_opp;
template &lt;class T, class Rounding&gt; struct rounded_transc_dummy;
template &lt;class T, class Rounding = rounded_arith_exact&lt;T&gt; &gt; struct rounded_transc_exact;
template &lt;class T, class Rounding = rounded_arith_std &lt;T&gt; &gt; struct rounded_transc_std;
template &lt;class T, class Rounding = rounded_arith_opp &lt;T&gt; &gt; struct rounded_transc_opp;
template &lt;class Rounding&gt; struct save_state;
template &lt;class Rounding&gt; struct save_state_nothing;
<span style="color: #FF0000">/* built-in checking policies */</span>
template &lt;class T&gt; struct checking_base;
template &lt;class T, class Checking = checking_base&lt;T&gt;, class Exception = exception_create_empty&gt; struct checking_no_empty;
template &lt;class T, class Checking = checking_base&lt;T&gt; &gt; struct checking_no_nan;
template &lt;class T, class Checking = checking_base&lt;T&gt;, class Exception = exception_invalid_number&gt; struct checking_catch_nan;
template &lt;class T&gt; struct checking_strict;
<span style=
"color: #FF0000">/* some metaprogramming to manipulate interval policies */</span>
template &lt;class Rounding, class Checking&gt; struct policies;
template &lt;class OldInterval, class NewRounding&gt; struct change_rounding;
template &lt;class OldInterval, class NewChecking&gt; struct change_checking;
template &lt;class OldInterval&gt; struct unprotect;
<span style=
"color: #FF0000">/* constants, need to be explicitly templated */</span>
template&lt;class I&gt; I pi();
template&lt;class I&gt; I pi_half();
template&lt;class I&gt; 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 &lt;class T, class Policies&gt; bool cerlt(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cerlt(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool cerlt(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cerle(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cerle(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool cerle(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cergt(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cergt(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool cergt(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cerge(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cerge(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool cerge(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cereq(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cereq(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool cereq(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cerne(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool cerne(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool cerne(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool poslt(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool poslt(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool poslt(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool posle(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool posle(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool posle(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool posgt(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool posgt(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool posgt(const T&amp; x, const interval&lt;T, Policies&gt; &amp; y);
template &lt;class T, class Policies&gt; bool posge(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool posge(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool posge(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool poseq(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool poseq(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool poseq(const T&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool posne(const interval&lt;T, Policies&gt;&amp; x, const interval&lt;T, Policies&gt;&amp; y);
template &lt;class T, class Policies&gt; bool posne(const interval&lt;T, Policies&gt;&amp; x, const T&amp; y);
template &lt;class T, class Policies&gt; bool posne(const T&amp; x, const interval&lt;T, Policies&gt;&amp; 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] &lt; [c,d] to be !([a,b] &gt;= [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>&lt;</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 &lt;= b</code> and
<code>&amp;b == &amp;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&eacute; Br&ouml;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&eacute; have
provided some useful comments in order for this library to be written.
Herv&eacute; 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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 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>
+176
View File
@@ -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>&lt; &lt;= =&gt; &gt; == !=</code>.
It must be a total order (reflexivity, antisymmetry, transitivity, and each
pair of numbers is ordered). So <code>complex&lt;T&gt;</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&lt; interval&lt;T&gt;
&gt;</code> in place of <code>interval&lt; complex&lt;T&gt; &gt;</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&lt;T&gt;(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&lt;class T&gt; inline bool is_zero(T const &amp;v) { return v == static_cast&lt;T&gt;(0); }
template&lt;class T&gt; inline bool is_neg (T const &amp;v) { return v &lt; static_cast&lt;T&gt;(0); }
template&lt;class T&gt; inline bool is_pos (T const &amp;v) { return v &gt; static_cast&lt;T&gt;(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&lt;T&gt;</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 &le; <i>x</i> &rArr; -<i>x</i> &le; 0</li>
<li><i>x</i> &le; <i>y</i> &rArr; -<i>y</i> &le; -<i>x</i></li>
<li><i>x</i> &le; <i>y</i> &rArr; <i>x</i>+<i>z</i> &le;
<i>y</i>+<i>z</i></li>
<li><i>x</i> &le; <i>y</i> and <i>z</i> &ge; 0 &rArr;
<i>x</i>&times;<i>z</i> &le; <i>y</i>&times;<i>z</i></li>
<li>0 &lt; <i>x</i> &le; <i>y</i> &rArr; 0 &lt; 1/<i>y</i> &le;
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&pi;-periodic;</li>
<li><code>cos</code>(2&pi;-<i>x</i>) is equal to
<code>cos</code>(<i>x</i>);</li>
<li><code>cos</code> is a decreasing function on [0,2&pi;].</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) &lt;= f(x,y) &lt;= 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 &pi; constant (and also &pi;/2 and 2&pi;).
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 &pi; 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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 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>
+80
View File
@@ -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&lt;class Rounding, class Checking&gt;
struct policies {
typedef Rounding rounding;
typedef Checking checking;
};
template&lt;class OldInterval, class NewRounding&gt;
struct change_rounding {
typedef ... type;
};
template&lt;class OldInterval, class NewChecking&gt;
struct change_checking {
typedef ... type;
};
template&lt;class OldInterval&gt;
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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;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>
+632
View File
@@ -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&lt;T&gt;</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&lt;T&gt;</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&lt;T&gt;</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); // [-&infin;;+&infin;][-&infin;;+&infin;]
T add_up (T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T sub_down(T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T sub_up (T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T mul_down(T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T mul_up (T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T div_down(T, T); // [-&infin;;+&infin;]([-&infin;;+&infin;]-{0})
T div_up (T, T); // [-&infin;;+&infin;]([-&infin;;+&infin;]-{0})
T sqrt_down(T); // ]0;+&infin;]
T sqrt_up (T); // ]0;+&infin;]
T exp_down(T); // [-&infin;;+&infin;]
T exp_up (T); // [-&infin;;+&infin;]
T log_down(T); // ]0;+&infin;]
T log_up (T); // ]0;+&infin;]
T cos_down(T); // [0;2&pi;]
T cos_up (T); // [0;2&pi;]
T tan_down(T); // ]-&pi;/2;&pi;/2[
T tan_up (T); // ]-&pi;/2;&pi;/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); // [-&infin;;+&infin;]
T atan_up (T); // [-&infin;;+&infin;]
T sinh_down(T); // [-&infin;;+&infin;]
T sinh_up (T); // [-&infin;;+&infin;]
T cosh_down(T); // [-&infin;;+&infin;]
T cosh_up (T); // [-&infin;;+&infin;]
T tanh_down(T); // [-&infin;;+&infin;]
T tanh_up (T); // [-&infin;;+&infin;]
T asinh_down(T); // [-&infin;;+&infin;]
T asinh_up (T); // [-&infin;;+&infin;]
T acosh_down(T); // [1;+&infin;]
T acosh_up (T); // [1;+&infin;]
T atanh_down(T); // [-1;1]
T atanh_up (T); // [-1;1]
T median(T, T); // [-&infin;;+&infin;][-&infin;;+&infin;]
T int_down(T); // [-&infin;;+&infin;]
T int_up (T); // [-&infin;;+&infin;]
// 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 &lt;class T&gt;
struct rounding_control
{
typedef ... rounding_mode;
void set_rounding_mode(rounding_mode);
void get_rounding_mode(rounding_mode&amp;);
void downward ();
void upward ();
void to_nearest();
T to_int(T);
T force_rounding(T);
};
template &lt;class T, class Rounding&gt;
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 &lt;class T, class Rounding&gt;
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 &lt;class Rounding&gt;
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 &lt;class T&gt; struct rounding_control;
<span style="color: #FF0000">/* arithmetic functions rounding */</span>
template &lt;class T, class Rounding = rounding_control&lt;T&gt; &gt; struct rounded_arith_exact;
template &lt;class T, class Rounding = rounding_control&lt;T&gt; &gt; struct rounded_arith_std;
template &lt;class T, class Rounding = rounding_control&lt;T&gt; &gt; struct rounded_arith_opp;
<span style="color: #FF0000">/* transcendental functions rounding */</span>
template &lt;class T, class Rounding&gt; struct rounded_transc_dummy;
template &lt;class T, class Rounding = rounded_arith_exact&lt;T&gt; &gt; struct rounded_transc_exact;
template &lt;class T, class Rounding = rounded_arith_std&lt;T&gt; &gt; struct rounded_transc_std;
template &lt;class T, class Rounding = rounded_arith_opp&lt;T&gt; &gt; struct rounded_transc_opp;
<span style="color: #FF0000">/* rounding-state-saving classes */</span>
template &lt;class Rounding&gt; struct save_state;
template &lt;class Rounding&gt; struct save_state_nothing;
<span style="color: #FF0000">/* default policy for type T */</span>
template &lt;class T&gt; struct rounded_math;
template &lt;&gt; struct rounded_math&lt;float&gt;;
template &lt;&gt; struct rounded_math&lt;double&gt;;
<span style=
"color: #FF0000">/* some metaprogramming to convert a protected to unprotected rounding */</span>
template &lt;class I&gt; 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&lt;I&gt;::type</code> where the
rounding policy has been unprotected. Some information about the types:
<code>interval&lt;T, interval_lib::policies&lt;Rounding, _&gt;
&gt;::traits_type::rounding</code> <b>is</b> the same type as
<code>Rounding</code>, and <code>unprotect&lt;interval&lt;T,
interval_lib::policies&lt;Rounding, _&gt; &gt; &gt;::type</code> <b>is</b>
the same type as <code>interval&lt;T,
interval_lib::policies&lt;Rounding::unprotected, _&gt; &gt;</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 -&infin;.</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&lt;T&gt;</code>) is simply
defined as:</p>
<pre>
template &lt;class T&gt; struct rounded_math&lt;T&gt; : save_state_nothing&lt;rounded_arith_exact&lt;T&gt; &gt; {};
</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 &lt;&gt; struct rounded_math&lt;float&gt; : save_state&lt;rounded_arith_opp&lt;float&gt; &gt; {};
template &lt;&gt; struct rounded_math&lt;double&gt; : save_state&lt;rounded_arith_opp&lt;double&gt; &gt; {};
template &lt;&gt; struct rounded_math&lt;long double&gt; : save_state&lt;rounded_arith_opp&lt;long double&gt; &gt; {};
</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&lt;I&gt;::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&lt;class I&gt;
I horner(const I&amp; 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&lt;I&gt;::type R;
const R&amp; a = x;
R y = p[n - 1];
for(int i = n - 2; i &gt;= 0; i--) {
y = y * a + (const R&amp;)(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&amp;</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>) &lt; -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&lt;T&gt;</code>;</li>
<li>for fast wide intervals without any rounding nor precision, use
<code>save_state_nothing&lt;rounded_transc_exact&lt;T&gt;
&gt;</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&lt;rounded_transc_dummy&lt;T,
rounded_arith_exact&lt;T&gt; &gt; &gt;</code> or directly
<code>save_state_nothing&lt;rounded_arith_exact&lt;T&gt;
&gt;</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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;nnimann, Polytechnic University<br>
Copyright &copy; 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>
+67
View File
@@ -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&lt;double&gt;</code> using SSE2 instructions? Tricky.</li>
<li>Write a traits specialization for <code>interval&lt;MPFR&gt;</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&lt;double&gt;</code> to
<code>interval&lt;float&gt;</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 &copy; 2002 Guillaume Melquiond, Sylvain Pion, Herv&eacute;
Br&ouml;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>