math/doc/html/math_toolkit/powers/ct_pow.html
2019-10-31 17:55:35 +00:00

268 lines
22 KiB
HTML

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Compile Time Power of a Runtime Base</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.11.0">
<link rel="up" href="../powers.html" title="Basic Functions">
<link rel="prev" href="hypot.html" title="hypot">
<link rel="next" href="../sinc.html" title="Sinus Cardinal and Hyperbolic Sinus Cardinal Functions">
</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="hypot.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../powers.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="../sinc.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.powers.ct_pow"></a><a class="link" href="ct_pow.html" title="Compile Time Power of a Runtime Base">Compile Time Power of a Runtime
Base</a>
</h3></div></div></div>
<p>
The <code class="computeroutput"><span class="identifier">pow</span></code> function effectively
computes the compile-time integral power of a run-time base.
</p>
<h5>
<a name="math_toolkit.powers.ct_pow.h0"></a>
<span class="phrase"><a name="math_toolkit.powers.ct_pow.synopsis"></a></span><a class="link" href="ct_pow.html#math_toolkit.powers.ct_pow.synopsis">Synopsis</a>
</h5>
<p>
<a href="../../../../../../boost/math/special_functions/pow.hpp" target="_top"><code class="computeroutput"><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">pow</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code></a>
</p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">math</span> <span class="special">{</span>
<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">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">pow</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">base</span><span class="special">);</span>
<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">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Policy</span><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">pow</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">base</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">Policy</span><span class="special">&amp;</span> <span class="identifier">policy</span><span class="special">);</span>
<span class="special">}}</span>
</pre>
<h5>
<a name="math_toolkit.powers.ct_pow.h1"></a>
<span class="phrase"><a name="math_toolkit.powers.ct_pow.rationale_and_usage"></a></span><a class="link" href="ct_pow.html#math_toolkit.powers.ct_pow.rationale_and_usage">Rationale
and Usage</a>
</h5>
<p>
Computing the power of a number with an exponent that is known at compile
time is a common need for programmers. In such cases, the usual method is
to avoid the overhead implied by the <code class="computeroutput"><span class="identifier">pow</span></code>,
<code class="computeroutput"><span class="identifier">powf</span></code> and <code class="computeroutput"><span class="identifier">powl</span></code>
C functions by hardcoding an expression such as:
</p>
<pre class="programlisting"><span class="comment">// Hand-written 8th power of a 'base' variable</span>
<span class="keyword">double</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">;</span>
</pre>
<p>
However, this kind of expression is not really readable (knowing the value
of the exponent involves counting the number of occurrences of <span class="emphasis"><em>base</em></span>),
error-prone (it's easy to forget an occurrence), syntactically bulky, and
non-optimal in terms of performance.
</p>
<p>
The <code class="computeroutput"><span class="identifier">pow</span></code> function of Boost.Math
helps writing this kind expression along with solving all the problems listed
above:
</p>
<pre class="programlisting"><span class="comment">// 8th power of a 'base' variable using math::pow</span>
<span class="keyword">double</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">pow</span><span class="special">&lt;</span><span class="number">8</span><span class="special">&gt;(</span><span class="identifier">base</span><span class="special">);</span>
</pre>
<p>
The expression is now shorter, easier to read, safer, and even faster. Indeed,
<code class="computeroutput"><span class="identifier">pow</span></code> will compute the expression
such that only log2(N) products are made for a power of N. For instance in
the example above, the resulting expression will be the same as if we had
written this, with only one computation of each identical subexpression:
</p>
<pre class="programlisting"><span class="comment">// Internal effect of pow&lt;8&gt;(base)</span>
<span class="keyword">double</span> <span class="identifier">result</span> <span class="special">=</span> <span class="special">((</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">)*(</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">))*((</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">)*(</span><span class="identifier">base</span><span class="special">*</span><span class="identifier">base</span><span class="special">));</span>
</pre>
<p>
Only 3 different products were actually computed.
</p>
<h5>
<a name="math_toolkit.powers.ct_pow.h2"></a>
<span class="phrase"><a name="math_toolkit.powers.ct_pow.return_type"></a></span><a class="link" href="ct_pow.html#math_toolkit.powers.ct_pow.return_type">Return
Type</a>
</h5>
<p>
The return type of these functions is computed using the <a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>result
type calculation rules</em></span></a>. For example:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
If T is a <code class="computeroutput"><span class="keyword">float</span></code>, the return
type is a <code class="computeroutput"><span class="keyword">float</span></code>.
</li>
<li class="listitem">
If T is a <code class="computeroutput"><span class="keyword">long</span> <span class="keyword">double</span></code>,
the return type is a <code class="computeroutput"><span class="keyword">long</span> <span class="keyword">double</span></code>.
</li>
<li class="listitem">
Otherwise, the return type is a <code class="computeroutput"><span class="keyword">double</span></code>.
</li>
</ul></div>
<h5>
<a name="math_toolkit.powers.ct_pow.h3"></a>
<span class="phrase"><a name="math_toolkit.powers.ct_pow.policies"></a></span><a class="link" href="ct_pow.html#math_toolkit.powers.ct_pow.policies">Policies</a>
</h5>
<p>
The final <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">Policy</a> argument is optional and can
be used to control the behaviour of the function: how it handles errors,
what level of precision to use etc. Refer to the <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">policy
documentation for more details</a>.
</p>
<h5>
<a name="math_toolkit.powers.ct_pow.h4"></a>
<span class="phrase"><a name="math_toolkit.powers.ct_pow.error_handling"></a></span><a class="link" href="ct_pow.html#math_toolkit.powers.ct_pow.error_handling">Error
Handling</a>
</h5>
<p>
Two cases of errors can occur when using <code class="computeroutput"><span class="identifier">pow</span></code>:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
In case of null base and negative exponent, an <a class="link" href="../error_handling.html#math_toolkit.error_handling.overflow_error">overflow_error</a>
occurs since this operation is a division by 0 (it equals to 1/0).
</li>
<li class="listitem">
In case of null base and null exponent, an <a class="link" href="../error_handling.html#math_toolkit.error_handling.indeterminate_result_error">indeterminate_result_error</a>
occurs since the result of this operation is indeterminate. Those errors
follow the <a class="link" href="../error_handling.html" title="Error Handling">general policies
of error handling in Boost.Math</a>.
</li>
</ul></div>
<p>
The default overflow error policy is <code class="computeroutput"><span class="identifier">throw_on_error</span></code>.
A call like <code class="computeroutput"><span class="identifier">pow</span><span class="special">&lt;-</span><span class="number">2</span><span class="special">&gt;(</span><span class="number">0</span><span class="special">)</span></code> will thus throw a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">overflow_error</span></code>
exception. As shown in the link given above, other error handling policies
can be used:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">errno_on_error</span></code>: Sets
<code class="computeroutput"><span class="special">::</span><span class="identifier">errno</span></code>
to <code class="computeroutput"><span class="identifier">ERANGE</span></code> and returns
<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">infinity</span><span class="special">()</span></code>.
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">ignore_error</span></code>: Returns
<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">infinity</span><span class="special">()</span></code>.
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">user_error</span></code>: Returns the
result of <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">policies</span><span class="special">::</span><span class="identifier">user_overflow_error</span></code>: this function
must be defined by the user.
</li>
</ul></div>
<p>
The default indeterminate result error policy is <code class="computeroutput"><span class="identifier">ignore_error</span></code>,
which for this function returns 1 since it's the most commonly chosen result
for a power of 0. Here again, other error handling policies can be used:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">throw_on_error</span></code>: Throws
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">errno_on_error</span></code>: Sets
<code class="computeroutput"><span class="special">::</span><span class="identifier">errno</span></code>
to <code class="computeroutput"><span class="identifier">EDOM</span></code> and returns 1.
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">user_error</span></code>: Returns the
result of <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">policies</span><span class="special">::</span><span class="identifier">user_indeterminate_result_error</span></code>: this
function must be defined by the user.
</li>
</ul></div>
<p>
Here is an example of error handling customization where we want to specify
the result that has to be returned in case of error. We will thus use the
<code class="computeroutput"><span class="identifier">user_error</span></code> policy, by passing
as second argument an instance of an overflow_error policy templated with
<code class="computeroutput"><span class="identifier">user_error</span></code>:
</p>
<pre class="programlisting"><span class="comment">// First we open the boost::math::policies namespace and define the `user_overflow_error`</span>
<span class="comment">// by making it return the value we want in case of error (-1 here)</span>
<span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">math</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">policies</span> <span class="special">{</span>
<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">user_overflow_error</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;)</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="special">-</span><span class="number">1</span><span class="special">;</span> <span class="special">}</span>
<span class="special">}}}</span>
<span class="comment">// Then we invoke pow and indicate that we want to use the user_error policy</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">policies</span><span class="special">;</span>
<span class="keyword">double</span> <span class="identifier">result</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">base</span><span class="special">,</span> <span class="identifier">policy</span><span class="special">&lt;</span><span class="identifier">overflow_error</span><span class="special">&lt;</span><span class="identifier">user_error</span><span class="special">&gt;</span> <span class="special">&gt;());</span>
<span class="comment">// We can now test the returned value and treat the special case if needed:</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">result</span> <span class="special">==</span> <span class="special">-</span><span class="number">1</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// there was an error, do something...</span>
<span class="special">}</span>
</pre>
<p>
Another way is to redefine the default <code class="computeroutput"><span class="identifier">overflow_error</span></code>
policy by using the BOOST_MATH_OVERFLOW_ERROR_POLICY macro. Once the <code class="computeroutput"><span class="identifier">user_overflow_error</span></code> function is defined
as above, we can achieve the same result like this:
</p>
<pre class="programlisting"><span class="comment">// Redefine the default error_overflow policy</span>
<span class="preprocessor">#define</span> <span class="identifier">BOOST_MATH_OVERFLOW_ERROR_POLICY</span> <span class="identifier">user_error</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">pow</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="comment">// From this point, passing a policy in argument is no longer needed, a call like this one</span>
<span class="comment">// will return -1 in case of error:</span>
<span class="keyword">double</span> <span class="identifier">result</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">base</span><span class="special">);</span>
</pre>
<h5>
<a name="math_toolkit.powers.ct_pow.h5"></a>
<span class="phrase"><a name="math_toolkit.powers.ct_pow.acknowledgements"></a></span><a class="link" href="ct_pow.html#math_toolkit.powers.ct_pow.acknowledgements">Acknowledgements</a>
</h5>
<p>
Bruno Lalande submitted this addition to Boost.Math.
</p>
<p>
Thanks to Joaqu&#237;n L&#243;pez Mu&#241;oz and Scott McMurray for their help in
improving the implementation.
</p>
<h5>
<a name="math_toolkit.powers.ct_pow.h6"></a>
<span class="phrase"><a name="math_toolkit.powers.ct_pow.references"></a></span><a class="link" href="ct_pow.html#math_toolkit.powers.ct_pow.references">References</a>
</h5>
<p>
D.E. Knuth, <span class="emphasis"><em>The Art of Computer Programming, Vol. 2: Seminumerical
Algorithms</em></span>, 2nd ed., Addison-Wesley, Reading, MA, 1981
</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-2019 Nikhar
Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Matthew Pulver, 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="hypot.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../powers.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="../sinc.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>