[DEV] add v1.66.0

This commit is contained in:
2018-01-12 21:47:58 +01:00
parent 87059bb1af
commit a97e9ae7d4
49032 changed files with 7668950 additions and 0 deletions

View File

@@ -0,0 +1,167 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Computing the Fifth Root</title>
<link rel="stylesheet" href="../../math.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Math Toolkit 2.6.0">
<link rel="up" href="../root_finding_examples.html" title="Examples of Root-Finding (with and without derivatives)">
<link rel="prev" href="lambda.html" title="Using C++11 Lambda's">
<link rel="next" href="multiprecision_root.html" title="Root-finding using Boost.Multiprecision">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="lambda.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="multiprecision_root.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="math_toolkit.root_finding_examples.5th_root_eg"></a><a class="link" href="5th_root_eg.html" title="Computing the Fifth Root">Computing
the Fifth Root</a>
</h3></div></div></div>
<p>
Let's now suppose we want to find the <span class="bold"><strong>fifth root</strong></span>
of a number <span class="emphasis"><em>a</em></span>.
</p>
<p>
The equation we want to solve is :
</p>
<p>
&#8192;&#8192;<span class="emphasis"><em>f</em></span>(x) = <span class="emphasis"><em>x<sup>5</sup> -a</em></span>
</p>
<p>
If your differentiation is a little rusty (or you are faced with an function
whose complexity makes differentiation daunting), then you can get help,
for example, from the invaluable <a href="http://www.wolframalpha.com/" target="_top">WolframAlpha
site.</a>
</p>
<p>
For example, entering the commmand: <code class="computeroutput"><span class="identifier">differentiate</span>
<span class="identifier">x</span> <span class="special">^</span> <span class="number">5</span></code>
</p>
<p>
or the Wolfram Language command: <code class="computeroutput"> <span class="identifier">D</span><span class="special">[</span><span class="identifier">x</span> <span class="special">^</span>
<span class="number">5</span><span class="special">,</span> <span class="identifier">x</span><span class="special">]</span></code>
</p>
<p>
gives the output: <code class="computeroutput"><span class="identifier">d</span><span class="special">/</span><span class="identifier">dx</span><span class="special">(</span><span class="identifier">x</span>
<span class="special">^</span> <span class="number">5</span><span class="special">)</span> <span class="special">=</span> <span class="number">5</span>
<span class="identifier">x</span> <span class="special">^</span> <span class="number">4</span></code>
</p>
<p>
and to get the second differential, enter: <code class="computeroutput"><span class="identifier">second</span>
<span class="identifier">differentiate</span> <span class="identifier">x</span>
<span class="special">^</span> <span class="number">5</span></code>
</p>
<p>
or the Wolfram Language command: <code class="computeroutput"><span class="identifier">D</span><span class="special">[</span><span class="identifier">x</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="number">2</span> <span class="special">}]</span></code>
</p>
<p>
to get the output: <code class="computeroutput"><span class="identifier">d</span> <span class="special">^</span>
<span class="number">2</span> <span class="special">/</span> <span class="identifier">dx</span> <span class="special">^</span> <span class="number">2</span><span class="special">(</span><span class="identifier">x</span> <span class="special">^</span>
<span class="number">5</span><span class="special">)</span> <span class="special">=</span> <span class="number">20</span> <span class="identifier">x</span>
<span class="special">^</span> <span class="number">3</span></code>
</p>
<p>
To get a reference value, we can enter: <code class="literal">fifth root 3126</code>
</p>
<p>
or: <code class="computeroutput"><span class="identifier">N</span><span class="special">[</span><span class="number">3126</span> <span class="special">^</span> <span class="special">(</span><span class="number">1</span> <span class="special">/</span> <span class="number">5</span><span class="special">),</span> <span class="number">50</span><span class="special">]</span></code>
</p>
<p>
to get a result with a precision of 50 decimal digits:
</p>
<p>
5.0003199590478625588206333405631053401128722314376
</p>
<p>
(We could also get a reference value using <a class="link" href="multiprecision_root.html" title="Root-finding using Boost.Multiprecision">multiprecision
root</a>).
</p>
<p>
The 1st and 2nd derivatives of x<sup>5</sup> are:
</p>
<p>
&#8192;&#8192;<span class="emphasis"><em>f</em></span>'(x) = 5x<sup>4</sup>
</p>
<p>
&#8192;&#8192;<span class="emphasis"><em>f</em></span>''(x) = 20x<sup>3</sup>
</p>
<p>
Using these expressions for the derivatives, the functor is:
</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">struct</span> <span class="identifier">fifth_functor_2deriv</span>
<span class="special">{</span>
<span class="comment">// Functor returning both 1st and 2nd derivatives.</span>
<span class="identifier">fifth_functor_2deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">to_find_root_of</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">a</span><span class="special">(</span><span class="identifier">to_find_root_of</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">/* Constructor stores value a to find root of, for example: */</span> <span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Return both f(x) and f'(x) and f''(x).</span>
<span class="identifier">T</span> <span class="identifier">fx</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">pow</span><span class="special">&lt;</span><span class="number">5</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">a</span><span class="special">;</span> <span class="comment">// Difference (estimate x^3 - value).</span>
<span class="identifier">T</span> <span class="identifier">dx</span> <span class="special">=</span> <span class="number">5</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">pow</span><span class="special">&lt;</span><span class="number">4</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">);</span> <span class="comment">// 1st derivative = 5x^4.</span>
<span class="identifier">T</span> <span class="identifier">d2x</span> <span class="special">=</span> <span class="number">20</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">pow</span><span class="special">&lt;</span><span class="number">3</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">);</span> <span class="comment">// 2nd derivative = 20 x^3</span>
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">fx</span><span class="special">,</span> <span class="identifier">dx</span><span class="special">,</span> <span class="identifier">d2x</span><span class="special">);</span> <span class="comment">// 'return' fx, dx and d2x.</span>
<span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="identifier">T</span> <span class="identifier">a</span><span class="special">;</span> <span class="comment">// to be 'fifth_rooted'.</span>
<span class="special">};</span> <span class="comment">// struct fifth_functor_2deriv</span>
</pre>
<p>
Our fifth-root function is now:
</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="identifier">T</span> <span class="identifier">fifth_2deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// return fifth root of x using 1st and 2nd derivatives and Halley.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">std</span><span class="special">;</span> <span class="comment">// Help ADL of std functions.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span> <span class="comment">// for halley_iterate.</span>
<span class="keyword">int</span> <span class="identifier">exponent</span><span class="special">;</span>
<span class="identifier">frexp</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">exponent</span><span class="special">);</span> <span class="comment">// Get exponent of z (ignore mantissa).</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">1.</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="number">5</span><span class="special">);</span> <span class="comment">// Rough guess is to divide the exponent by five.</span>
<span class="identifier">T</span> <span class="identifier">min</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">0.5</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="number">5</span><span class="special">);</span> <span class="comment">// Minimum possible value is half our guess.</span>
<span class="identifier">T</span> <span class="identifier">max</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">2.</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="number">5</span><span class="special">);</span> <span class="comment">// Maximum possible value is twice our guess.</span>
<span class="comment">// Stop when slightly more than one of the digits are correct:</span>
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">digits</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span> <span class="special">*</span> <span class="number">0.4</span><span class="special">);</span>
<span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">50</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">maxit</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">halley_iterate</span><span class="special">(</span><span class="identifier">fifth_functor_2deriv</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">),</span> <span class="identifier">guess</span><span class="special">,</span> <span class="identifier">min</span><span class="special">,</span> <span class="identifier">max</span><span class="special">,</span> <span class="identifier">digits</span><span class="special">,</span> <span class="identifier">it</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>
Full code of this example is at <a href="../../../../example/root_finding_example.cpp" target="_top">root_finding_example.cpp</a>
and <a href="../../../../example/root_finding_n_example.cpp" target="_top">root_finding_n_example.cpp</a>.
</p>
</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; 2006-2010, 2012-2014, 2017 Nikhar
Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Johan R&#229;de, Gautam
Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg, Daryle Walker
and Xiaogang Zhang<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="lambda.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="multiprecision_root.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,484 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Finding the Cubed Root With and Without Derivatives</title>
<link rel="stylesheet" href="../../math.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Math Toolkit 2.6.0">
<link rel="up" href="../root_finding_examples.html" title="Examples of Root-Finding (with and without derivatives)">
<link rel="prev" href="../root_finding_examples.html" title="Examples of Root-Finding (with and without derivatives)">
<link rel="next" href="lambda.html" title="Using C++11 Lambda's">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="lambda.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="math_toolkit.root_finding_examples.cbrt_eg"></a><a class="link" href="cbrt_eg.html" title="Finding the Cubed Root With and Without Derivatives">Finding the
Cubed Root With and Without Derivatives</a>
</h3></div></div></div>
<p>
First some <code class="computeroutput"><span class="preprocessor">#includes</span></code> that
will be needed.
</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">math</span><span class="special">/</span><span class="identifier">tools</span><span class="special">/</span><span class="identifier">roots</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="comment">//using boost::math::policies::policy;</span>
<span class="comment">//using boost::math::tools::newton_raphson_iterate;</span>
<span class="comment">//using boost::math::tools::halley_iterate; //</span>
<span class="comment">//using boost::math::tools::eps_tolerance; // Binary functor for specified number of bits.</span>
<span class="comment">//using boost::math::tools::bracket_and_solve_root;</span>
<span class="comment">//using boost::math::tools::toms748_solve;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">next</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// For float_distance.</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">tuple</span><span class="special">&gt;</span> <span class="comment">// for std::tuple and std::make_tuple.</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">cbrt</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// For boost::math::cbrt.</span>
</pre>
<div class="tip"><table border="0" summary="Tip">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
<th align="left">Tip</th>
</tr>
<tr><td align="left" valign="top"><p>
For clarity, <code class="computeroutput"><span class="keyword">using</span></code> statements
are provided to list what functions are being used in this example: you
can, of course, partly or fully qualify the names in other ways. (For your
application, you may wish to extract some parts into header files, but
you should never use <code class="computeroutput"><span class="keyword">using</span></code>
statements globally in header files).
</p></td></tr>
</table></div>
<p>
Let's suppose we want to find the root of a number <span class="emphasis"><em>a</em></span>,
and to start, compute the cube root.
</p>
<p>
So the equation we want to solve is:
</p>
<p>
&#8192;&#8192; <span class="emphasis"><em>f(x) = x&#179; -a</em></span>
</p>
<p>
We will first solve this without using any information about the slope or
curvature of the cube root function.
</p>
<p>
Fortunately, the cube-root function is 'Really Well Behaved' in that it is
monotonic and has only one root (we leave negative values 'as an exercise
for the student').
</p>
<p>
We then show how adding what we can know about this function, first just
the slope or 1st derivative <span class="emphasis"><em>f'(x)</em></span>, will speed homing
in on the solution.
</p>
<p>
Lastly, we show how adding the curvature <span class="emphasis"><em>f''(x)</em></span> too
will speed convergence even more.
</p>
<h4>
<a name="math_toolkit.root_finding_examples.cbrt_eg.h0"></a>
<span class="phrase"><a name="math_toolkit.root_finding_examples.cbrt_eg.cbrt_no_derivatives"></a></span><a class="link" href="cbrt_eg.html#math_toolkit.root_finding_examples.cbrt_eg.cbrt_no_derivatives">Cube
root function without derivatives</a>
</h4>
<p>
First we define a function object (functor):
</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">struct</span> <span class="identifier">cbrt_functor_noderiv</span>
<span class="special">{</span>
<span class="comment">// cube root of x using only function - no derivatives.</span>
<span class="identifier">cbrt_functor_noderiv</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">to_find_root_of</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">a</span><span class="special">(</span><span class="identifier">to_find_root_of</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">/* Constructor just stores value a to find root of. */</span> <span class="special">}</span>
<span class="identifier">T</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">fx</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">*</span><span class="identifier">x</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="comment">// Difference (estimate x^3 - a).</span>
<span class="keyword">return</span> <span class="identifier">fx</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="identifier">T</span> <span class="identifier">a</span><span class="special">;</span> <span class="comment">// to be 'cube_rooted'.</span>
<span class="special">};</span>
</pre>
<p>
Implementing the cube-root function itself is fairly trivial now: the hardest
part is finding a good approximation to begin with. In this case we'll just
divide the exponent by three. (There are better but more complex guess algorithms
used in 'real life'.)
</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="identifier">T</span> <span class="identifier">cbrt_noderiv</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// return cube root of x using bracket_and_solve (no derivatives).</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">std</span><span class="special">;</span> <span class="comment">// Help ADL of std functions.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span> <span class="comment">// For bracket_and_solve_root.</span>
<span class="keyword">int</span> <span class="identifier">exponent</span><span class="special">;</span>
<span class="identifier">frexp</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">exponent</span><span class="special">);</span> <span class="comment">// Get exponent of z (ignore mantissa).</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">1.</span><span class="special">,</span> <span class="identifier">exponent</span><span class="special">/</span><span class="number">3</span><span class="special">);</span> <span class="comment">// Rough guess is to divide the exponent by three.</span>
<span class="identifier">T</span> <span class="identifier">factor</span> <span class="special">=</span> <span class="number">2</span><span class="special">;</span> <span class="comment">// How big steps to take when searching.</span>
<span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">20</span><span class="special">;</span> <span class="comment">// Limit to maximum iterations.</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">maxit</span><span class="special">;</span> <span class="comment">// Initally our chosen max iterations, but updated with actual.</span>
<span class="keyword">bool</span> <span class="identifier">is_rising</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span> <span class="comment">// So if result if guess^3 is too low, then try increasing guess.</span>
<span class="keyword">int</span> <span class="identifier">digits</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span><span class="special">;</span> <span class="comment">// Maximum possible binary digits accuracy for type T.</span>
<span class="comment">// Some fraction of digits is used to control how accurate to try to make the result.</span>
<span class="keyword">int</span> <span class="identifier">get_digits</span> <span class="special">=</span> <span class="identifier">digits</span> <span class="special">-</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// We have to have a non-zero interval at each step, so</span>
<span class="comment">// maximum accuracy is digits - 1. But we also have to</span>
<span class="comment">// allow for inaccuracy in f(x), otherwise the last few</span>
<span class="comment">// iterations just thrash around.</span>
<span class="identifier">eps_tolerance</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">tol</span><span class="special">(</span><span class="identifier">get_digits</span><span class="special">);</span> <span class="comment">// Set the tolerance.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">bracket_and_solve_root</span><span class="special">(</span><span class="identifier">cbrt_functor_noderiv</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">),</span> <span class="identifier">guess</span><span class="special">,</span> <span class="identifier">factor</span><span class="special">,</span> <span class="identifier">is_rising</span><span class="special">,</span> <span class="identifier">tol</span><span class="special">,</span> <span class="identifier">it</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">first</span> <span class="special">+</span> <span class="special">(</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">second</span> <span class="special">-</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">first</span><span class="special">)/</span><span class="number">2</span><span class="special">;</span> <span class="comment">// Midway between brackets is our result, if necessary we could</span>
<span class="comment">// return the result as an interval here.</span>
<span class="special">}</span>
</pre>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top">
<p>
The final parameter specifying a maximum number of iterations is optional.
However, it defaults to <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span>
<span class="identifier">maxit</span> <span class="special">=</span>
<span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span><span class="special">&gt;::</span><span class="identifier">max</span><span class="special">)();</span></code> which is <code class="computeroutput"><span class="number">18446744073709551615</span></code>
and is more than anyone would wish to wait for!
</p>
<p>
So it may be wise to chose some reasonable estimate of how many iterations
may be needed, In this case the function is so well behaved that we can
chose a low value of 20.
</p>
<p>
Internally when Boost.Math uses these functions, it sets the maximum iterations
to <code class="computeroutput"><span class="identifier">policies</span><span class="special">::</span><span class="identifier">get_max_root_iterations</span><span class="special">&lt;</span><span class="identifier">Policy</span><span class="special">&gt;();</span></code>.
</p>
</td></tr>
</table></div>
<p>
Should we have wished we can show how many iterations were used in <code class="computeroutput"><span class="identifier">bracket_and_solve_root</span></code> (this information
is lost outside <code class="computeroutput"><span class="identifier">cbrt_noderiv</span></code>),
for example with:
</p>
<pre class="programlisting"><span class="keyword">if</span> <span class="special">(</span><span class="identifier">it</span> <span class="special">&gt;=</span> <span class="identifier">maxit</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"Unable to locate solution in "</span> <span class="special">&lt;&lt;</span> <span class="identifier">maxit</span> <span class="special">&lt;&lt;</span> <span class="string">" iterations:"</span>
<span class="string">" Current best guess is between "</span> <span class="special">&lt;&lt;</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">first</span> <span class="special">&lt;&lt;</span> <span class="string">" and "</span> <span class="special">&lt;&lt;</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">second</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">else</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"Converged after "</span> <span class="special">&lt;&lt;</span> <span class="identifier">it</span> <span class="special">&lt;&lt;</span> <span class="string">" (from maximum of "</span> <span class="special">&lt;&lt;</span> <span class="identifier">maxit</span> <span class="special">&lt;&lt;</span> <span class="string">" iterations)."</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
for output like
</p>
<pre class="programlisting"><span class="identifier">Converged</span> <span class="identifier">after</span> <span class="number">11</span> <span class="special">(</span><span class="identifier">from</span> <span class="identifier">maximum</span> <span class="identifier">of</span> <span class="number">20</span> <span class="identifier">iterations</span><span class="special">).</span>
</pre>
<p>
This snippet from <code class="computeroutput"><span class="identifier">main</span><span class="special">()</span></code>
in <a href="../../../../example/root_finding_example.cpp" target="_top">root_finding_example.cpp</a>
shows how it can be used.
</p>
<pre class="programlisting"><span class="keyword">try</span>
<span class="special">{</span>
<span class="keyword">double</span> <span class="identifier">threecubed</span> <span class="special">=</span> <span class="number">27.</span><span class="special">;</span> <span class="comment">// Value that has an *exactly representable* integer cube root.</span>
<span class="keyword">double</span> <span class="identifier">threecubedp1</span> <span class="special">=</span> <span class="number">28.</span><span class="special">;</span> <span class="comment">// Value whose cube root is *not* exactly representable.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"cbrt(28) "</span> <span class="special">&lt;&lt;</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">cbrt</span><span class="special">(</span><span class="number">28.</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> <span class="comment">// boost::math:: version of cbrt.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"std::cbrt(28) "</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cbrt</span><span class="special">(</span><span class="number">28.</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> <span class="comment">// std:: version of cbrt.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span><span class="string">" cast double "</span> <span class="special">&lt;&lt;</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="number">3.0365889718756625194208095785056696355814539772481111</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// Cube root using bracketing:</span>
<span class="keyword">double</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">cbrt_noderiv</span><span class="special">(</span><span class="identifier">threecubed</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"cbrt_noderiv("</span> <span class="special">&lt;&lt;</span> <span class="identifier">threecubed</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">r</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">r</span> <span class="special">=</span> <span class="identifier">cbrt_noderiv</span><span class="special">(</span><span class="identifier">threecubedp1</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"cbrt_noderiv("</span> <span class="special">&lt;&lt;</span> <span class="identifier">threecubedp1</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">r</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
</pre>
<pre class="programlisting"> cbrt_noderiv(27) = 3
cbrt_noderiv(28) = 3.0365889718756618
</pre>
<p>
The result of <code class="computeroutput"><span class="identifier">bracket_and_solve_root</span></code>
is a <a href="http://www.cplusplus.com/reference/utility/pair/" target="_top">pair</a>
of values that could be displayed.
</p>
<p>
The number of bits separating them can be found using <code class="computeroutput"><span class="identifier">float_distance</span><span class="special">(</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">first</span><span class="special">,</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">second</span><span class="special">)</span></code>. The distance is zero (closest representable)
for 3<sup>3</sup> = 27 but <code class="computeroutput"><span class="identifier">float_distance</span><span class="special">(</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">first</span><span class="special">,</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">second</span><span class="special">)</span> <span class="special">=</span> <span class="number">3</span></code>
for cube root of 28 with this function. The result (avoiding overflow) is
midway between these two values.
</p>
<h4>
<a name="math_toolkit.root_finding_examples.cbrt_eg.h1"></a>
<span class="phrase"><a name="math_toolkit.root_finding_examples.cbrt_eg.cbrt_1st_derivative"></a></span><a class="link" href="cbrt_eg.html#math_toolkit.root_finding_examples.cbrt_eg.cbrt_1st_derivative">Cube
root function with 1st derivative (slope)</a>
</h4>
<p>
We now solve the same problem, but using more information about the function,
to show how this can speed up finding the best estimate of the root.
</p>
<p>
For the root function, the 1st differential (the slope of the tangent to
a curve at any point) is known.
</p>
<p>
This algorithm is similar to this <a href="http://en.wikipedia.org/wiki/Nth_root_algorithm" target="_top">nth
root algorithm</a>.
</p>
<p>
If you need some reminders, then <a href="http://en.wikipedia.org/wiki/Derivative#Derivatives_of_elementary_functions" target="_top">derivatives
of elementary functions</a> may help.
</p>
<p>
Using the rule that the derivative of <span class="emphasis"><em>x<sup>n</sup></em></span> for positive
n (actually all nonzero n) is <span class="emphasis"><em>n x<sup>n-1</sup></em></span>, allows us to get
the 1st differential as <span class="emphasis"><em>3x<sup>2</sup></em></span>.
</p>
<p>
To see how this extra information is used to find a root, view <a href="http://en.wikipedia.org/wiki/Newton%27s_method" target="_top">Newton-Raphson
iterations</a> and the <a href="http://en.wikipedia.org/wiki/Newton%27s_method#mediaviewer/File:NewtonIteration_Ani.gif" target="_top">animation</a>.
</p>
<p>
We define a better functor <code class="computeroutput"><span class="identifier">cbrt_functor_deriv</span></code>
that returns both the evaluation of the function to solve, along with its
first derivative:
</p>
<p>
To '<span class="emphasis"><em>return</em></span>' two values, we use a <a href="http://en.cppreference.com/w/cpp/utility/pair" target="_top">std::pair</a>
of floating-point values.
</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">struct</span> <span class="identifier">cbrt_functor_deriv</span>
<span class="special">{</span> <span class="comment">// Functor also returning 1st derivative.</span>
<span class="identifier">cbrt_functor_deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">to_find_root_of</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">a</span><span class="special">(</span><span class="identifier">to_find_root_of</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">// Constructor stores value a to find root of,</span>
<span class="comment">// for example: calling cbrt_functor_deriv&lt;T&gt;(a) to use to get cube root of a.</span>
<span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Return both f(x) and f'(x).</span>
<span class="identifier">T</span> <span class="identifier">fx</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">*</span><span class="identifier">x</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="comment">// Difference (estimate x^3 - value).</span>
<span class="identifier">T</span> <span class="identifier">dx</span> <span class="special">=</span> <span class="number">3</span> <span class="special">*</span> <span class="identifier">x</span><span class="special">*</span><span class="identifier">x</span><span class="special">;</span> <span class="comment">// 1st derivative = 3x^2.</span>
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span><span class="identifier">fx</span><span class="special">,</span> <span class="identifier">dx</span><span class="special">);</span> <span class="comment">// 'return' both fx and dx.</span>
<span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="identifier">T</span> <span class="identifier">a</span><span class="special">;</span> <span class="comment">// Store value to be 'cube_rooted'.</span>
<span class="special">};</span>
</pre>
<p>
Our cube root function is now:
</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="identifier">T</span> <span class="identifier">cbrt_deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// return cube root of x using 1st derivative and Newton_Raphson.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">exponent</span><span class="special">;</span>
<span class="identifier">frexp</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">exponent</span><span class="special">);</span> <span class="comment">// Get exponent of z (ignore mantissa).</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">1.</span><span class="special">,</span> <span class="identifier">exponent</span><span class="special">/</span><span class="number">3</span><span class="special">);</span> <span class="comment">// Rough guess is to divide the exponent by three.</span>
<span class="identifier">T</span> <span class="identifier">min</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">0.5</span><span class="special">,</span> <span class="identifier">exponent</span><span class="special">/</span><span class="number">3</span><span class="special">);</span> <span class="comment">// Minimum possible value is half our guess.</span>
<span class="identifier">T</span> <span class="identifier">max</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">2.</span><span class="special">,</span> <span class="identifier">exponent</span><span class="special">/</span><span class="number">3</span><span class="special">);</span> <span class="comment">// Maximum possible value is twice our guess.</span>
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">digits</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span><span class="special">;</span> <span class="comment">// Maximum possible binary digits accuracy for type T.</span>
<span class="keyword">int</span> <span class="identifier">get_digits</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">digits</span> <span class="special">*</span> <span class="number">0.6</span><span class="special">);</span> <span class="comment">// Accuracy doubles with each step, so stop when we have</span>
<span class="comment">// just over half the digits correct.</span>
<span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">20</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">maxit</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">newton_raphson_iterate</span><span class="special">(</span><span class="identifier">cbrt_functor_deriv</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">),</span> <span class="identifier">guess</span><span class="special">,</span> <span class="identifier">min</span><span class="special">,</span> <span class="identifier">max</span><span class="special">,</span> <span class="identifier">get_digits</span><span class="special">,</span> <span class="identifier">it</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>
The result of <a href="../../../../../../libs/math/include/boost/math/tools/roots.hpp" target="_top"><code class="computeroutput"><span class="identifier">newton_raphson_iterate</span></code></a> function
is a single value.
</p>
<div class="tip"><table border="0" summary="Tip">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
<th align="left">Tip</th>
</tr>
<tr><td align="left" valign="top"><p>
There is a compromise between accuracy and speed when chosing the value
of <code class="computeroutput"><span class="identifier">digits</span></code>. It is tempting
to simply chose <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span></code>, but this may mean some inefficient
and unnecessary iterations as the function thrashes around trying to locate
the last bit. In theory, since the precision doubles with each step it
is sufficient to stop when half the bits are correct: as the last step
will have doubled that to full precision. Of course the function has no
way to tell if that is actually the case unless it does one more step to
be sure. In practice setting the precision to slightly more than <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span> <span class="special">/</span> <span class="number">2</span></code> is a good choice.
</p></td></tr>
</table></div>
<p>
Note that it is up to the caller of the function to check the iteration count
after the call to see if iteration stoped as a result of running out of iterations
rather than meeting the required precision.
</p>
<p>
Using the test data in <a href="../../../../test/test_cbrt.cpp" target="_top">/test/test_cbrt.cpp</a>
this found the cube root exact to the last digit in every case, and in no
more than 6 iterations at double precision. However, you will note that a
high precision was used in this example, exactly what was warned against
earlier on in these docs! In this particular case it is possible to compute
<span class="emphasis"><em>f(x)</em></span> exactly and without undue cancellation error, so
a high limit is not too much of an issue.
</p>
<p>
However, reducing the limit to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span> <span class="special">*</span> <span class="number">2</span> <span class="special">/</span> <span class="number">3</span></code>
gave full precision in all but one of the test cases (and that one was out
by just one bit). The maximum number of iterations remained 6, but in most
cases was reduced by one.
</p>
<p>
Note also that the above code omits a probable optimization by computing
z&#178;
and reusing it, omits error handling, and does not handle negative values
of z correctly. (These are left as the customary exercise for the reader!)
</p>
<p>
The <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">cbrt</span></code> function also includes these and other
improvements: most importantly it uses a much better initial guess which
reduces the iteration count to just 1 in almost all cases.
</p>
<h4>
<a name="math_toolkit.root_finding_examples.cbrt_eg.h2"></a>
<span class="phrase"><a name="math_toolkit.root_finding_examples.cbrt_eg.cbrt_2_derivatives"></a></span><a class="link" href="cbrt_eg.html#math_toolkit.root_finding_examples.cbrt_eg.cbrt_2_derivatives">Cube
root with 1st &amp; 2nd derivative (slope &amp; curvature)</a>
</h4>
<p>
Next we define yet another even better functor <code class="computeroutput"><span class="identifier">cbrt_functor_2deriv</span></code>
that returns both the evaluation of the function to solve, along with its
first <span class="bold"><strong>and second</strong></span> derivative:
</p>
<p>
&#8192;&#8192;<span class="emphasis"><em>f''(x) = 6x</em></span>
</p>
<p>
using information about both slope and curvature to speed convergence.
</p>
<p>
To <span class="emphasis"><em>'return'</em></span> three values, we use a <code class="computeroutput"><span class="identifier">tuple</span></code>
of three floating-point values:
</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">struct</span> <span class="identifier">cbrt_functor_2deriv</span>
<span class="special">{</span>
<span class="comment">// Functor returning both 1st and 2nd derivatives.</span>
<span class="identifier">cbrt_functor_2deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">to_find_root_of</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">a</span><span class="special">(</span><span class="identifier">to_find_root_of</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">// Constructor stores value a to find root of, for example:</span>
<span class="comment">// calling cbrt_functor_2deriv&lt;T&gt;(x) to get cube root of x,</span>
<span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Return both f(x) and f'(x) and f''(x).</span>
<span class="identifier">T</span> <span class="identifier">fx</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">*</span><span class="identifier">x</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="comment">// Difference (estimate x^3 - value).</span>
<span class="identifier">T</span> <span class="identifier">dx</span> <span class="special">=</span> <span class="number">3</span> <span class="special">*</span> <span class="identifier">x</span><span class="special">*</span><span class="identifier">x</span><span class="special">;</span> <span class="comment">// 1st derivative = 3x^2.</span>
<span class="identifier">T</span> <span class="identifier">d2x</span> <span class="special">=</span> <span class="number">6</span> <span class="special">*</span> <span class="identifier">x</span><span class="special">;</span> <span class="comment">// 2nd derivative = 6x.</span>
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">fx</span><span class="special">,</span> <span class="identifier">dx</span><span class="special">,</span> <span class="identifier">d2x</span><span class="special">);</span> <span class="comment">// 'return' fx, dx and d2x.</span>
<span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="identifier">T</span> <span class="identifier">a</span><span class="special">;</span> <span class="comment">// to be 'cube_rooted'.</span>
<span class="special">};</span>
</pre>
<p>
Our cube root function is now:
</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="identifier">T</span> <span class="identifier">cbrt_2deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// return cube root of x using 1st and 2nd derivatives and Halley.</span>
<span class="comment">//using namespace std; // Help ADL of std functions.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">exponent</span><span class="special">;</span>
<span class="identifier">frexp</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">exponent</span><span class="special">);</span> <span class="comment">// Get exponent of z (ignore mantissa).</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">1.</span><span class="special">,</span> <span class="identifier">exponent</span><span class="special">/</span><span class="number">3</span><span class="special">);</span> <span class="comment">// Rough guess is to divide the exponent by three.</span>
<span class="identifier">T</span> <span class="identifier">min</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">0.5</span><span class="special">,</span> <span class="identifier">exponent</span><span class="special">/</span><span class="number">3</span><span class="special">);</span> <span class="comment">// Minimum possible value is half our guess.</span>
<span class="identifier">T</span> <span class="identifier">max</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">2.</span><span class="special">,</span> <span class="identifier">exponent</span><span class="special">/</span><span class="number">3</span><span class="special">);</span> <span class="comment">// Maximum possible value is twice our guess.</span>
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">digits</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span><span class="special">;</span> <span class="comment">// Maximum possible binary digits accuracy for type T.</span>
<span class="comment">// digits used to control how accurate to try to make the result.</span>
<span class="keyword">int</span> <span class="identifier">get_digits</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">digits</span> <span class="special">*</span> <span class="number">0.4</span><span class="special">);</span> <span class="comment">// Accuracy triples with each step, so stop when just</span>
<span class="comment">// over one third of the digits are correct.</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">20</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">halley_iterate</span><span class="special">(</span><span class="identifier">cbrt_functor_2deriv</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">),</span> <span class="identifier">guess</span><span class="special">,</span> <span class="identifier">min</span><span class="special">,</span> <span class="identifier">max</span><span class="special">,</span> <span class="identifier">get_digits</span><span class="special">,</span> <span class="identifier">maxit</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>
The function <code class="computeroutput"><span class="identifier">halley_iterate</span></code>
also returns a single value, and the number of iterations will reveal if
it met the convergence criterion set by <code class="computeroutput"><span class="identifier">get_digits</span></code>.
</p>
<p>
The no-derivative method gives a result of
</p>
<pre class="programlisting"><span class="identifier">cbrt_noderiv</span><span class="special">(</span><span class="number">28</span><span class="special">)</span> <span class="special">=</span> <span class="number">3.0365889718756618</span>
</pre>
<p>
with a 3 bits distance between the bracketed values, whereas the derivative
methods both converge to a single value
</p>
<pre class="programlisting"><span class="identifier">cbrt_2deriv</span><span class="special">(</span><span class="number">28</span><span class="special">)</span> <span class="special">=</span> <span class="number">3.0365889718756627</span>
</pre>
<p>
which we can compare with the <a href="../../../../../../libs/math/doc/html/math_toolkit/powers/cbrt.html" target="_top">boost::math::cbrt</a>
</p>
<pre class="programlisting"><span class="identifier">cbrt</span><span class="special">(</span><span class="number">28</span><span class="special">)</span> <span class="special">=</span> <span class="number">3.0365889718756627</span>
</pre>
<p>
Note that the iterations are set to stop at just one-half of full precision,
and yet, even so, not one of the test cases had a single bit wrong. What's
more, the maximum number of iterations was now just 4.
</p>
<p>
Just to complete the picture, we could have called <a class="link" href="../roots_deriv.html#math_toolkit.roots_deriv.schroder"><code class="computeroutput"><span class="identifier">schroder_iterate</span></code></a> in the last example:
and in fact it makes no difference to the accuracy or number of iterations
in this particular case. However, the relative performance of these two methods
may vary depending upon the nature of <span class="emphasis"><em>f(x)</em></span>, and the
accuracy to which the initial guess can be computed. There appear to be no
generalisations that can be made except "try them and see".
</p>
<p>
Finally, had we called <code class="computeroutput"><span class="identifier">cbrt</span></code>
with <a href="http://shoup.net/ntl/doc/RR.txt" target="_top">NTL::RR</a> set to
1000 bit precision (about 300 decimal digits), then full precision can be
obtained with just 7 iterations. To put that in perspective, an increase
in precision by a factor of 20, has less than doubled the number of iterations.
That just goes to emphasise that most of the iterations are used up getting
the first few digits correct: after that these methods can churn out further
digits with remarkable efficiency.
</p>
<p>
Or to put it another way: <span class="emphasis"><em>nothing beats a really good initial guess!</em></span>
</p>
<p>
Full code of this example is at <a href="../../../../example/root_finding_example.cpp" target="_top">root_finding_example.cpp</a>,
</p>
</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; 2006-2010, 2012-2014, 2017 Nikhar
Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Johan R&#229;de, Gautam
Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg, Daryle Walker
and Xiaogang Zhang<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="../root_finding_examples.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="lambda.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,273 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>A More complex example - Inverting the Elliptic Integrals</title>
<link rel="stylesheet" href="../../math.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Math Toolkit 2.6.0">
<link rel="up" href="../root_finding_examples.html" title="Examples of Root-Finding (with and without derivatives)">
<link rel="prev" href="nth_root.html" title="Generalizing to Compute the nth root">
<link rel="next" href="../bad_guess.html" title="The Effect of a Poor Initial Guess">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="nth_root.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../bad_guess.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="math_toolkit.root_finding_examples.elliptic_eg"></a><a class="link" href="elliptic_eg.html" title="A More complex example - Inverting the Elliptic Integrals">A More
complex example - Inverting the Elliptic Integrals</a>
</h3></div></div></div>
<p>
The arc length of an ellipse with radii <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span>
is given by:
</p>
<pre class="programlisting">L(a, b) = 4aE(k)</pre>
<p>
with:
</p>
<pre class="programlisting">k = &#8730;(1 - b<sup>2</sup>/a<sup>2</sup>)</pre>
<p>
where <span class="emphasis"><em>E(k)</em></span> is the complete elliptic integral of the
second kind - see <a class="link" href="../ellint/ellint_2.html" title="Elliptic Integrals of the Second Kind - Legendre Form">ellint_2</a>.
</p>
<p>
Let's suppose we know the arc length and one radii, we can then calculate
the other radius by inverting the formula above. We'll begin by encoding
the above formula into a functor that our root-finding algorithms can call.
</p>
<p>
Note that while not completely obvious from the formula above, the function
is completely symmetrical in the two radii - which can be interchanged at
will - in this case we need to make sure that <code class="computeroutput"><span class="identifier">a</span>
<span class="special">&gt;=</span> <span class="identifier">b</span></code>
so that we don't accidentally take the square root of a negative number:
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">=</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">elliptic_root_functor_noderiv</span>
<span class="special">{</span> <span class="comment">// Nth root of x using only function - no derivatives.</span>
<span class="identifier">elliptic_root_functor_noderiv</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">arc</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">radius</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">m_arc</span><span class="special">(</span><span class="identifier">arc</span><span class="special">),</span> <span class="identifier">m_radius</span><span class="special">(</span><span class="identifier">radius</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">// Constructor just stores value a to find root of.</span>
<span class="special">}</span>
<span class="identifier">T</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">;</span>
<span class="comment">// return the difference between required arc-length, and the calculated arc-length for an</span>
<span class="comment">// ellipse with radii m_radius and x:</span>
<span class="identifier">T</span> <span class="identifier">a</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">max</span><span class="special">)(</span><span class="identifier">m_radius</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">b</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">min</span><span class="special">)(</span><span class="identifier">m_radius</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">k</span> <span class="special">=</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="number">1</span> <span class="special">-</span> <span class="identifier">b</span> <span class="special">*</span> <span class="identifier">b</span> <span class="special">/</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="keyword">return</span> <span class="number">4</span> <span class="special">*</span> <span class="identifier">a</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">ellint_2</span><span class="special">(</span><span class="identifier">k</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">m_arc</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="identifier">T</span> <span class="identifier">m_arc</span><span class="special">;</span> <span class="comment">// length of arc.</span>
<span class="identifier">T</span> <span class="identifier">m_radius</span><span class="special">;</span> <span class="comment">// one of the two radii of the ellipse</span>
<span class="special">};</span> <span class="comment">// template &lt;class T&gt; struct elliptic_root_functor_noderiv</span>
</pre>
<p>
We'll also need a decent estimate to start searching from, the approximation:
</p>
<pre class="programlisting">L(a, b) &#8776; 4&#8730;(a<sup>2</sup> + b<sup>2</sup>)</pre>
<p>
Is easily inverted to give us what we need, which using derivative-free root
finding leads to the algorithm:
</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">=</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="identifier">T</span> <span class="identifier">elliptic_root_noderiv</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">radius</span><span class="special">,</span> <span class="identifier">T</span> <span class="identifier">arc</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">// return the other radius of an ellipse, given one radii and the arc-length</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">std</span><span class="special">;</span> <span class="comment">// Help ADL of std functions.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span> <span class="comment">// For bracket_and_solve_root.</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="identifier">arc</span> <span class="special">*</span> <span class="identifier">arc</span> <span class="special">/</span> <span class="number">16</span> <span class="special">-</span> <span class="identifier">radius</span> <span class="special">*</span> <span class="identifier">radius</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">factor</span> <span class="special">=</span> <span class="number">1.2</span><span class="special">;</span> <span class="comment">// How big steps to take when searching.</span>
<span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">50</span><span class="special">;</span> <span class="comment">// Limit to maximum iterations.</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">maxit</span><span class="special">;</span> <span class="comment">// Initally our chosen max iterations, but updated with actual.</span>
<span class="keyword">bool</span> <span class="identifier">is_rising</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span> <span class="comment">// arc-length increases if one radii increases, so function is rising</span>
<span class="comment">// Define a termination condition, stop when nearly all digits are correct, but allow for</span>
<span class="comment">// the fact that we are returning a range, and must have some inaccuracy in the elliptic integral:</span>
<span class="identifier">eps_tolerance</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">tol</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span> <span class="special">-</span> <span class="number">2</span><span class="special">);</span>
<span class="comment">// Call bracket_and_solve_root to find the solution, note that this is a rising function:</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">bracket_and_solve_root</span><span class="special">(</span><span class="identifier">elliptic_root_functor_noderiv</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">arc</span><span class="special">,</span> <span class="identifier">radius</span><span class="special">),</span> <span class="identifier">guess</span><span class="special">,</span> <span class="identifier">factor</span><span class="special">,</span> <span class="identifier">is_rising</span><span class="special">,</span> <span class="identifier">tol</span><span class="special">,</span> <span class="identifier">it</span><span class="special">);</span>
<span class="comment">// Result is midway between the endpoints of the range:</span>
<span class="keyword">return</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">first</span> <span class="special">+</span> <span class="special">(</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">second</span> <span class="special">-</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">first</span><span class="special">)</span> <span class="special">/</span> <span class="number">2</span><span class="special">;</span>
<span class="special">}</span> <span class="comment">// template &lt;class T&gt; T elliptic_root_noderiv(T x)</span>
</pre>
<p>
This function generally finds the root within 8-10 iterations, so given that
the runtime is completely dominated by the cost of calling the ellliptic
integral it would be nice to reduce that count somewhat. We'll try to do
that by using a derivative-based method; the derivatives of this function
are rather hard to work out by hand, but fortunately <a href="http://www.wolframalpha.com/input/?i=d%2Fda+%5b4+*+a+*+EllipticE%281+-+b%5e2%2Fa%5e2%29%5d" target="_top">Wolfram
Alpha</a> can do the grunt work for us to give:
</p>
<pre class="programlisting">d/da L(a, b) = 4(a<sup>2</sup>E(k) - b<sup>2</sup>K(k)) / (a<sup>2</sup> - b<sup>2</sup>)</pre>
<p>
Note that now we have <span class="bold"><strong>two</strong></span> elliptic integral
calls to get the derivative, so our functor will be at least twice as expensive
to call as the derivative-free one above: we'll have to reduce the iteration
count quite substantially to make a difference!
</p>
<p>
Here's the revised functor:
</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">=</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">elliptic_root_functor_1deriv</span>
<span class="special">{</span> <span class="comment">// Functor also returning 1st derviative.</span>
<span class="identifier">BOOST_STATIC_ASSERT_MSG</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_integral</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">,</span> <span class="string">"Only floating-point type types can be used!"</span><span class="special">);</span>
<span class="identifier">elliptic_root_functor_1deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">arc</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">radius</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">m_arc</span><span class="special">(</span><span class="identifier">arc</span><span class="special">),</span> <span class="identifier">m_radius</span><span class="special">(</span><span class="identifier">radius</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">// Constructor just stores value a to find root of.</span>
<span class="special">}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">;</span>
<span class="comment">// Return the difference between required arc-length, and the calculated arc-length for an</span>
<span class="comment">// ellipse with radii m_radius and x, plus it's derivative.</span>
<span class="comment">// See http://www.wolframalpha.com/input/?i=d%2Fda+[4+*+a+*+EllipticE%281+-+b^2%2Fa^2%29]</span>
<span class="comment">// We require two elliptic integral calls, but from these we can calculate both</span>
<span class="comment">// the function and it's derivative:</span>
<span class="identifier">T</span> <span class="identifier">a</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">max</span><span class="special">)(</span><span class="identifier">m_radius</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">b</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">min</span><span class="special">)(</span><span class="identifier">m_radius</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">a2</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">T</span> <span class="identifier">b2</span> <span class="special">=</span> <span class="identifier">b</span> <span class="special">*</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">k</span> <span class="special">=</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="number">1</span> <span class="special">-</span> <span class="identifier">b2</span> <span class="special">/</span> <span class="identifier">a2</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">Ek</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">ellint_2</span><span class="special">(</span><span class="identifier">k</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">Kk</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">ellint_1</span><span class="special">(</span><span class="identifier">k</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">fx</span> <span class="special">=</span> <span class="number">4</span> <span class="special">*</span> <span class="identifier">a</span> <span class="special">*</span> <span class="identifier">Ek</span> <span class="special">-</span> <span class="identifier">m_arc</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">dfx</span> <span class="special">=</span> <span class="number">4</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a2</span> <span class="special">*</span> <span class="identifier">Ek</span> <span class="special">-</span> <span class="identifier">b2</span> <span class="special">*</span> <span class="identifier">Kk</span><span class="special">)</span> <span class="special">/</span> <span class="special">(</span><span class="identifier">a2</span> <span class="special">-</span> <span class="identifier">b2</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span><span class="identifier">fx</span><span class="special">,</span> <span class="identifier">dfx</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="identifier">T</span> <span class="identifier">m_arc</span><span class="special">;</span> <span class="comment">// length of arc.</span>
<span class="identifier">T</span> <span class="identifier">m_radius</span><span class="special">;</span> <span class="comment">// one of the two radii of the ellipse</span>
<span class="special">};</span> <span class="comment">// struct elliptic_root__functor_1deriv</span>
</pre>
<p>
The root-finding code is now almost the same as before, but we'll make use
of Newton-iteration to get the result:
</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">=</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="identifier">T</span> <span class="identifier">elliptic_root_1deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">radius</span><span class="special">,</span> <span class="identifier">T</span> <span class="identifier">arc</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">std</span><span class="special">;</span> <span class="comment">// Help ADL of std functions.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span> <span class="comment">// For newton_raphson_iterate.</span>
<span class="identifier">BOOST_STATIC_ASSERT_MSG</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_integral</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">,</span> <span class="string">"Only floating-point type types can be used!"</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="identifier">arc</span> <span class="special">*</span> <span class="identifier">arc</span> <span class="special">/</span> <span class="number">16</span> <span class="special">-</span> <span class="identifier">radius</span> <span class="special">*</span> <span class="identifier">radius</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">min</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="comment">// Minimum possible value is zero.</span>
<span class="identifier">T</span> <span class="identifier">max</span> <span class="special">=</span> <span class="identifier">arc</span><span class="special">;</span> <span class="comment">// Maximum possible value is the arc length.</span>
<span class="comment">// Accuracy doubles at each step, so stop when just over half of the digits are</span>
<span class="comment">// correct, and rely on that step to polish off the remainder:</span>
<span class="keyword">int</span> <span class="identifier">get_digits</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span> <span class="special">*</span> <span class="number">0.6</span><span class="special">);</span>
<span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">20</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">maxit</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">newton_raphson_iterate</span><span class="special">(</span><span class="identifier">elliptic_root_functor_1deriv</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">arc</span><span class="special">,</span> <span class="identifier">radius</span><span class="special">),</span> <span class="identifier">guess</span><span class="special">,</span> <span class="identifier">min</span><span class="special">,</span> <span class="identifier">max</span><span class="special">,</span> <span class="identifier">get_digits</span><span class="special">,</span> <span class="identifier">it</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
<span class="special">}</span> <span class="comment">// T elliptic_root_1_deriv Newton-Raphson</span>
</pre>
<p>
The number of iterations required for <code class="computeroutput"><span class="keyword">double</span></code>
precision is now usually around 4 - so we've slightly more than halved the
number of iterations, but made the functor twice as expensive to call!
</p>
<p>
Interestingly though, the second derivative requires no more expensive elliptic
integral calls than the first does, in other words it comes essentially "for
free", in which case we might as well make use of it and use Halley-iteration.
This is quite a typical situation when inverting special-functions. Here's
the revised functor:
</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">=</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">elliptic_root_functor_2deriv</span>
<span class="special">{</span> <span class="comment">// Functor returning both 1st and 2nd derivatives.</span>
<span class="identifier">BOOST_STATIC_ASSERT_MSG</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_integral</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">,</span> <span class="string">"Only floating-point type types can be used!"</span><span class="special">);</span>
<span class="identifier">elliptic_root_functor_2deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">arc</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">radius</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">m_arc</span><span class="special">(</span><span class="identifier">arc</span><span class="special">),</span> <span class="identifier">m_radius</span><span class="special">(</span><span class="identifier">radius</span><span class="special">)</span> <span class="special">{}</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">sqrt</span><span class="special">;</span>
<span class="comment">// Return the difference between required arc-length, and the calculated arc-length for an</span>
<span class="comment">// ellipse with radii m_radius and x, plus it's derivative.</span>
<span class="comment">// See http://www.wolframalpha.com/input/?i=d^2%2Fda^2+[4+*+a+*+EllipticE%281+-+b^2%2Fa^2%29]</span>
<span class="comment">// for the second derivative.</span>
<span class="identifier">T</span> <span class="identifier">a</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">max</span><span class="special">)(</span><span class="identifier">m_radius</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">b</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">min</span><span class="special">)(</span><span class="identifier">m_radius</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">a2</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">T</span> <span class="identifier">b2</span> <span class="special">=</span> <span class="identifier">b</span> <span class="special">*</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">k</span> <span class="special">=</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="number">1</span> <span class="special">-</span> <span class="identifier">b2</span> <span class="special">/</span> <span class="identifier">a2</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">Ek</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">ellint_2</span><span class="special">(</span><span class="identifier">k</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">Kk</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">ellint_1</span><span class="special">(</span><span class="identifier">k</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">fx</span> <span class="special">=</span> <span class="number">4</span> <span class="special">*</span> <span class="identifier">a</span> <span class="special">*</span> <span class="identifier">Ek</span> <span class="special">-</span> <span class="identifier">m_arc</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">dfx</span> <span class="special">=</span> <span class="number">4</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a2</span> <span class="special">*</span> <span class="identifier">Ek</span> <span class="special">-</span> <span class="identifier">b2</span> <span class="special">*</span> <span class="identifier">Kk</span><span class="special">)</span> <span class="special">/</span> <span class="special">(</span><span class="identifier">a2</span> <span class="special">-</span> <span class="identifier">b2</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">dfx2</span> <span class="special">=</span> <span class="number">4</span> <span class="special">*</span> <span class="identifier">b2</span> <span class="special">*</span> <span class="special">((</span><span class="identifier">a2</span> <span class="special">+</span> <span class="identifier">b2</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">Kk</span> <span class="special">-</span> <span class="number">2</span> <span class="special">*</span> <span class="identifier">a2</span> <span class="special">*</span> <span class="identifier">Ek</span><span class="special">)</span> <span class="special">/</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a2</span> <span class="special">-</span> <span class="identifier">b2</span><span class="special">)</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">a2</span> <span class="special">-</span> <span class="identifier">b2</span><span class="special">));</span>
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">fx</span><span class="special">,</span> <span class="identifier">dfx</span><span class="special">,</span> <span class="identifier">dfx2</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="identifier">T</span> <span class="identifier">m_arc</span><span class="special">;</span> <span class="comment">// length of arc.</span>
<span class="identifier">T</span> <span class="identifier">m_radius</span><span class="special">;</span> <span class="comment">// one of the two radii of the ellipse</span>
<span class="special">};</span>
</pre>
<p>
The actual root-finding code is almost the same as before, except we can
use Halley, rather than Newton iteration:
</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">=</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="identifier">T</span> <span class="identifier">elliptic_root_2deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">radius</span><span class="special">,</span> <span class="identifier">T</span> <span class="identifier">arc</span><span class="special">)</span>
<span class="special">{</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">std</span><span class="special">;</span> <span class="comment">// Help ADL of std functions.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span> <span class="comment">// For halley_iterate.</span>
<span class="identifier">BOOST_STATIC_ASSERT_MSG</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_integral</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">,</span> <span class="string">"Only floating-point type types can be used!"</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="identifier">arc</span> <span class="special">*</span> <span class="identifier">arc</span> <span class="special">/</span> <span class="number">16</span> <span class="special">-</span> <span class="identifier">radius</span> <span class="special">*</span> <span class="identifier">radius</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">min</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="comment">// Minimum possible value is zero.</span>
<span class="identifier">T</span> <span class="identifier">max</span> <span class="special">=</span> <span class="identifier">arc</span><span class="special">;</span> <span class="comment">// radius can't be larger than the arc length.</span>
<span class="comment">// Accuracy triples at each step, so stop when just over one-third of the digits</span>
<span class="comment">// are correct, and the last iteration will polish off the remaining digits:</span>
<span class="keyword">int</span> <span class="identifier">get_digits</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span> <span class="special">*</span> <span class="number">0.4</span><span class="special">);</span>
<span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">20</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">maxit</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">halley_iterate</span><span class="special">(</span><span class="identifier">elliptic_root_functor_2deriv</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">arc</span><span class="special">,</span> <span class="identifier">radius</span><span class="special">),</span> <span class="identifier">guess</span><span class="special">,</span> <span class="identifier">min</span><span class="special">,</span> <span class="identifier">max</span><span class="special">,</span> <span class="identifier">get_digits</span><span class="special">,</span> <span class="identifier">it</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
<span class="special">}</span> <span class="comment">// nth_2deriv Halley</span>
</pre>
<p>
While this function uses only slightly fewer iterations (typically around
3) to find the root, compared to the original derivative-free method, we've
moved from 8-10 elliptic integral calls to 6.
</p>
<p>
Full code of this example is at <a href="../../../../example/root_elliptic_finding.cpp" target="_top">root_elliptic_finding.cpp</a>.
</p>
</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; 2006-2010, 2012-2014, 2017 Nikhar
Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Johan R&#229;de, Gautam
Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg, Daryle Walker
and Xiaogang Zhang<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="nth_root.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../bad_guess.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,79 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Using C++11 Lambda's</title>
<link rel="stylesheet" href="../../math.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Math Toolkit 2.6.0">
<link rel="up" href="../root_finding_examples.html" title="Examples of Root-Finding (with and without derivatives)">
<link rel="prev" href="cbrt_eg.html" title="Finding the Cubed Root With and Without Derivatives">
<link rel="next" href="5th_root_eg.html" title="Computing the Fifth Root">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="cbrt_eg.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="5th_root_eg.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="math_toolkit.root_finding_examples.lambda"></a><a class="link" href="lambda.html" title="Using C++11 Lambda's">Using C++11
Lambda's</a>
</h3></div></div></div>
<p>
Since all the root finding functions accept a function-object, they can be
made to work (often in a lot less code) with C++11 lambda's. Here's the much
reduced code for our "toy" cube root function:
</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="identifier">T</span> <span class="identifier">cbrt_2deriv_lambda</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// return cube root of x using 1st and 2nd derivatives and Halley.</span>
<span class="comment">//using namespace std; // Help ADL of std functions.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">exponent</span><span class="special">;</span>
<span class="identifier">frexp</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">exponent</span><span class="special">);</span> <span class="comment">// Get exponent of z (ignore mantissa).</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">1.</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// Rough guess is to divide the exponent by three.</span>
<span class="identifier">T</span> <span class="identifier">min</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">0.5</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// Minimum possible value is half our guess.</span>
<span class="identifier">T</span> <span class="identifier">max</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">2.</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// Maximum possible value is twice our guess.</span>
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">digits</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span><span class="special">;</span> <span class="comment">// Maximum possible binary digits accuracy for type T.</span>
<span class="comment">// digits used to control how accurate to try to make the result.</span>
<span class="keyword">int</span> <span class="identifier">get_digits</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">digits</span> <span class="special">*</span> <span class="number">0.4</span><span class="special">);</span> <span class="comment">// Accuracy triples with each step, so stop when just</span>
<span class="comment">// over one third of the digits are correct.</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">20</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">halley_iterate</span><span class="special">(</span>
<span class="comment">// lambda function:</span>
<span class="special">[</span><span class="identifier">x</span><span class="special">](</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">g</span><span class="special">){</span> <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">g</span> <span class="special">*</span> <span class="identifier">g</span> <span class="special">*</span> <span class="identifier">g</span> <span class="special">-</span> <span class="identifier">x</span><span class="special">,</span> <span class="number">3</span> <span class="special">*</span> <span class="identifier">g</span> <span class="special">*</span> <span class="identifier">g</span><span class="special">,</span> <span class="number">6</span> <span class="special">*</span> <span class="identifier">g</span><span class="special">);</span> <span class="special">},</span>
<span class="identifier">guess</span><span class="special">,</span> <span class="identifier">min</span><span class="special">,</span> <span class="identifier">max</span><span class="special">,</span> <span class="identifier">get_digits</span><span class="special">,</span> <span class="identifier">maxit</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>
Full code of this example is at <a href="../../../../example/root_finding_example.cpp" target="_top">root_finding_example.cpp</a>,
</p>
</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; 2006-2010, 2012-2014, 2017 Nikhar
Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Johan R&#229;de, Gautam
Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg, Daryle Walker
and Xiaogang Zhang<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="cbrt_eg.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="5th_root_eg.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,291 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Root-finding using Boost.Multiprecision</title>
<link rel="stylesheet" href="../../math.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Math Toolkit 2.6.0">
<link rel="up" href="../root_finding_examples.html" title="Examples of Root-Finding (with and without derivatives)">
<link rel="prev" href="5th_root_eg.html" title="Computing the Fifth Root">
<link rel="next" href="nth_root.html" title="Generalizing to Compute the nth root">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="5th_root_eg.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="nth_root.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="math_toolkit.root_finding_examples.multiprecision_root"></a><a class="link" href="multiprecision_root.html" title="Root-finding using Boost.Multiprecision">Root-finding
using Boost.Multiprecision</a>
</h3></div></div></div>
<p>
The apocryphally astute reader might, by now, be asking "How do we know
if this computes the 'right' answer?".
</p>
<p>
For most values, there is, sadly, no 'right' answer. This is because values
can only rarely be <span class="emphasis"><em>exactly represented</em></span> by C++ floating-point
types. What we do want is the 'best' representation - one that is the nearest
<a href="http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding" target="_top">representable</a>
value. (For more about how numbers are represented see <a href="http://en.wikipedia.org/wiki/Floating_point" target="_top">Floating
point</a>).
</p>
<p>
Of course, we might start with finding an external reference source like
<a href="http://www.wolframalpha.com/" target="_top">Wolfram Alpha</a>, as above,
but this is not always possible.
</p>
<p>
Another way to reassure is to compute 'reference' values at higher precision
with which to compare the results of our iterative computations using built-in
like <code class="computeroutput"><span class="keyword">double</span></code>. They should agree
within the tolerance that was set.
</p>
<p>
The result of <code class="computeroutput"><span class="keyword">static_cast</span></code>ing
to <code class="computeroutput"><span class="keyword">double</span></code> from a higher-precision
type like <code class="computeroutput"><span class="identifier">cpp_bin_float_50</span></code>
is guaranteed to be the <span class="bold"><strong>nearest representable</strong></span>
<code class="computeroutput"><span class="keyword">double</span></code> value.
</p>
<p>
For example, the cube root functions in our example for <code class="computeroutput"><span class="identifier">cbrt</span><span class="special">(</span><span class="number">28.</span><span class="special">)</span></code>
compute
</p>
<p>
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cbrt</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="number">28.</span><span class="special">)</span> <span class="special">=</span>
<span class="number">3.0365889718756627</span></code>
</p>
<p>
WolframAlpha says <code class="computeroutput"><span class="number">3.036588971875662519420809578505669635581453977248111123242141</span><span class="special">...</span></code>
</p>
<p>
<code class="computeroutput"><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;(</span><span class="number">3.03658897187566251942080957850</span><span class="special">)</span>
<span class="special">=</span> <span class="number">3.0365889718756627</span></code>
</p>
<p>
This example <code class="computeroutput"><span class="identifier">cbrt</span><span class="special">(</span><span class="number">28.</span><span class="special">)</span> <span class="special">=</span>
<span class="number">3.0365889718756627</span></code>
</p>
<div class="tip"><table border="0" summary="Tip">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
<th align="left">Tip</th>
</tr>
<tr><td align="left" valign="top">
<p>
To ensure that all potentially significant decimal digits are displayed
use <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">max_digits10</span></code> (or if not available on
older platforms or compilers use <code class="computeroutput"><span class="number">2</span><span class="special">+</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;::</span><span class="identifier">digits</span><span class="special">*</span><span class="number">3010</span><span class="special">/</span><span class="number">10000</span></code>).<br>
</p>
<p>
Ideally, values should agree to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">-</span><span class="identifier">limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits10</span></code>
decimal digits.
</p>
<p>
This also means that a 'reference' value to be <span class="bold"><strong>input</strong></span>
or <code class="computeroutput"><span class="keyword">static_cast</span></code> should have
at least <code class="computeroutput"><span class="identifier">max_digits10</span></code> decimal
digits (17 for 64-bit <code class="computeroutput"><span class="keyword">double</span></code>).
</p>
</td></tr>
</table></div>
<p>
If we wish to compute <span class="bold"><strong>higher-precision values</strong></span>
then, on some platforms, we may be able to use <code class="computeroutput"><span class="keyword">long</span>
<span class="keyword">double</span></code> with a higher precision than
<code class="computeroutput"><span class="keyword">double</span></code> to compare with the very
common <code class="computeroutput"><span class="keyword">double</span></code> and/or a more
efficient built-in quad floating-point type like <code class="computeroutput"><span class="identifier">__float128</span></code>.
</p>
<p>
Almost all platforms can easily use <a href="../../../../../../libs/multiprecision/doc/html/index.html" target="_top">Boost.Multiprecision</a>,
for example, <a href="../../../../../../libs/multiprecision/doc/html/boost_multiprecision/tut/floats/cpp_dec_float.html" target="_top">cpp_dec_float</a>
or a binary type <a href="../../../../../../libs/multiprecision/doc/html/boost_multiprecision/tut/floats/cpp_bin_float.html" target="_top">cpp_bin_float</a>
types, to compute values at very much higher precision.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
With multiprecision types, it is debatable whether to use the type <code class="computeroutput"><span class="identifier">T</span></code> for computing the initial guesses.
Type <code class="computeroutput"><span class="keyword">double</span></code> is like to be
accurate enough for the method used in these examples. This would limit
the exponent range of possible values to that of <code class="computeroutput"><span class="keyword">double</span></code>.
There is also the cost of conversion to and from type <code class="computeroutput"><span class="identifier">T</span></code>
to consider. In these examples, <code class="computeroutput"><span class="keyword">double</span></code>
is used via <code class="computeroutput"><span class="keyword">typedef</span> <span class="keyword">double</span>
<span class="identifier">guess_type</span></code>.
</p></td></tr>
</table></div>
<p>
Since the functors and functions used above are templated on the value type,
we can very simply use them with any of the <a href="../../../../../../libs/multiprecision/doc/html/index.html" target="_top">Boost.Multiprecision</a>
types. As a reminder, here's our toy cube root function using 2 derivatives
and C++11 lambda functions to find the root:
</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="identifier">T</span> <span class="identifier">cbrt_2deriv_lambda</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// return cube root of x using 1st and 2nd derivatives and Halley.</span>
<span class="comment">//using namespace std; // Help ADL of std functions.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">exponent</span><span class="special">;</span>
<span class="identifier">frexp</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">exponent</span><span class="special">);</span> <span class="comment">// Get exponent of z (ignore mantissa).</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">1.</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// Rough guess is to divide the exponent by three.</span>
<span class="identifier">T</span> <span class="identifier">min</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">0.5</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// Minimum possible value is half our guess.</span>
<span class="identifier">T</span> <span class="identifier">max</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="number">2.</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="number">3</span><span class="special">);</span> <span class="comment">// Maximum possible value is twice our guess.</span>
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">digits</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span><span class="special">;</span> <span class="comment">// Maximum possible binary digits accuracy for type T.</span>
<span class="comment">// digits used to control how accurate to try to make the result.</span>
<span class="keyword">int</span> <span class="identifier">get_digits</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="identifier">digits</span> <span class="special">*</span> <span class="number">0.4</span><span class="special">);</span> <span class="comment">// Accuracy triples with each step, so stop when just</span>
<span class="comment">// over one third of the digits are correct.</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">20</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">halley_iterate</span><span class="special">(</span>
<span class="comment">// lambda function:</span>
<span class="special">[</span><span class="identifier">x</span><span class="special">](</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">g</span><span class="special">){</span> <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">g</span> <span class="special">*</span> <span class="identifier">g</span> <span class="special">*</span> <span class="identifier">g</span> <span class="special">-</span> <span class="identifier">x</span><span class="special">,</span> <span class="number">3</span> <span class="special">*</span> <span class="identifier">g</span> <span class="special">*</span> <span class="identifier">g</span><span class="special">,</span> <span class="number">6</span> <span class="special">*</span> <span class="identifier">g</span><span class="special">);</span> <span class="special">},</span>
<span class="identifier">guess</span><span class="special">,</span> <span class="identifier">min</span><span class="special">,</span> <span class="identifier">max</span><span class="special">,</span> <span class="identifier">get_digits</span><span class="special">,</span> <span class="identifier">maxit</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>
Some examples below are 50 decimal digit decimal and binary types (and on
some platforms a much faster <code class="computeroutput"><span class="identifier">float128</span></code>
or <code class="computeroutput"><span class="identifier">quad_float</span></code> type ) that
we can use with these includes:
</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">cpp_bin_float</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// For cpp_bin_float_50.</span>
<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">cpp_dec_float</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// For cpp_dec_float_50.</span>
<span class="preprocessor">#ifndef</span> <span class="identifier">_MSC_VER</span> <span class="comment">// float128 is not yet supported by Microsoft compiler at 2013.</span>
<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">float128</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span> <span class="comment">// Requires libquadmath.</span>
<span class="preprocessor">#endif</span>
</pre>
<p>
Some using statements simplify their use:
</p>
<pre class="programlisting"> <span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">cpp_dec_float_50</span><span class="special">;</span> <span class="comment">// decimal.</span>
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">cpp_bin_float_50</span><span class="special">;</span> <span class="comment">// binary.</span>
<span class="preprocessor">#ifndef</span> <span class="identifier">_MSC_VER</span> <span class="comment">// Not supported by Microsoft compiler.</span>
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">float128</span><span class="special">;</span>
<span class="preprocessor">#endif</span>
</pre>
<p>
They can be used thus:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">.</span><span class="identifier">precision</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">cpp_dec_float_50</span><span class="special">&gt;::</span><span class="identifier">digits10</span><span class="special">);</span>
<span class="identifier">cpp_dec_float_50</span> <span class="identifier">two</span> <span class="special">=</span> <span class="number">2</span><span class="special">;</span> <span class="comment">// </span>
<span class="identifier">cpp_dec_float_50</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">cbrt_2deriv</span><span class="special">(</span><span class="identifier">two</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"cbrt("</span> <span class="special">&lt;&lt;</span> <span class="identifier">two</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">r</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">r</span> <span class="special">=</span> <span class="identifier">cbrt_2deriv</span><span class="special">(</span><span class="number">2.</span><span class="special">);</span> <span class="comment">// Passing a double, so ADL will compute a double precision result.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"cbrt("</span> <span class="special">&lt;&lt;</span> <span class="identifier">two</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">r</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// cbrt(2) = 1.2599210498948731906665443602832965552806854248047 'wrong' from digits 17 onwards!</span>
<span class="identifier">r</span> <span class="special">=</span> <span class="identifier">cbrt_2deriv</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">cpp_dec_float_50</span><span class="special">&gt;(</span><span class="number">2.</span><span class="special">));</span> <span class="comment">// Passing a cpp_dec_float_50, </span>
<span class="comment">// so will compute a cpp_dec_float_50 precision result.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"cbrt("</span> <span class="special">&lt;&lt;</span> <span class="identifier">two</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">r</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">r</span> <span class="special">=</span> <span class="identifier">cbrt_2deriv</span><span class="special">&lt;</span><span class="identifier">cpp_dec_float_50</span><span class="special">&gt;(</span><span class="number">2.</span><span class="special">);</span> <span class="comment">// Explictly a cpp_dec_float_50, so will compute a cpp_dec_float_50 precision result.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"cbrt("</span> <span class="special">&lt;&lt;</span> <span class="identifier">two</span> <span class="special">&lt;&lt;</span> <span class="string">") = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">r</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="comment">// cpp_dec_float_50 1.2599210498948731647672106072782283505702514647015</span>
</pre>
<p>
A reference value computed by <a href="http://www.wolframalpha.com/" target="_top">Wolfram
Alpha</a> is
</p>
<pre class="programlisting"><span class="identifier">N</span><span class="special">[</span><span class="number">2</span><span class="special">^(</span><span class="number">1</span><span class="special">/</span><span class="number">3</span><span class="special">),</span> <span class="number">50</span><span class="special">]</span> <span class="number">1.2599210498948731647672106072782283505702514647015</span>
</pre>
<p>
which agrees exactly.
</p>
<p>
To <span class="bold"><strong>show</strong></span> values to their full precision,
it is necessary to adjust the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span></code>
<code class="computeroutput"><span class="identifier">precision</span></code> to suit the type,
for example:
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="identifier">T</span> <span class="identifier">show_cube_root</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">value</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">// Demonstrate by printing the root using all definitely significant digits.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">.</span><span class="identifier">precision</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits10</span><span class="special">);</span>
<span class="identifier">T</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">cbrt_2deriv</span><span class="special">(</span><span class="identifier">value</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"value = "</span> <span class="special">&lt;&lt;</span> <span class="identifier">value</span> <span class="special">&lt;&lt;</span> <span class="string">", cube root ="</span> <span class="special">&lt;&lt;</span> <span class="identifier">r</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="keyword">return</span> <span class="identifier">r</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<pre class="programlisting"><span class="identifier">show_cube_root</span><span class="special">(</span><span class="number">2.</span><span class="special">);</span>
<span class="identifier">show_cube_root</span><span class="special">(</span><span class="number">2.L</span><span class="special">);</span>
<span class="identifier">show_cube_root</span><span class="special">(</span><span class="identifier">two</span><span class="special">);</span>
</pre>
<p>
which outputs:
</p>
<pre class="programlisting">cbrt(2) = 1.2599210498948731647672106072782283505702514647015
value = 2, cube root =1.25992104989487
value = 2, cube root =1.25992104989487
value = 2, cube root =1.2599210498948731647672106072782283505702514647015
</pre>
<div class="tip"><table border="0" summary="Tip">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
<th align="left">Tip</th>
</tr>
<tr><td align="left" valign="top">
<p>
Be <span class="bold"><strong>very careful</strong></span> about the floating-point
type <code class="computeroutput"><span class="identifier">T</span></code> that is passed to
the root-finding function. Carelessly passing a integer by writing <code class="computeroutput"><span class="identifier">cpp_dec_float_50</span> <span class="identifier">r</span>
<span class="special">=</span> <span class="identifier">cbrt_2deriv</span><span class="special">(</span><span class="number">2</span><span class="special">);</span></code>
or <code class="computeroutput"><span class="identifier">show_cube_root</span><span class="special">(</span><span class="number">2</span><span class="special">);</span></code> will
provoke many warnings and compile errors.
</p>
<p>
Even <code class="computeroutput"><span class="identifier">show_cube_root</span><span class="special">(</span><span class="number">2.F</span><span class="special">);</span></code> will
produce warnings because <code class="computeroutput"><span class="keyword">typedef</span>
<span class="keyword">double</span> <span class="identifier">guess_type</span></code>
defines the type used to compute the guess and bracket values as <code class="computeroutput"><span class="keyword">double</span></code>.
</p>
<p>
Even more treacherous is passing a <code class="computeroutput"><span class="keyword">double</span></code>
as in <code class="computeroutput"><span class="identifier">cpp_dec_float_50</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">cbrt_2deriv</span><span class="special">(</span><span class="number">2.</span><span class="special">);</span></code> which
silently gives the 'wrong' result, computing a <code class="computeroutput"><span class="keyword">double</span></code>
result and <span class="bold"><strong>then</strong></span> converting to <code class="computeroutput"><span class="identifier">cpp_dec_float_50</span></code>! All digits beyond
<code class="computeroutput"><span class="identifier">max_digits10</span></code> will be incorrect.
Making the <code class="computeroutput"><span class="identifier">cbrt</span></code> type explicit
with <code class="computeroutput"><span class="identifier">cbrt_2deriv</span><span class="special">&lt;</span><span class="identifier">cpp_dec_float_50</span><span class="special">&gt;(</span><span class="number">2.</span><span class="special">);</span></code> will
give you the desired 50 decimal digit precision result.
</p>
</td></tr>
</table></div>
<p>
Full code of this example is at <a href="../../../../example/root_finding_multiprecision_example.cpp" target="_top">root_finding_multiprecision_example.cpp</a>.
</p>
</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; 2006-2010, 2012-2014, 2017 Nikhar
Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Johan R&#229;de, Gautam
Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg, Daryle Walker
and Xiaogang Zhang<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="5th_root_eg.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="nth_root.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,188 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Generalizing to Compute the nth root</title>
<link rel="stylesheet" href="../../math.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Math Toolkit 2.6.0">
<link rel="up" href="../root_finding_examples.html" title="Examples of Root-Finding (with and without derivatives)">
<link rel="prev" href="multiprecision_root.html" title="Root-finding using Boost.Multiprecision">
<link rel="next" href="elliptic_eg.html" title="A More complex example - Inverting the Elliptic Integrals">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="multiprecision_root.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="elliptic_eg.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="math_toolkit.root_finding_examples.nth_root"></a><a class="link" href="nth_root.html" title="Generalizing to Compute the nth root">Generalizing
to Compute the nth root</a>
</h3></div></div></div>
<p>
If desired, we can now further generalize to compute the <span class="emphasis"><em>n</em></span>th
root by computing the derivatives <span class="bold"><strong>at compile-time</strong></span>
using the rules for differentiation and <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">pow</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;</span></code> where
template parameter <code class="computeroutput"><span class="identifier">N</span></code> is an
integer and a compile time constant. Our functor and function now have an
additional template parameter <code class="computeroutput"><span class="identifier">N</span></code>,
for the root required.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
Since the powers and derivatives are fixed at compile time, the resulting
code is as efficient as as if hand-coded as the cube and fifth-root examples
above. A good compiler should also optimise any repeated multiplications.
</p></td></tr>
</table></div>
<p>
Our <span class="emphasis"><em>n</em></span>th root functor is
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">int</span> <span class="identifier">N</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span> <span class="special">=</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">nth_functor_2deriv</span>
<span class="special">{</span> <span class="comment">// Functor returning both 1st and 2nd derivatives.</span>
<span class="identifier">BOOST_STATIC_ASSERT_MSG</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_integral</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">,</span> <span class="string">"Only floating-point type types can be used!"</span><span class="special">);</span>
<span class="identifier">BOOST_STATIC_ASSERT_MSG</span><span class="special">((</span><span class="identifier">N</span> <span class="special">&gt;</span> <span class="number">0</span><span class="special">)</span> <span class="special">==</span> <span class="keyword">true</span><span class="special">,</span> <span class="string">"root N must be &gt; 0!"</span><span class="special">);</span>
<span class="identifier">nth_functor_2deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">to_find_root_of</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">a</span><span class="special">(</span><span class="identifier">to_find_root_of</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">/* Constructor stores value a to find root of, for example: */</span> <span class="special">}</span>
<span class="comment">// using boost::math::tuple; // to return three values.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Return f(x), f'(x) and f''(x).</span>
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">pow</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">fx</span> <span class="special">=</span> <span class="identifier">pow</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">a</span><span class="special">;</span> <span class="comment">// Difference (estimate x^n - a).</span>
<span class="identifier">T</span> <span class="identifier">dx</span> <span class="special">=</span> <span class="identifier">N</span> <span class="special">*</span> <span class="identifier">pow</span><span class="special">&lt;</span><span class="identifier">N</span> <span class="special">-</span> <span class="number">1</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">);</span> <span class="comment">// 1st derivative f'(x).</span>
<span class="identifier">T</span> <span class="identifier">d2x</span> <span class="special">=</span> <span class="identifier">N</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">N</span> <span class="special">-</span> <span class="number">1</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">pow</span><span class="special">&lt;</span><span class="identifier">N</span> <span class="special">-</span> <span class="number">2</span> <span class="special">&gt;(</span><span class="identifier">x</span><span class="special">);</span> <span class="comment">// 2nd derivative f''(x).</span>
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">fx</span><span class="special">,</span> <span class="identifier">dx</span><span class="special">,</span> <span class="identifier">d2x</span><span class="special">);</span> <span class="comment">// 'return' fx, dx and d2x.</span>
<span class="special">}</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="identifier">T</span> <span class="identifier">a</span><span class="special">;</span> <span class="comment">// to be 'nth_rooted'.</span>
<span class="special">};</span>
</pre>
<p>
and our <span class="emphasis"><em>n</em></span>th root function is
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">int</span> <span class="identifier">N</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span> <span class="special">=</span> <span class="keyword">double</span><span class="special">&gt;</span>
<span class="identifier">T</span> <span class="identifier">nth_2deriv</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span>
<span class="special">{</span> <span class="comment">// return nth root of x using 1st and 2nd derivatives and Halley.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">std</span><span class="special">;</span> <span class="comment">// Help ADL of std functions.</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span> <span class="comment">// For halley_iterate.</span>
<span class="identifier">BOOST_STATIC_ASSERT_MSG</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_integral</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">,</span> <span class="string">"Only floating-point type types can be used!"</span><span class="special">);</span>
<span class="identifier">BOOST_STATIC_ASSERT_MSG</span><span class="special">((</span><span class="identifier">N</span> <span class="special">&gt;</span> <span class="number">0</span><span class="special">)</span> <span class="special">==</span> <span class="keyword">true</span><span class="special">,</span> <span class="string">"root N must be &gt; 0!"</span><span class="special">);</span>
<span class="identifier">BOOST_STATIC_ASSERT_MSG</span><span class="special">((</span><span class="identifier">N</span> <span class="special">&gt;</span> <span class="number">1000</span><span class="special">)</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">,</span> <span class="string">"root N is too big!"</span><span class="special">);</span>
<span class="keyword">typedef</span> <span class="keyword">double</span> <span class="identifier">guess_type</span><span class="special">;</span> <span class="comment">// double may restrict (exponent) range for a multiprecision T?</span>
<span class="keyword">int</span> <span class="identifier">exponent</span><span class="special">;</span>
<span class="identifier">frexp</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">guess_type</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">),</span> <span class="special">&amp;</span><span class="identifier">exponent</span><span class="special">);</span> <span class="comment">// Get exponent of z (ignore mantissa).</span>
<span class="identifier">T</span> <span class="identifier">guess</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">guess_type</span><span class="special">&gt;(</span><span class="number">1.</span><span class="special">),</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="identifier">N</span><span class="special">);</span> <span class="comment">// Rough guess is to divide the exponent by n.</span>
<span class="identifier">T</span> <span class="identifier">min</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">guess_type</span><span class="special">&gt;(</span><span class="number">1.</span><span class="special">)</span> <span class="special">/</span> <span class="number">2</span><span class="special">,</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="identifier">N</span><span class="special">);</span> <span class="comment">// Minimum possible value is half our guess.</span>
<span class="identifier">T</span> <span class="identifier">max</span> <span class="special">=</span> <span class="identifier">ldexp</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">guess_type</span><span class="special">&gt;(</span><span class="number">2.</span><span class="special">),</span> <span class="identifier">exponent</span> <span class="special">/</span> <span class="identifier">N</span><span class="special">);</span> <span class="comment">// Maximum possible value is twice our guess.</span>
<span class="keyword">int</span> <span class="identifier">digits</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">digits</span> <span class="special">*</span> <span class="number">0.4</span><span class="special">;</span> <span class="comment">// Accuracy triples with each step, so stop when</span>
<span class="comment">// slightly more than one third of the digits are correct.</span>
<span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">maxit</span> <span class="special">=</span> <span class="number">20</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">uintmax_t</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">maxit</span><span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">halley_iterate</span><span class="special">(</span><span class="identifier">nth_functor_2deriv</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">x</span><span class="special">),</span> <span class="identifier">guess</span><span class="special">,</span> <span class="identifier">min</span><span class="special">,</span> <span class="identifier">max</span><span class="special">,</span> <span class="identifier">digits</span><span class="special">,</span> <span class="identifier">it</span><span class="special">);</span>
<span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<pre class="programlisting"> <span class="identifier">show_nth_root</span><span class="special">&lt;</span><span class="number">5</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;(</span><span class="number">2.</span><span class="special">);</span>
<span class="identifier">show_nth_root</span><span class="special">&lt;</span><span class="number">5</span><span class="special">,</span> <span class="keyword">long</span> <span class="keyword">double</span><span class="special">&gt;(</span><span class="number">2.</span><span class="special">);</span>
<span class="preprocessor">#ifndef</span> <span class="identifier">_MSC_VER</span> <span class="comment">// float128 is not supported by Microsoft compiler 2013.</span>
<span class="identifier">show_nth_root</span><span class="special">&lt;</span><span class="number">5</span><span class="special">,</span> <span class="identifier">float128</span><span class="special">&gt;(</span><span class="number">2</span><span class="special">);</span>
<span class="preprocessor">#endif</span>
<span class="identifier">show_nth_root</span><span class="special">&lt;</span><span class="number">5</span><span class="special">,</span> <span class="identifier">cpp_dec_float_50</span><span class="special">&gt;(</span><span class="number">2</span><span class="special">);</span> <span class="comment">// dec</span>
<span class="identifier">show_nth_root</span><span class="special">&lt;</span><span class="number">5</span><span class="special">,</span> <span class="identifier">cpp_bin_float_50</span><span class="special">&gt;(</span><span class="number">2</span><span class="special">);</span> <span class="comment">// bin</span>
</pre>
<p>
produces an output similar to this
</p>
<pre class="programlisting"> <span class="identifier">Using</span> <span class="identifier">MSVC</span> <span class="number">2013</span>
<span class="identifier">nth</span> <span class="identifier">Root</span> <span class="identifier">finding</span> <span class="identifier">Example</span><span class="special">.</span>
<span class="identifier">Type</span> <span class="keyword">double</span> <span class="identifier">value</span> <span class="special">=</span> <span class="number">2</span><span class="special">,</span> <span class="number">5</span><span class="identifier">th</span> <span class="identifier">root</span> <span class="special">=</span> <span class="number">1.14869835499704</span>
<span class="identifier">Type</span> <span class="keyword">long</span> <span class="keyword">double</span> <span class="identifier">value</span> <span class="special">=</span> <span class="number">2</span><span class="special">,</span> <span class="number">5</span><span class="identifier">th</span> <span class="identifier">root</span> <span class="special">=</span> <span class="number">1.14869835499704</span>
<span class="identifier">Type</span> <span class="keyword">class</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">number</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">backends</span><span class="special">::</span><span class="identifier">cpp_dec_float</span><span class="special">&lt;</span><span class="number">50</span><span class="special">,</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">void</span><span class="special">&gt;,</span><span class="number">1</span><span class="special">&gt;</span> <span class="identifier">value</span> <span class="special">=</span> <span class="number">2</span><span class="special">,</span>
<span class="number">5</span><span class="identifier">th</span> <span class="identifier">root</span> <span class="special">=</span> <span class="number">1.1486983549970350067986269467779275894438508890978</span>
<span class="identifier">Type</span> <span class="keyword">class</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">number</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">backends</span><span class="special">::</span><span class="identifier">cpp_bin_float</span><span class="special">&lt;</span><span class="number">50</span><span class="special">,</span><span class="number">10</span><span class="special">,</span><span class="keyword">void</span><span class="special">,</span><span class="keyword">int</span><span class="special">,</span><span class="number">0</span><span class="special">,</span><span class="number">0</span><span class="special">&gt;,</span><span class="number">0</span><span class="special">&gt;</span> <span class="identifier">value</span> <span class="special">=</span> <span class="number">2</span><span class="special">,</span>
<span class="number">5</span><span class="identifier">th</span> <span class="identifier">root</span> <span class="special">=</span> <span class="number">1.1486983549970350067986269467779275894438508890978</span>
</pre>
<div class="tip"><table border="0" summary="Tip">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
<th align="left">Tip</th>
</tr>
<tr><td align="left" valign="top">
<p>
Take care with the type passed to the function. It is best to pass a <code class="computeroutput"><span class="keyword">double</span></code> or greater-precision floating-point
type.
</p>
<p>
Passing an integer value, for example, <code class="computeroutput"><span class="identifier">nth_2deriv</span><span class="special">&lt;</span><span class="number">5</span><span class="special">&gt;(</span><span class="number">2</span><span class="special">)</span></code> will be
rejected, while <code class="computeroutput"><span class="identifier">nth_2deriv</span><span class="special">&lt;</span><span class="number">5</span><span class="special">,</span>
<span class="keyword">double</span><span class="special">&gt;(</span><span class="number">2</span><span class="special">)</span></code> converts
the integer to <code class="computeroutput"><span class="keyword">double</span></code>.
</p>
<p>
Avoid passing a <code class="computeroutput"><span class="keyword">float</span></code> value
that will provoke warnings (actually spurious) from the compiler about
potential loss of data, as noted above.
</p>
</td></tr>
</table></div>
<div class="warning"><table border="0" summary="Warning">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../../../../doc/src/images/warning.png"></td>
<th align="left">Warning</th>
</tr>
<tr><td align="left" valign="top"><p>
Asking for unreasonable roots, for example, <code class="computeroutput"><span class="identifier">show_nth_root</span><span class="special">&lt;</span><span class="number">1000000</span><span class="special">&gt;(</span><span class="number">2.</span><span class="special">);</span></code>
may lead to <a href="http://en.wikipedia.org/wiki/Loss_of_significance" target="_top">Loss
of significance</a> like <code class="computeroutput"><span class="identifier">Type</span>
<span class="keyword">double</span> <span class="identifier">value</span>
<span class="special">=</span> <span class="number">2</span><span class="special">,</span> <span class="number">1000000</span><span class="identifier">th</span> <span class="identifier">root</span>
<span class="special">=</span> <span class="number">1.00000069314783</span></code>.
Use of the the <code class="computeroutput"><span class="identifier">pow</span></code> function
is more sensible for this unusual need.
</p></td></tr>
</table></div>
<p>
Full code of this example is at <a href="../../../../example/root_finding_n_example.cpp" target="_top">root_finding_n_example.cpp</a>.
</p>
</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; 2006-2010, 2012-2014, 2017 Nikhar
Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Johan R&#229;de, Gautam
Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg, Daryle Walker
and Xiaogang Zhang<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="multiprecision_root.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../root_finding_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="elliptic_eg.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>