blob: 5c5f67c81c98e93d3adc8801b5f28cc2b4315f05 [file] [log] [blame]
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Floating Point Concerns</title>
<link href="styles.css" rel="stylesheet">
</head>
<body>
<h1>Floating Point Concerns</h1>
<p>Consider this simple implementation of <code>endian_reverse</code>:</p>
<blockquote>
<pre>template &lt;class T&gt;
inline T endian_reverse(T x) BOOST_NOEXCEPT
{
std::reverse(reinterpret_cast&lt;unsigned char*&gt;(&amp;x),
reinterpret_cast&lt;unsigned char*&gt;(&amp;x) + sizeof(T));
return x;
}</pre>
</blockquote>
<p><b>Under what conditions with this code fail?</b></p>
<p dir="ltr">It will fail if an object of type <code>T</code> has one or more
bit patterns that cause a failure. Failures usually occur when&nbsp; an invalid
or otherwise special bit pattern is loaded into or saved from a hardware
register.</p>
<p dir="ltr">The problem could in theory occur with both integers and floating
point numbers, but the <a href="http://en.wikipedia.org/wiki/Two's_complement">
two's complement integers</a> ubiquitous in modern computer architectures do not
have any invalid or otherwise special bit patterns that cause failure when
byte-wise reversed.</p>
<p dir="ltr">But floating point numbers are a different story. Even if we limit
discussion to IEEE 754 (aka ISO/IEC/IEEE 60559) binary representations of 4 and
8 byte sizes, several problems are easy to demonstrate:</p>
<ul>
<li dir="ltr">
<p dir="ltr">...</li>
</ul>
<h2 dir="ltr">Safe interfaces and possible reference implementations</h2>
<h3 dir="ltr">In-place interface</h3>
<blockquote>
<pre dir="ltr">template &lt;class T&gt;
inline void endian_reverse_inplace(T&amp; x)
{
std::reverse(reinterpret_cast&lt;unsigned char*&gt;(&amp;x),
reinterpret_cast&lt;unsigned char*&gt;(&amp;x) + sizeof(T));
}</pre>
</blockquote>
<p dir="ltr">This is the same as the current (i.e integer) customization point
interface, so there is no need for any change.</p>
<p dir="ltr"><b>Warning:</b> Even thought <code>x</code> may have had a valid
value on the originating platform, after calling this function the value of
<code>x</code> may differ or be invalid on this platform.</p>
<h3 dir="ltr">Copy interface</h3>
<blockquote>
<pre dir="ltr">template &lt;class T&gt;
inline void endian_reverse_copy(const T&amp; from, T&amp; to)
{
std::reverse_copy(reinterpret_cast&lt;const unsigned char*&gt;(&amp;from),
reinterpret_cast&lt;const unsigned char*&gt;(&amp;from) + sizeof(T),
reinterpret_cast&lt;unsigned char*&gt;(&amp;to));
}</pre>
</blockquote>
<p><b>Warning:</b> Even thought <code>from</code> may have been a valid value on
the originating platform, after calling this function the value of <code>to</code>
may differ or be invalid on this platform.</p>
<h3>Return-by-value interface</h3>
<blockquote>
<pre>template &lt;class T&gt;
inline T endian_reverse_to_native(<span style="background-color: #FFFF00">const</span><span style="background-color: #FFFF00"> T&amp;</span> x) BOOST_NOEXCEPT
{
T tmp;
std::reverse_copy(reinterpret_cast&lt;const unsigned char*&gt;(&amp;x),
reinterpret_cast&lt;const unsigned char*&gt;(&amp;x) + sizeof(T),
reinterpret_cast&lt;unsigned char*&gt;(&amp;tmp));
return tmp;
}</pre>
</blockquote>
<p><b>Warning:</b> Even thought <code>x</code> may have had a valid value on the
originating platform, the value of returned by this function may differ or be
invalid on this platform.</p>
<h2>Acknowledgements</h2>
<hr>
<p>Last revised: <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->27 March, 2015<!--webbot bot="Timestamp" endspan i-checksum="28924" --></p>
<p>© Copyright Beman Dawes, 2015</p>
<p>Distributed under the Boost Software License, Version 1.0. See <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a></p>
<p>&nbsp;</p>
</body>
</html>