mirror of
https://github.com/boostorg/interval.git
synced 2026-01-25 06:12:25 +00:00
869 lines
50 KiB
HTML
869 lines
50 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||
"http://www.w3.org/TR/html4/loose.dtd">
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||
<title>Boost Interval Arithmetic Library</title>
|
||
</head>
|
||
|
||
<body lang="en">
|
||
<h1><img src="../../../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
|
||
align="middle">
|
||
Interval Arithmetic Library</h1>
|
||
|
||
<center>
|
||
|
||
<table cols="2" width="80%">
|
||
<tbody>
|
||
<tr align=TOP>
|
||
<td align=TOP><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 align=TOP><b>Other pages associated with this page:</b><br>
|
||
<a href="rounding.htm">Rounding policies</a><br>
|
||
<a href="checking.htm">Checking policies</a><br>
|
||
<a href="policies.htm">Policies manipulation</a><br>
|
||
<a href="comparisons.htm">Comparisons</a><br>
|
||
<a href="numbers.htm">Base number type requirements</a><br>
|
||
<a href="guide.htm">Choosing your own interval type</a><br>
|
||
<a href="examples.htm">Test and example programs</a><br>
|
||
<a href="includes.htm">Headers inclusion</a><br>
|
||
<a href="todo.htm">Some items on the todo list</a></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</center>
|
||
|
||
<h2 id="intro">Introduction and Overview</h2>
|
||
|
||
<p>As implied by its name, this library is intended to help manipulating
|
||
mathematical intervals. It consists of a single header <<a
|
||
href="../../../../boost/numeric/interval.hpp">boost/numeric/interval.hpp</a>>
|
||
and principally a type which can be used as <code>interval<T></code>.
|
||
In fact, this interval template is declared as
|
||
<code>interval<T,Policies></code> where <code>Policies</code> is a
|
||
policy class that controls the various behaviours of the interval class;
|
||
<code>interval<T></code> just happens to pick the default policies for
|
||
the type <code>T</code>.</p>
|
||
|
||
<h3>Interval Arithmetic</h3>
|
||
|
||
<p>An interval is a pair of numbers which represents all the numbers between
|
||
these two. (Intervals are considered close so the bounds are included.) The
|
||
purpose of this library is to extend the usual arithmetic functions to
|
||
intervals. These intervals will be written [<i>a</i>,<i>b</i>] to represent
|
||
all the numbers between <i>a</i> and <i>b</i> (included). <i>a</i> and
|
||
<i>b</i> can be infinite (but they can not be the same infinite) and <i>a</i>
|
||
≤ <i>b</i>.</p>
|
||
|
||
<p>The fundamental property of interval arithmetic is the
|
||
<em><strong>inclusion property</strong></em>:</p>
|
||
<dl>
|
||
<dd>``if <i>f</i> is a function on a set of numbers, <i>f</i> can be
|
||
extended to a new function defined on intervals. This new function
|
||
<i>f</i> takes one interval argument and returns an interval result
|
||
such as: ∀ <i>x</i> ∈ [<i>a</i>,<i>b</i>],
|
||
<i>f</i>(<i>x</i>) ∈ <i>f</i>([<i>a</i>,<i>b</i>]).''</dd>
|
||
</dl>
|
||
|
||
<p>Such a property is not limited to functions with only one argument.
|
||
Whenever possible, the interval result should be the smallest one able to
|
||
satisfy the property (it is not really useful if the new functions always
|
||
answer [-∞,+∞]).</p>
|
||
|
||
<p>There are at least two reasons a user would like to use this library. The
|
||
obvious one is when the user has to compute with intervals. One example is
|
||
when input data have some builtin imprecision: instead of a number, an input
|
||
variable can be passed as an interval. Another example application is to
|
||
solve equations, by bisecting an interval until the interval width is small
|
||
enough. A third example application is in computer graphics, where
|
||
computations with boxes, segments or rays can be reduced to computations with
|
||
points via intervals.</p>
|
||
|
||
<p>Another common reason to use interval arithmetic is when the computer
|
||
doesn't produce exact results: by using intervals, it is possible to quantify
|
||
the propagation of rounding errors. This approach is used often in numerical
|
||
computation. For example, let's assume the computer stores numbers with ten
|
||
decimal significant digits. To the question 1 + 1E-100 - 1, the computer will
|
||
answer 0 although the correct answer would be 1E-100. With the help of
|
||
interval arithmetic, the computer will answer [0,1E-9]. This is quite a huge
|
||
interval for such a little result, but the precision is now known, without
|
||
having to compute error propagation.</p>
|
||
|
||
<h3>Numbers, rounding, and exceptional behavior</h3>
|
||
|
||
<p>The <em><strong>base number type</strong></em> is the type that holds the
|
||
bounds of the interval. In order to successfully use interval arithmetic, the
|
||
base number type must present some <a
|
||
href="rounding.htm">characteristics</a>. Firstly, due to the definition of an
|
||
interval, the base numbers have to be totally ordered so, for instance,
|
||
<code>complex<T></code> is not usable as base number type for
|
||
intervals. The mathematical functions for the base number type should also
|
||
be compatible with the total order (for instance if x>y and z>t, then
|
||
it should also hold that x+z > y+t), so modulo types are not usable
|
||
either.</p>
|
||
|
||
<p>Secondly, the computations must be exact or provide some rounding methods
|
||
(for instance, toward minus or plus infinity) if we want to guarantee the
|
||
inclusion property. Note that we also may explicitely specify no rounding,
|
||
for instance if the base number type is exact, i.e. the result of a
|
||
mathematic 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
|
||
longuer 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+b down and c+d up will suffice. Other operators and
|
||
functions are similarly defined (see their definitions below).</p>
|
||
|
||
<h3>Comparisons</h3>
|
||
|
||
<p>It is also possible to define some comparison operators. Given two
|
||
intervals, the result is a tri-state boolean type
|
||
{<i>false</i>,<i>true,indeterminate</i>}. The answers <i>false</i> and
|
||
<i>true</i> are easy to manipulate since they can directly be mapped on the
|
||
boolean <i>true</i> and <i>false</i>. But it is not the case for the answer
|
||
<em>indeterminate</em> since comparison operators are supposed to be boolean
|
||
functions. So, what to do in order to obtain boolean answers?</p>
|
||
|
||
<p>One solution consists of deciding to adopt an exceptional behavior, such
|
||
as a failed assertion or raising an exception. In this case, the exceptional
|
||
behavior will be triggered when the result is indeterminate.</p>
|
||
|
||
<p>Another solution is to map <em>indeterminate</em> always to <i>false,</i>
|
||
or always to <i>true</i>. If <i>false</i> is chosen, the comparison will be
|
||
called "<i>certain</i>;" indeed, the result of [<i>a</i>,<i>b</i>] <
|
||
[<i>c</i>,<i>d</i>] will be <i>true</i> if and only if: ∀ <i>x</i>
|
||
∈ [<i>a</i>,<i>b</i>] ∀ <i>y</i> ∈ [<i>c</i>,<i>d</i>],
|
||
<i>x</i> < <i>y</i>. If <i>true</i> is chosen, the comparison will be
|
||
called "<i>possible</i>;" indeed, the result of [<i>a</i>,<i>b</i>] <
|
||
[<i>c</i>,<i>d</i>] will be <i>true</i> if and only if: ∃ <i>x</i>
|
||
∈ [<i>a</i>,<i>b</i>] ∃ <i>y</i> ∈ [<i>c</i>,<i>d</i>],
|
||
<i>x</i> < <i>y</i>.</p>
|
||
|
||
<p>Since any of these solution has a clearly defined semantics, it is not
|
||
clear that we should enforce either of them. For this reason, the default
|
||
behavior consists to mimic the real comparisons by throwing an exception in
|
||
the indeterminate case. Other behaviors can be selected bu using specific
|
||
comparison namespace. There is also a bunch of explicitely named comparison
|
||
functions. See <a href="comparisons.htm">comparisons</a> pages for further
|
||
details.</p>
|
||
|
||
<h3>Overview of the library, and usage</h3>
|
||
|
||
<p>This library provides two quite distinct levels of usage. One is to use
|
||
the basic class template <code>interval<T></code> without specifying
|
||
the policy. This only requires to know and understand the concepts developed
|
||
above and the content of the namespace boost. In addition to the class
|
||
<code>interval<T></code>, this level of usage provides arithmetic
|
||
operators (<code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>),
|
||
algebraic and piecewise-algebraic functions (<code>abs</code>,
|
||
<code>square</code>, <code>sqrt</code>, <code>pow</code>), transcendental and
|
||
trigonometric functions (<code>exp</code>, <code>log</code>,
|
||
<code>sin</code>, <code>cos</code>, <code>tan</code>, <code>asin</code>,
|
||
<code>acos</code>, <code>atan</code>, <code>sinh</code>, <code>cosh</code>,
|
||
<code>tanh</code>, <code>asinh</code>, <code>acosh</code>,
|
||
<code>atanh</code>), and the standard comparison operators
|
||
(<code><</code>, <code><=</code>, <code>></code>,
|
||
<code>>=</code>, <code>==</code>, <code>!=</code>), as well as several
|
||
interval-specific functions (<code>min</code>, <code>max</code>, which have a
|
||
different meaning than <code>std::min</code> and <code>std::max</code>;
|
||
<code>lower</code>, <code>upper</code>, <code>width</code>,
|
||
<code>median</code>, <code>empty</code>, <code>singleton, equal</code>,
|
||
<code>in</code>, <code>in_zero</code>, <code>subset</code>,
|
||
<code>proper_subset</code>, <code>overlap</code>, <code>intersection</code>,
|
||
<code>hull</code>, <code>bisect</code>).</p>
|
||
|
||
<p>For some functions which take several parameters of type
|
||
<code>interval<T></code>, all combinations of argument types
|
||
<code>T</code> and <code>interval<T></code> which contain at least one
|
||
<code>interval<T></code>, are considered in order to avoid a conversion
|
||
from the arguments of type <code>T</code> to a singleton of type
|
||
<code>interval<T></code>. This is done for efficiency reasons (the fact
|
||
that an argument is a singleton sometimes renders some tests unnecessary).</p>
|
||
|
||
<p>A somewhat more advanced usage of this library is to hand-pick the
|
||
policies <code>Rounding</code> and <code>Checking</code> and pass them to
|
||
<code>interval<T, Policies></code> through the use of <code>Policies :=
|
||
boost::interval_lib::policies<Rounding,Checking></code>. Appropriate
|
||
policies can be fabricated by using the various classes provided in the
|
||
namespace <code>boost::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"></a>Synopsis</h2>
|
||
<pre>namespace boost {
|
||
namespace numeric {
|
||
|
||
namespace interval_lib {
|
||
|
||
/* this declaration is necessary for the declaration of interval */
|
||
template <class T> struct default_policies;
|
||
|
||
/* ... ; the full synopsis of namespace interval_lib can be found <a href="#interval_lib">here</a> */
|
||
|
||
} // namespace interval_lib
|
||
|
||
|
||
/* template interval_policies; class definition can be found <a href="#interval_policies">here</a> */
|
||
template<class Rounding, class Checking>
|
||
struct interval_policies;
|
||
|
||
/* template class interval; class definition can be found <a href="#interval">here</a> */
|
||
template<class T, class Policies = typename interval_lib::default_policies<T> >
|
||
class interval;
|
||
|
||
/* arithmetic operators involving intervals */
|
||
template <class T, class Traits> interval<T, Traits> operator+(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> operator-(const interval<T, Traits>& x);
|
||
|
||
template <class T, class Traits> interval<T, Traits> operator+(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> operator+(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> interval<T, Traits> operator+(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> interval<T, Traits> operator-(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> operator-(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> interval<T, Traits> operator-(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> interval<T, Traits> operator*(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> operator*(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> interval<T, Traits> operator*(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> interval<T, Traits> operator/(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> operator/(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> interval<T, Traits> operator/(const T& r, const interval<T, Traits>& x);
|
||
|
||
/* algebraic functions: sqrt, abs, square, pow */
|
||
template <class T, class Traits> interval<T, Traits> abs(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> sqrt(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> square(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> pow(const interval<T, Traits>& x, int y);
|
||
|
||
/* transcendental functions: exp, log */
|
||
template <class T, class Traits> interval<T, Traits> exp(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> log(const interval<T, Traits>& x);
|
||
|
||
/* fmod, for trigonometric function argument reduction (see below) */
|
||
template <class T, class Traits> interval<T, Traits> fmod(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> fmod(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> interval<T, Traits> fmod(const T& x, const interval<T, Traits>& y);
|
||
|
||
/* trigonometric functions */
|
||
template <class T, class Traits> interval<T, Traits> sin(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> cos(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> tan(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> asin(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> acos(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> atan(const interval<T, Traits>& x);
|
||
|
||
/* hyperbolic trigonometric functions */
|
||
template <class T, class Traits> interval<T, Traits> sinh(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> cosh(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> tanh(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> asinh(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> acosh(const interval<T, Traits>& x);
|
||
template <class T, class Traits> interval<T, Traits> atanh(const interval<T, Traits>& x);
|
||
|
||
/* min, max external functions (NOT std::min/max, see below) */
|
||
template <class T, class Traits> interval<T, Traits> max(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> max(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> interval<T, Traits> max(const T& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> min(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> min(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> interval<T, Traits> min(const T& x, const interval<T, Traits>& y);
|
||
|
||
/* bounds-related interval functions */
|
||
template <class T, class Traits> T lower(const interval<T, Traits>& x);
|
||
template <class T, class Traits> T upper(const interval<T, Traits>& x);
|
||
template <class T, class Traits> T width(const interval<T, Traits>& x);
|
||
template <class T, class Traits> T median(const interval<T, Traits>& x);
|
||
|
||
/* bounds-related interval functions */
|
||
template <class T, class Traits> bool empty(const interval<T, Traits>& b);
|
||
template <class T, class Traits> bool singleton(const interval<T, Traits>& x);
|
||
template <class T, class Traits> bool equal(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool in(const T& r, const interval<T, Traits>& b);
|
||
template <class T, class Traits> bool in_zero(const interval<T, Traits>& b);
|
||
template <class T, class Traits> bool subset(const interval<T, Traits>& a, const interval<T, Traits>& b);
|
||
template <class T, class Traits> bool proper_subset(const interval<T, Traits>& a, const interval<T, Traits>& b);
|
||
template <class T, class Traits> bool overlap(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
|
||
/* set manipulation interval functions */
|
||
template <class T, class Traits> interval<T, Traits> intersection(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> hull(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> hull(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> interval<T, Traits> hull(const T& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> interval<T, Traits> hull(const T& x, const T& y);
|
||
template <class T, class Traits> std::pair<interval<T, Traits>, interval<T, Traits> > bisect(const interval<T, Traits>& x);
|
||
|
||
/* interval comparison operators */
|
||
template<class T, class Traits> bool operator<(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template<class T, class Traits> bool operator<(const interval<T, Traits>& x, const T& y);
|
||
template<class T, class Traits> bool operator<(const T& x, const interval<T, Traits>& y);
|
||
|
||
template<class T, class Traits> bool operator<=(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template<class T, class Traits> bool operator<=(const interval<T, Traits>& x, const T& y);
|
||
template<class T, class Traits> bool operator<=(const T& x, const interval<T, Traits>& y);
|
||
|
||
template<class T, class Traits> bool operator>(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template<class T, class Traits> bool operator>(const interval<T, Traits>& x, const T& y);
|
||
template<class T, class Traits> bool operator>(const T& x, const interval<T, Traits>& y);
|
||
|
||
template<class T, class Traits> bool operator>=(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template<class T, class Traits> bool operator>=(const interval<T, Traits>& x, const T& y);
|
||
template<class T, class Traits> bool operator>=(const T& x, const interval<T, Traits>& y);</pre>
|
||
<pre>template<class T, class Traits> bool operator==(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template<class T, class Traits> bool operator==(const interval<T, Traits>& x, const T& y);
|
||
template<class T, class Traits> bool operator==(const T& x, const interval<T, Traits>& y);
|
||
|
||
template<class T, class Traits> bool operator!=(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template<class T, class Traits> bool operator!=(const interval<T, Traits>& x, const T& y);
|
||
template<class T, class Traits> bool operator!=(const T& x, const interval<T, Traits>& y);
|
||
|
||
} // namespace numeric
|
||
} // namespace boost</pre>
|
||
|
||
<h2><a name="interval"></a>Template class <code>interval</code></h2>
|
||
The public interface of the template class interval itself is kept at a
|
||
simplest minimum:
|
||
<pre>template <class T, class Policies = typename interval_lib::default_policies<T>::type>
|
||
class interval
|
||
{
|
||
public:
|
||
typedef T base_type;
|
||
typedef Traits traits_type;
|
||
|
||
interval(const T& v = T());
|
||
interval(const T& l, const T& u);
|
||
|
||
template<class Traits2>
|
||
interval(const interval<T,Traits2>& r);
|
||
|
||
// compiler-generated copy constructor and assignment operator are fine
|
||
|
||
interval& operator=(const T& x);
|
||
void assign(const T& l, const T& u);
|
||
|
||
const T& lower() const;
|
||
const T& upper() const;
|
||
|
||
static interval empty();
|
||
static interval whole();
|
||
static interval hull(const T& x, const T& y);
|
||
|
||
interval& operator+= (const T& r);
|
||
interval& operator+= (const interval& r);
|
||
interval& operator-= (const T& r);
|
||
interval& operator-= (const interval& r);
|
||
interval& operator*= (const T& r);
|
||
interval& operator*= (const interval& r);
|
||
interval& operator/= (const T& r);
|
||
interval& operator/= (const interval& r);
|
||
};</pre>
|
||
|
||
<p>The two main constructors accept one and two arguments of type T. The
|
||
first one produces a singleton interval [v,v]; and the second one an interval
|
||
[l,u]. The second one will use the checking policy if u<l. If you are not
|
||
sure whether the bounds are inverted or not, it is better to use the function
|
||
call <code>hull(l,u)</code>. This will not create a problem if u<l.</p>
|
||
|
||
<p>There is a template constructor in order to change the traits parameter of
|
||
an interval. But there is no constructor that changes the base type of an
|
||
interval (it could lead to violating the inclusion property if the old base
|
||
type is not contained in the new one).</p>
|
||
|
||
<p>There is an assign function in order to directly change the bounds of an
|
||
interval. It behaves like the second constructor if the bounds are inverted.
|
||
There is no assign function that directly takes an interval or only one
|
||
number as a parameter; just use the assignment operator in that case.</p>
|
||
|
||
<p>Assignment operator, copy constructor and destructor are the ones the
|
||
compiler automatically generates. There is also an assignment operator for
|
||
the type T.</p>
|
||
|
||
<p>The static functions <code>empty</code> and <code>whole</code> produces
|
||
the corresponding intervals. They are static member functions rather than
|
||
global functions because they cannot guess their return types. Likewise for
|
||
<code>hull</code>.</p>
|
||
|
||
<h2><a name="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></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).</p>
|
||
|
||
<h4><code>min</code> <code>max</code> <code>abs</code> <code>square</code>
|
||
<code>pow</code> <code>division_part?</code></h4>
|
||
|
||
<p>The functions <code>min</code>, <code>max</code> and <code>abs</code> are
|
||
also defined. Please do not mistake them for the functions defined in the
|
||
standard library (aka <code>a<b?a:b</code>, <code>a>b?a:b</code>,
|
||
<code>a<0?-a:a</code>). These functions are compatible with the elementary
|
||
property of interval arithmetic. For example, max([<i>a</i>,<i>b</i>],
|
||
[<i>c</i>,<i>d</i>]) = {max(<i>x</i>,<i>y</i>) such that <i>x</i> in
|
||
[<i>a</i>,<i>b</i>] and <i>y</i> in [<i>c</i>,<i>d</i>]}. They are not
|
||
defined in the <code>std</code> namespace but in the boost namespace in order
|
||
to avoid conflict with the other definitions.</p>
|
||
|
||
<p>The <code>square</code> function is quite particular. As you can expect
|
||
from its name, it computes the square of its argument. The reason this
|
||
function is provided is: <code>square(x)</code> is not <code>x*x</code> but
|
||
only a subset when <code>x</code> contains zero. For example, [-2,2]*[-2,2] =
|
||
[-4,4] but [-2,2]<5D> = [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.</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 containg [2,3] / [-2,1] is
|
||
not ]-∞,∞[ but the union of ]-∞,-1] and [2,∞[.
|
||
When the result of the division is representable by only one interval,
|
||
<code>division_part1</code> returns this interval and sets the boolean
|
||
reference to <code>false</code>. However, if the result needs two intervals,
|
||
<code>division_part1</code> returns the negative part and sets the boolean
|
||
reference to <code>true</code>; a call to <code>division_part2</code> is now
|
||
needed to get the positive part.</p>
|
||
|
||
<h4><code>intersect</code> <code>hull</code> <code>overlap</code>
|
||
<code>in</code> <code>in_zero</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>in_zero</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">checking</a> policy to
|
||
produce empty intervals when the input interval is strictly outside of the
|
||
domain of the function.</p>
|
||
|
||
<p>The function <code>fmod(interval x, interval y)</code> expects the lower
|
||
bound of <code>y</code> to be strictly positive and returns an interval
|
||
<code>z</code> such as <code>0 <= z.lower() < y.upper()</code> and such
|
||
as <code>z</code> is a superset of <code>x-n*y</code> (with <code>n</code>
|
||
being an integer). So, if the two arguments are positive singletons, this
|
||
function <code>fmod(interval, interval)</code> will behave like the
|
||
traditional function <code>fmod(double, double)</code>.</p>
|
||
|
||
<p>Please note that <code>fmod</code> does not respect the inclusion property
|
||
of arithmetic interval. For example, the result of
|
||
<code>fmod</code>([13,17],[7,8]) should be [0,8] (since it must contain [0,3]
|
||
and [5,8]). But this answer is not really useful when the purpose is to
|
||
restrict an interval in order to compute a periodic function. It is the
|
||
reason why <code>fmod</code> will answer [5,10].</p>
|
||
|
||
<h3>Constants</h3>
|
||
|
||
<p>Some constants are hidden in the <code>boost::interval_lib</code>
|
||
namespace. They need to be explicitely templated by the interval type. The
|
||
functions are <code>pi<I>()</code>, <code>pi_half<I>()</code> and
|
||
<code>pi_twice<I>()</code>, and they return an object of interval type
|
||
<code>I</code>. Their respective values are π, π/2 and
|
||
2π.</p>
|
||
|
||
<h3>Exception throwing</h3>
|
||
|
||
<p>The interval class and all the functions defined around this class never
|
||
throw any exceptions by themselves. However, it does not mean that an
|
||
operation will never throw an exception. For example, let's consider the copy
|
||
constructor. As explained before, it is the default copy constructor
|
||
generated by the compiler. So it will not throw an exception if the copy
|
||
constructor of the base type does not throw an exception.</p>
|
||
|
||
<p>The same situation applies to all the functions: exceptions will only be
|
||
thrown if the base type or one of the three policies throws an exception.</p>
|
||
|
||
<h2 id="interval_lib">Interval Support Library</h2>
|
||
|
||
<p>The interval support library consists of a collection of classes that can
|
||
be used and combined to fabricate almost various commonly-needed interval
|
||
policies. In contrast to the basic classes and functions which are used in
|
||
conjunction with <code>interval<T></code> (and the default policies as
|
||
the implicit second template parameter in this type), which belong simply to
|
||
the namespace <code>boost</code>, these components belong to the namespace
|
||
<code>boost::numeric::interval_lib</code>.</p>
|
||
|
||
<p>We merely give the synopsis here and defer each section to a separate web
|
||
page since it is only intended for the advanced user. This allows to expand
|
||
on each topic with examples, without unduly stretching the limits of this
|
||
document.</p>
|
||
|
||
<h4>Synopsis</h4>
|
||
<pre>namespace boost {
|
||
namespace numeric {
|
||
namespace interval_lib {
|
||
|
||
<font color="#ff0000">/* built-in rounding policy and its specializations */</font>
|
||
template <class T> struct rounded_math;
|
||
template <> struct rounded_math<float>;
|
||
template <> struct rounded_math<double>;
|
||
template <> struct rounded_math<long double>;
|
||
|
||
<span style="color: #FF0000">/* built-in rounding construction blocks */</span>
|
||
template <class T> struct rounding_control;
|
||
|
||
template <class T, class Rounding = rounding_control<T> > struct rounded_arith_exact;
|
||
template <class T, class Rounding = rounding_control<T> > struct rounded_arith_std;
|
||
template <class T, class Rounding = rounding_control<T> > struct rounded_arith_opp;
|
||
|
||
template <class T, class Rounding> struct rounded_transc_dummy;
|
||
template <class T, class Rounding = rounded_arith_exact<T> > struct rounded_transc_exact;
|
||
template <class T, class Rounding = rounded_arith_std<T> > struct rounded_transc_std;
|
||
template <class T, class Rounding = rounded_arith_opp<T> > struct rounded_transc_opp;
|
||
|
||
template <class Rounding> struct save_state;
|
||
template <class Rounding> struct save_state_nothing;
|
||
|
||
<font color="#ff0000">/* built-in checking policies */</font>
|
||
template <class T> struct checking_nothing;
|
||
template <class T> struct checking_lax;
|
||
template <class T> struct checking_strict;
|
||
|
||
<span style="color: #FF0000">/* some metaprogramming to manipulate interval policies */</span>
|
||
template <class Rounding, class Checking> struct policies;
|
||
template <class OldInterval, class NewRounding> struct change_rounding;
|
||
template <class OldInterval, class NewChecking> struct change_checking;
|
||
template <class OldInterval> struct unprotect;
|
||
|
||
<span style="color: #FF0000">/* constants, need to be explicitly templated */</span>
|
||
template<class I> I pi();
|
||
template<class I> I pi_half();
|
||
template<class I> I pi_twice();
|
||
|
||
<span style="color: #FF0000">/* interval explicit comparison functions</span><span style="color: #FF0000">:
|
||
* the mode can be cer=certainly or pos=possibly,
|
||
* the function lt=less_than, gt=greater_than, le=less_than_or_equal_to, ge=greater_than_or_equal_to
|
||
* eq=equal_to, ne= not_equal_to */</span>
|
||
template <class T, class Traits> bool cerlt(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool cerlt(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool cerlt(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool cerle(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool cerle(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool cerle(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool cergt(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool cergt(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool cergt(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool cerge(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool cerge(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool cerge(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool cereq(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool cereq(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool cereq(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool cerne(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool cerne(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool cerne(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool poslt(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool poslt(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool poslt(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool posle(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool posle(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool posle(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool posgt(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool posgt(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool posgt(const T& x, const interval<T, Traits> & y);
|
||
|
||
template <class T, class Traits> bool posge(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool posge(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool posge(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool poseq(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool poseq(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool poseq(const T& x, const interval<T, Traits>& y);
|
||
|
||
template <class T, class Traits> bool posne(const interval<T, Traits>& x, const interval<T, Traits>& y);
|
||
template <class T, class Traits> bool posne(const interval<T, Traits>& x, const T& y);
|
||
template <class T, class Traits> bool posne(const T& x, const interval<T, Traits>& y);
|
||
|
||
<font color="#ff0000">/* comparison namespaces */</font>
|
||
namespace compare {
|
||
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="compil">Compilation Notes</h2>
|
||
|
||
<h4>Compilation options</h4>
|
||
We have made many efforts to reduce the number of compilation options to a
|
||
minimum, but depending on your platform, you may find that you need one or
|
||
two. Some versions of gcc miss proper specialization of
|
||
<code>numeric_limits</code> and using the flag <code>-DBOOST_NO_LIMITS</code>
|
||
may help. Also removing the warnings for older gcc compilers about the lack
|
||
of long double support can be done with the option
|
||
<code>-Wno-long-double</code>. The tests and examples have successfully been
|
||
compiled with gcc 2.95 on x86 (Debian, FreeBSD), on sparc (Debian); with gcc
|
||
2.95 and stlport on x86 (Solaris), sparc (Solaris), and powerpc (Debian);
|
||
with gcc 2.96, 3.04, 3.1.1, and 3.2 on x86 (Debian); with Intel cc 6.0 and
|
||
7.0 on x86 (Debian); and with SunPRO 5.3 (Solaris). There are some issues
|
||
with Borland on x86 (Windows), and Visual C++ which we're working on.
|
||
|
||
<h2 id="dangers">Common Pitfalls and Dangers</h2>
|
||
|
||
<h4>Comparisons</h4>
|
||
|
||
<p>One of the biggest problems is problably the correct use of the comparison
|
||
functions and operators. First, functions and operators do not try to know if
|
||
two intervals are the same mathematical object. So, if the comparison used is
|
||
"certain", then <code>x != x</code> is always true unless <code>x</code> is a
|
||
singleton interval; and the same problem arises with <code>cereq</code> and
|
||
<code>cerne</code>.</p>
|
||
|
||
<p>Another misleading interpretation of the comparison is: you cannot always
|
||
expect [a,b] < [c,d] to be !([a,b] >= [c,d]) since the comparison is
|
||
not necessarily total. Equality and less comparison should be seen as two
|
||
distincts relational operators.</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 occurences 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::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.)</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 three 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 second 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 mecanisms are provided in order to speed up the
|
||
computations. It seems to be heavy and hazardous optimizations for a gain of
|
||
only a few computer cycles; but in reality, the speed-up factor can easily go
|
||
past 2 or 3 depending on the computer. Moreover, these optimizations do not
|
||
impact the interface in any major way (with the design we have chosen,
|
||
everything can be added by specialization or by passing different template
|
||
parameters).</p>
|
||
|
||
<p><strong>Pred/succ.</strong> In a previous version, two functions
|
||
<code>pred</code> and <code>succ</code>, with various corollaries like
|
||
<code>widen</code>, were supplied. The intent was to enlarge the interval by
|
||
one ulp (as little as possible), e.g. to ensure the inclusion property. Since
|
||
making interval a template of T, we could not define <i>ulp</i> for a random
|
||
parameter. In turn, rounding policies let us eliminate entirely the use of
|
||
ulp while making the intervals tighter (if a result is a representable
|
||
singleton, there is no use to widen the interval). We decided to drop those
|
||
functions.</p>
|
||
|
||
<p><strong>Specialization of <code>std::less</code>.</strong> Since the
|
||
operator <code><</code> depends on the comparison namespace chosen 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 basic header
|
||
<code>boost/numeric/interval.hpp</code> does not include the I/O operators
|
||
for the class interval. Somewhat default operators can be had by including
|
||
<code>boost/numeric/interval/io.hpp</code>, and they make very few effort to
|
||
guarantee the inclusion property (they do so for <code>float</code>,
|
||
<code>double</code>, and <code>long double</code>). But they cannot guarantee
|
||
it for any base number type, especially since it is not know how the type
|
||
will be displayed (for example, there could be trouble if the type is a
|
||
symbolic type that uses the character `[` or `]'). For this, we would need an
|
||
extra i/o policy. It was not felt worth the trouble. For one thing, it's
|
||
always possible to display the bounds. For another, intervals are used
|
||
somewhat internally and there is seldom need to display them. But if this
|
||
should be needed, the header is there.</p>
|
||
|
||
<p><strong>Conversion from <code>interval<T1></code> to
|
||
<code>interval<T></code>.</strong> There is no such conversion in the
|
||
library. Specifically, there is no way to change the base number type without
|
||
explicitly casting both the lower and upper bounds from <code>T1</code> to
|
||
<code>T2</code> and using a constructor. We did not want to provide this
|
||
conversion because there is no easy way to make sure the inclusion property
|
||
is guaranteed: a simple casting with loss of precision can lead to invalid or
|
||
empty intervals. Moreover it is not clear who should be responsible for the
|
||
conversion: <code>T2</code> is not required to know about all the possible
|
||
types <code>T1</code>. We also do not want to throw an exception is there is
|
||
a loss of precision (as is done for instance in <code>numeric_cast</code>);
|
||
instead, the result should be correctly rounded to ensure the inclusion
|
||
property. So we decided not to provide the conversion and leave it up to the
|
||
user to do it himself or herself.</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> and the
|
||
work itself can be found <a
|
||
href="http://www.rhein-main.de/people/jmaurer/interval.tar.gz">here</a>.
|
||
Jeremy Siek and Maarten Keijzer provided some rounding control for MSVC and
|
||
Sparc platforms.</p>
|
||
|
||
<p>Guillaume Melquiond, Herv<72> Br<42>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 mostly did most of
|
||
the coding, while Sylvain and Herv<72> have provided some useful comments in
|
||
order for this library to be written. Herv<72> reorganized and wrote chapters of
|
||
the documentation based on Guillaume's great starting point.</p>
|
||
<hr>
|
||
|
||
<p>Revised: 2003-02-05<br>
|
||
Copyright (c) Guillaume Melquiond, Sylvain Pion, Herv<72> Br<42>nnimann,
|
||
2002-2003.<br>
|
||
Polytechnic University, 2002.</p>
|
||
</body>
|
||
</html>
|