2021-10-05 21:37:46 +02:00

166 lines
13 KiB
HTML

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Obtaining the Size of a Unit In the Last Place - ULP</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 3.0.0">
<link rel="up" href="../next_float.html" title="Floating-Point Representation Distance (ULP), and Finding Adjacent Floating-Point Values">
<link rel="prev" href="float_advance.html" title="Advancing a floating-point Value by a Specific Representation Distance (ULP) float_advance">
<link rel="next" href="../float_comparison.html" title="Floating-point Comparison">
</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="float_advance.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../next_float.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="../float_comparison.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.next_float.ulp"></a><a class="link" href="ulp.html" title="Obtaining the Size of a Unit In the Last Place - ULP">Obtaining the Size of a
Unit In the Last Place - ULP</a>
</h3></div></div></div>
<p>
Function <code class="computeroutput"><span class="identifier">ulp</span></code> gives the size
of a unit-in-the-last-place for a specified floating-point value.
</p>
<h5>
<a name="math_toolkit.next_float.ulp.h0"></a>
<span class="phrase"><a name="math_toolkit.next_float.ulp.synopsis"></a></span><a class="link" href="ulp.html#math_toolkit.next_float.ulp.synopsis">Synopsis</a>
</h5>
<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">special_functions</span><span class="special">/</span><span class="identifier">ulp</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<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">class</span> <span class="identifier">FPT</span><span class="special">&gt;</span>
<span class="identifier">FPT</span> <span class="identifier">ulp</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">FPT</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">FPT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Policy</span><span class="special">&gt;</span>
<span class="identifier">FPT</span> <span class="identifier">ulp</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">FPT</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">Policy</span><span class="special">&amp;);</span>
<span class="special">}}</span> <span class="comment">// namespaces</span>
</pre>
<h5>
<a name="math_toolkit.next_float.ulp.h1"></a>
<span class="phrase"><a name="math_toolkit.next_float.ulp.description_ulp"></a></span><a class="link" href="ulp.html#math_toolkit.next_float.ulp.description_ulp">Description
- ulp</a>
</h5>
<p>
Returns one <a href="http://en.wikipedia.org/wiki/Unit_in_the_last_place" target="_top">unit
in the last place</a> of <span class="emphasis"><em>x</em></span>.
</p>
<p>
Corner cases are handled as follows:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
If the argument is a NaN, then raises a <a class="link" href="../error_handling.html#math_toolkit.error_handling.domain_error">domain_error</a>.
</li>
<li class="listitem">
If the argument is an infinity, then raises an <a class="link" href="../error_handling.html#math_toolkit.error_handling.overflow_error">overflow_error</a>.
</li>
<li class="listitem">
If the argument is zero then returns the smallest representable value:
for example for type <code class="computeroutput"><span class="keyword">double</span></code>
this would be either <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="keyword">double</span><span class="special">&gt;::</span><span class="identifier">min</span><span class="special">()</span></code> or <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="keyword">double</span><span class="special">&gt;::</span><span class="identifier">denorm_min</span><span class="special">()</span></code> depending whether denormals are supported
(which have the values <code class="computeroutput"><span class="number">2.2250738585072014e-308</span></code>
and <code class="computeroutput"><span class="number">4.9406564584124654e-324</span></code>
respectively).
</li>
<li class="listitem">
If the result is too small to represent, then returns the smallest representable
value.
</li>
<li class="listitem">
Always returns a positive value such that <code class="computeroutput"><span class="identifier">ulp</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">ulp</span><span class="special">(-</span><span class="identifier">x</span><span class="special">)</span></code>.
</li>
</ul></div>
<p>
<span class="bold"><strong>Important:</strong></span> The behavior of this function
is aligned to that of <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#ulp%28double%29" target="_top">Java's
ulp function</a>, please note however that this function should only
ever be used for rough and ready calculations as there are enough corner
cases to trap even careful programmers. In particular:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
The function is asymmetrical, which is to say, given <code class="computeroutput"><span class="identifier">u</span>
<span class="special">=</span> <span class="identifier">ulp</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></code> if <code class="computeroutput"><span class="identifier">x</span>
<span class="special">&gt;</span> <span class="number">0</span></code>
then <code class="computeroutput"><span class="identifier">x</span> <span class="special">+</span>
<span class="identifier">u</span></code> is the next floating-point
value, but <code class="computeroutput"><span class="identifier">x</span> <span class="special">-</span>
<span class="identifier">u</span></code> is not necessarily the previous
value. Similarly, if <code class="computeroutput"><span class="identifier">x</span> <span class="special">&lt;</span> <span class="number">0</span></code>
then <code class="computeroutput"><span class="identifier">x</span> <span class="special">-</span>
<span class="identifier">u</span></code> is the previous floating-point
value, but <code class="computeroutput"><span class="identifier">x</span> <span class="special">+</span>
<span class="identifier">u</span></code> is not necessarily the next
value. The corner cases occur at power of 2 boundaries.
</li>
<li class="listitem">
When the argument becomes very small, it may be that there is no floating-point
value that represents one ULP. Whether this is the case or not depends
not only on whether the hardware may <span class="emphasis"><em>sometimes</em></span> support
denormals (as signalled by <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">FPT</span><span class="special">&gt;::</span><span class="identifier">has_denorm</span></code>),
but also whether these are currently enabled at runtime (for example
on SSE hardware, the DAZ or FTZ flags will disable denormal support).
In this situation, the <code class="computeroutput"><span class="identifier">ulp</span></code>
function may return a value that is many orders of magnitude too large.
</li>
</ul></div>
<p>
In light of the issues above, we recommend that:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
To move between adjacent floating-point values always use <a class="link" href="float_next.html" title="Finding the Next Greater Representable Value (float_next)">float_next</a>,
<a class="link" href="float_prior.html" title="Finding the Next Smaller Representable Value (float_prior)">float_prior</a>
or <a class="link" href="nextafter.html" title="Finding the Next Representable Value in a Specific Direction (nextafter)">nextafter</a>
(<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">nextafter</span></code> is another candidate, but
our experience is that this also often breaks depending which optimizations
and hardware flags are in effect).
</li>
<li class="listitem">
To move several floating-point values away use <a class="link" href="float_advance.html" title="Advancing a floating-point Value by a Specific Representation Distance (ULP) float_advance">float_advance</a>.
</li>
<li class="listitem">
To calculate the edit distance between two floats use <a href="../../../../../../libs/math/doc/html/math_toolkit/next_float/float_distance.html" target="_top">Boost.Math
float_distance</a>.
</li>
</ul></div>
<p>
There is none the less, one important use case for this function:
</p>
<p>
If it is known that the true result of some function is x<sub>t</sub> and the calculated
result is x<sub>c</sub>, then the error measured in ulp is simply <code class="literal">fabs(x<sub>t</sub> -
x<sub>c</sub>) / ulp(x<sub>t</sub>)</code>.
</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 © 2006-2021 Nikhar Agrawal, Anton Bikineev, Matthew Borland,
Paul A. Bristow, Marco Guazzone, Christopher Kormanyos, Hubert Holin, Bruno
Lalande, John Maddock, Evan Miller, Jeremy Murphy, Matthew Pulver, Johan Rå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="float_advance.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../next_float.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="../float_comparison.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>