Files
multiprecision/doc/html/boost_multiprecision/intro.html
2012-03-28 17:53:35 +00:00

523 lines
30 KiB
HTML

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Introduction</title>
<link rel="stylesheet" href="http://www.boost.org/doc/libs/release/doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Multiprecision">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Multiprecision">
<link rel="prev" href="../index.html" title="Chapter&#160;1.&#160;Boost.Multiprecision">
<link rel="next" href="tut.html" title="Tutorial">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="tut.html"><img src="../images/next.png" alt="Next"></a>
</div>
<div class="section boost_multiprecision_intro">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_multiprecision.intro"></a><a class="link" href="intro.html" title="Introduction">Introduction</a>
</h2></div></div></div>
<p>
The Multiprecision Library provides <span class="emphasis"><em>User-defined</em></span> integer,
rational and floating-point C++ types which try to emulate as closely as practicable
the C++ built-in types, but provide for more range and precision. Depending
upon the number type, precision may be arbitrarily large (limited only by available
memory), fixed at compile time values, for example 50 decimal digits, or a
variable controlled at run-time by member functions. The types are expression-template-enabled
for better performance than naive user-defined types.
</p>
<p>
The Multiprecision library comes in two distinct parts:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem">
An expression-template-enabled front-end <code class="computeroutput"><span class="identifier">mp_number</span></code>
that handles all the operator overloading, expression evaluation optimization,
and code reduction.
</li>
<li class="listitem">
A selection of back-ends that implement the actual arithmetic operations,
and need conform only to the reduced interface requirements of the front-end.
</li>
</ul></div>
<p>
Separation of front-end and back-end allows use of highly refined, but restricted
license libraries where possible, but provides Boost license alternatives for
users who must have a portable unconstrained license. Which is to say some
back-ends rely on 3rd party libraries, but a header-only Boost license version
is always available (if somewhat slower).
</p>
<p>
The library is often used via one of the predefined typedefs: for example if
you wanted an <a href="http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic" target="_top">arbitrary
precision</a> integer type using <a href="http://gmplib.org" target="_top">GMP</a>
as the underlying implementation then you could use:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">multiprecision</span><span class="special">/</span><span class="identifier">gmp</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// Defines the wrappers around the GMP library's types</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">mpz_int</span> <span class="identifier">myint</span><span class="special">;</span> <span class="comment">// Arbitrary precision integer type.</span>
</pre>
<p>
Alternatively, you can compose your own multiprecision type, by combining
<code class="computeroutput"><span class="identifier">mp_number</span></code> with one of the predefined
back-end types. For example, suppose you wanted a 300 decimal digit floating-point
type based on the <a href="http://www.mpfr.org" target="_top">MPFR</a> library. In
this case, there's no predefined typedef with that level of precision, so instead
we compose our own:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">multiprecision</span><span class="special">/</span><span class="identifier">mpfr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// Defines the Backend type that wraps MPFR</span>
<span class="keyword">namespace</span> <span class="identifier">mp</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">;</span> <span class="comment">// Reduce the typing a bit later...</span>
<span class="keyword">typedef</span> <span class="identifier">mp</span><span class="special">::</span><span class="identifier">mp_number</span><span class="special">&lt;</span><span class="identifier">mp</span><span class="special">::</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="number">300</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">my_float</span><span class="special">;</span>
<span class="identifier">my_float</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">c</span><span class="special">;</span> <span class="comment">// These variables have 300 decimal digits precision</span>
</pre>
<p>
We can repeat the above example, but with the expression templates disabled
(for faster compile times, but slower runtimes) by passing a second template
argument to <code class="computeroutput"><span class="identifier">mp_number</span></code>:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">multiprecision</span><span class="special">/</span><span class="identifier">mpfr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// Defines the Backend type that wraps MPFR</span>
<span class="keyword">namespace</span> <span class="identifier">mp</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">;</span> <span class="comment">// Reduce the typing a bit later...</span>
<span class="keyword">typedef</span> <span class="identifier">mp</span><span class="special">::</span><span class="identifier">mp_number</span><span class="special">&lt;</span><span class="identifier">mp</span><span class="special">::</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="number">300</span><span class="special">&gt;,</span> <span class="keyword">false</span><span class="special">&gt;</span> <span class="identifier">my_float</span><span class="special">;</span>
<span class="identifier">my_float</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">c</span><span class="special">;</span> <span class="comment">// These variables have 300 decimal digits precision</span>
</pre>
<h5>
<a name="boost_multiprecision.intro.h0"></a>
<span><a name="boost_multiprecision.intro.expression_templates"></a></span><a class="link" href="intro.html#boost_multiprecision.intro.expression_templates">Expression
Templates</a>
</h5>
<p>
Class <code class="computeroutput"><span class="identifier">mp_number</span></code> is expression-template-enabled:
that means that rather than having a multiplication operator that looks like
this:
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Backend</span><span class="special">&gt;</span>
<span class="identifier">mp_number</span><span class="special">&lt;</span><span class="identifier">Backend</span><span class="special">&gt;</span> <span class="keyword">operator</span> <span class="special">*</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_number</span><span class="special">&lt;</span><span class="identifier">Backend</span><span class="special">&gt;&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_number</span><span class="special">&lt;</span><span class="identifier">Backend</span><span class="special">&gt;&amp;</span> <span class="identifier">b</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">mp_number</span><span class="special">&lt;</span><span class="identifier">Backend</span><span class="special">&gt;</span> <span class="identifier">result</span><span class="special">(</span><span class="identifier">a</span><span class="special">);</span>
<span class="identifier">result</span> <span class="special">*=</span> <span class="identifier">b</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
Instead the operator looks more like this:
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Backend</span><span class="special">&gt;</span>
<span class="emphasis"><em>unmentionable-type</em></span> <span class="keyword">operator</span> <span class="special">*</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_number</span><span class="special">&lt;</span><span class="identifier">Backend</span><span class="special">&gt;&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_number</span><span class="special">&lt;</span><span class="identifier">Backend</span><span class="special">&gt;&amp;</span> <span class="identifier">b</span><span class="special">);</span>
</pre>
<p>
Where the "unmentionable" return type is an implementation detail
that, rather than containing the result of the multiplication, contains instructions
on how to compute the result. In effect it's just a pair of references to the
arguments of the function, plus some compile-time information that stores what
the operation is.
</p>
<p>
The great advantage of this method is the <span class="emphasis"><em>elimination of temporaries</em></span>:
for example the "naive" implementation of <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code> above, requires one temporary for computing
the result, and at least another one to return it. It's true that sometimes
this overhead can be reduced by using move-semantics, but it can't be eliminated
completely. For example, lets suppose we're evaluating a polynomial via Horners
method, something like this:
</p>
<pre class="programlisting"><span class="identifier">T</span> <span class="identifier">a</span><span class="special">[</span><span class="number">7</span><span class="special">]</span> <span class="special">=</span> <span class="special">{</span> <span class="comment">/* some values */</span> <span class="special">};</span>
<span class="comment">//....</span>
<span class="identifier">y</span> <span class="special">=</span> <span class="special">(((((</span><span class="identifier">a</span><span class="special">[</span><span class="number">6</span><span class="special">]</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">a</span><span class="special">[</span><span class="number">5</span><span class="special">])</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">a</span><span class="special">[</span><span class="number">4</span><span class="special">])</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">a</span><span class="special">[</span><span class="number">3</span><span class="special">])</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">a</span><span class="special">[</span><span class="number">2</span><span class="special">])</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">a</span><span class="special">[</span><span class="number">1</span><span class="special">])</span> <span class="special">*</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">a</span><span class="special">[</span><span class="number">0</span><span class="special">];</span>
</pre>
<p>
If type <code class="computeroutput"><span class="identifier">T</span></code> is an <code class="computeroutput"><span class="identifier">mp_number</span></code>, then this expression is evaluated
<span class="emphasis"><em>without creating a single temporary value</em></span>. In contrast,
if we were using the C++ wrapper that ships with <a href="http://gmplib.org" target="_top">GMP</a>
- <a href="http://gmplib.org/manual/C_002b_002b-Interface-Floats.html#C_002b_002b-Interface-Floats" target="_top">mpfr_class</a>
- then this expression would result in no less than 11 temporaries (this is
true even though <a href="http://gmplib.org/manual/C_002b_002b-Interface-Floats.html#C_002b_002b-Interface-Floats" target="_top">mpfr_class</a>
does use expression templates to reduce the number of temporaries somewhat).
Had we used an even simpler wrapper around <a href="http://gmplib.org" target="_top">GMP</a>
or <a href="http://www.mpfr.org" target="_top">MPFR</a> like <code class="computeroutput"><span class="identifier">mpclass</span></code>
things would have been even worse and no less that 24 temporaries are created
for this simple expression (note - we actually measure the number of memory
allocations performed rather than the number of temporaries directly).
</p>
<p>
This library also extends expression template support to standard library functions
like <code class="computeroutput"><span class="identifier">abs</span></code> or <code class="computeroutput"><span class="identifier">sin</span></code>
with <code class="computeroutput"><span class="identifier">mp_number</span></code> arguments. This
means that an expression such as:
</p>
<pre class="programlisting"><span class="identifier">y</span> <span class="special">=</span> <span class="identifier">abs</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
</pre>
<p>
can be evaluated without a single temporary being calculated. Even expressions
like:
</p>
<pre class="programlisting"><span class="identifier">y</span> <span class="special">=</span> <span class="identifier">sin</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
</pre>
<p>
get this treatment, so that variable 'y' is used as "working storage"
within the implementation of <code class="computeroutput"><span class="identifier">sin</span></code>,
thus reducing the number of temporaries used by one. Of course, should you
write:
</p>
<pre class="programlisting"><span class="identifier">x</span> <span class="special">=</span> <span class="identifier">sin</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
</pre>
<p>
Then we clearly can't use <code class="computeroutput"><span class="identifier">x</span></code>
as working storage during the calculation, so then a temporary variable is
created in this case.
</p>
<p>
Given the comments above, you might be forgiven for thinking that expression-templates
are some kind of universal-panacea: sadly though, all tricks like this have
their downsides. For one thing, expression template libraries like this one,
tend to be slower to compile than their simpler cousins, they're also harder
to debug (should you actually want to step through our code!), and rely on
compiler optimizations being turned on to give really good performance. Also,
since the return type from expressions involving <code class="computeroutput"><span class="identifier">mp_number</span></code>s
is an "unmentionable implementation detail", you have to be careful
to cast the result of an expression to the actual number type when passing
an expression to a template function. For example, given:
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">void</span> <span class="identifier">my_proc</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;);</span>
</pre>
<p>
Then calling:
</p>
<pre class="programlisting"><span class="identifier">my_proc</span><span class="special">(</span><span class="identifier">a</span><span class="special">+</span><span class="identifier">b</span><span class="special">);</span>
</pre>
<p>
Will very likely result in obscure error messages inside the body of <code class="computeroutput"><span class="identifier">my_proc</span></code> - since we've passed it an expression
template type, and not a number type. Instead we probably need:
</p>
<pre class="programlisting"><span class="identifier">my_proc</span><span class="special">(</span><span class="identifier">my_mp_number_type</span><span class="special">(</span><span class="identifier">a</span><span class="special">+</span><span class="identifier">b</span><span class="special">));</span>
</pre>
<p>
Having said that, these situations don't occur that often - or indeed not at
all for non-template functions. In addition, all the functions in the Boost.Math
library will automatically convert expression-template arguments to the underlying
number type without you having to do anything, so:
</p>
<pre class="programlisting"><span class="identifier">mpfr_float_100</span> <span class="identifier">a</span><span class="special">(</span><span class="number">20</span><span class="special">),</span> <span class="identifier">delta</span><span class="special">(</span><span class="number">0.125</span><span class="special">);</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">gamma_p</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">delta</span><span class="special">);</span>
</pre>
<p>
Will work just fine, with the <code class="computeroutput"><span class="identifier">a</span> <span class="special">+</span> <span class="identifier">delta</span></code> expression
template argument getting converted to an <code class="computeroutput"><span class="identifier">mpfr_float_100</span></code>
internally by the Boost.Math library.
</p>
<p>
One other potential pitfall that's only possible in C++11: you should never
store an expression template using:
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">my_expression</span> <span class="special">=</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span> <span class="special">-</span> <span class="identifier">c</span><span class="special">;</span>
</pre>
<p>
unless you're absolutely sure that the lifetimes of <code class="computeroutput"><span class="identifier">a</span></code>,
<code class="computeroutput"><span class="identifier">b</span></code> and <code class="computeroutput"><span class="identifier">c</span></code>
will outlive that of <code class="computeroutput"><span class="identifier">my_expression</span></code>.
</p>
<p>
And finally... the performance improvements from an expression template library
like this are often not as dramatic as the reduction in number of temporaries
would suggest. For example if we compare this library with <a href="http://math.berkeley.edu/~wilken/code/gmpfrxx/" target="_top">mpfr_class</a>
and <a href="http://www.holoborodko.com/pavel/mpfr/" target="_top">mpreal</a>, with
all three using the underlying <a href="http://www.mpfr.org" target="_top">MPFR</a>
library at 50 decimal digits precision then we see the following typical results
for polynomial execution:
</p>
<div class="table">
<a name="boost_multiprecision.intro.evaluation_of_order_6_polynomial_"></a><p class="title"><b>Table&#160;1.1.&#160;Evaluation of Order 6 Polynomial.</b></p>
<div class="table-contents"><table class="table" summary="Evaluation of Order 6 Polynomial.">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Library
</p>
</th>
<th>
<p>
Relative Time
</p>
</th>
<th>
<p>
Relative number of memory allocations
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
mp_number
</p>
</td>
<td>
<p>
1.0 (0.00793s)
</p>
</td>
<td>
<p>
1.0 (2996 total)
</p>
</td>
</tr>
<tr>
<td>
<p>
<a href="http://math.berkeley.edu/~wilken/code/gmpfrxx/" target="_top">mpfr_class</a>
</p>
</td>
<td>
<p>
1.2 (0.00931s)
</p>
</td>
<td>
<p>
4.3 (12976 total)
</p>
</td>
</tr>
<tr>
<td>
<p>
<a href="http://www.holoborodko.com/pavel/mpfr/" target="_top">mpreal</a>
</p>
</td>
<td>
<p>
1.9 (0.0148s)
</p>
</td>
<td>
<p>
9.3 (27947 total)
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><p>
As you can see, the execution time increases a lot more slowly than the number
of memory allocations. There are a number of reasons for this:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem">
The cost of extended-precision multiplication and division is so great,
that the times taken for these tend to swamp everything else.
</li>
<li class="listitem">
The cost of an in-place multiplication (using <code class="computeroutput"><span class="keyword">operator</span><span class="special">*=</span></code>) tends to be more than an out-of-place
<code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code>
(typically <code class="computeroutput"><span class="keyword">operator</span> <span class="special">*=</span></code>
has to create a temporary workspace to carry out the multiplication, where
as <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code>
can use the target variable as workspace). Since the expression templates
carry out their magic by converting out-of-place operators to in-place
ones, we necessarily take this hit. Even so the transformation is more
efficient than creating the extra temporary variable, just not by as much
as one would hope.
</li>
</ul></div>
<p>
Finally, note that <code class="computeroutput"><span class="identifier">mp_number</span></code>
takes a second template argument, which, when set to <code class="computeroutput"><span class="keyword">false</span></code>
disables all the expression template machinary. The result is much faster to
compile, but slower at runtime.
</p>
<p>
We'll conclude this section by providing some more performance comparisons
between these three libraries, again, all are using <a href="http://www.mpfr.org" target="_top">MPFR</a>
to carry out the underlying arithmetic, and all are operating at the same precision
(50 decimal digits):
</p>
<div class="table">
<a name="boost_multiprecision.intro.evaluation_of_boost_math_s_bessel_function_test_data"></a><p class="title"><b>Table&#160;1.2.&#160;Evaluation of Boost.Math's Bessel function test data</b></p>
<div class="table-contents"><table class="table" summary="Evaluation of Boost.Math's Bessel function test data">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Library
</p>
</th>
<th>
<p>
Relative Time
</p>
</th>
<th>
<p>
Relative Number of Memory Allocations
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
mp_number
</p>
</td>
<td>
<p>
1.0 (6.21s)
</p>
</td>
<td>
<p>
1.0 (2685469)
</p>
</td>
</tr>
<tr>
<td>
<p>
<a href="http://math.berkeley.edu/~wilken/code/gmpfrxx/" target="_top">mpfr_class</a>
</p>
</td>
<td>
<p>
1.04 (6.45s)
</p>
</td>
<td>
<p>
1.47 (3946007)
</p>
</td>
</tr>
<tr>
<td>
<p>
<a href="http://www.holoborodko.com/pavel/mpfr/" target="_top">mpreal</a>
</p>
</td>
<td>
<p>
1.53 (9.52s)
</p>
</td>
<td>
<p>
4.92 (13222940)
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><div class="table">
<a name="boost_multiprecision.intro.evaluation_of_boost_math_s_non_central_t_distribution_test_data"></a><p class="title"><b>Table&#160;1.3.&#160;Evaluation of Boost.Math's Non-Central T distribution test data</b></p>
<div class="table-contents"><table class="table" summary="Evaluation of Boost.Math's Non-Central T distribution test data">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Library
</p>
</th>
<th>
<p>
Relative Time
</p>
</th>
<th>
<p>
Relative Number of Memory Allocations
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
mp_number
</p>
</td>
<td>
<p>
1.0 (269s)
</p>
</td>
<td>
<p>
1.0 (139082551)
</p>
</td>
</tr>
<tr>
<td>
<p>
<a href="http://math.berkeley.edu/~wilken/code/gmpfrxx/" target="_top">mpfr_class</a>
</p>
</td>
<td>
<p>
1.04 (278s)
</p>
</td>
<td>
<p>
1.81 (252400791)
</p>
</td>
</tr>
<tr>
<td>
<p>
<a href="http://www.holoborodko.com/pavel/mpfr/" target="_top">mpreal</a>
</p>
</td>
<td>
<p>
1.49 (401s)
</p>
</td>
<td>
<p>
3.22 (447009280)
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break">
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2002-2012 John Maddock and Christopher Kormanyos<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="tut.html"><img src="../images/next.png" alt="Next"></a>
</div>
</body>
</html>