mirror of
https://github.com/boostorg/endian.git
synced 2025-07-31 13:07:24 +02:00
Implement, test, float and double endian types.
This commit is contained in:
125
doc/index.html
125
doc/index.html
@ -177,6 +177,129 @@ application.</p>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Timing tests</h2>
|
||||
<p>These tests were run against release builds on a circa 2012 4-core little endian X64 Intel Core i5-3570K
|
||||
CPU @ 3.40GHz under Windows 7.</p>
|
||||
|
||||
<p>See <a href="../test/speed_test.cpp">speed_test.cpp</a>,
|
||||
<a href="../test/speed_test_functions.hpp">speed_test_functions.hpp</a>,
|
||||
<a href="../test/speed_test_functions.cpp">speed_test_functions.cpp</a>, and
|
||||
<a href="../build/Jamfile.v2">Jamfile.v2</a> for the actual code and build. The timed functions are in a separate
|
||||
compilation unit to prevent being optimized away.</p>
|
||||
|
||||
<p>Because the timings are anomalous, particularly for those high-lighted below
|
||||
in yellow, the generated code from the GNU compiler was studied in detail. <b>
|
||||
Exactly the same code is being generated for by-value conversion functions,
|
||||
in-place conversion functions, and the endian types. Exactly the same code is
|
||||
being generated whether intrinsics are used or not for 32 and 64-bit tests.</b>
|
||||
(For GCC 4.7, there are no 16-bit intrinsics, so they are emulated by using
|
||||
32-bit intrinsics.)</p>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr>
|
||||
<td bgcolor="#D7EEFF">
|
||||
<p align="center"><b>Conclusions</b></p>
|
||||
<p>The decision to use endian types or endian conversion functions should be
|
||||
made based on application use cases, not assumptions about generated code
|
||||
efficiency. Modern optimizers generate the same code for either approach,
|
||||
and whether or not intrinsics are available. </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0"style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr><td colspan="6" align="center"><b>GNU g++ version 4.7.0</b></td></tr>
|
||||
<tr><td colspan="6" align="center"><b> Iterations: 1,000,000,000, Intrinsics: __builtin_bswap16, etc.</b></td></tr>
|
||||
<tr><td><b>Test Case</b></td>
|
||||
<td align="center"><b>int<br>arg</b></td>
|
||||
<td align="center"><b>int<br>value(arg)</b></td>
|
||||
<td align="center"><b>int<br>in place(arg)</b></td>
|
||||
<td align="center"><b>Endian<br>arg</b></td>
|
||||
</tr>
|
||||
<tr><td>16-bit aligned big endian</td><td align="right" bgcolor="#FFFFCC">2.71 s</td>
|
||||
<td align="right">2.42 s</td><td align="right">2.42 s</td><td align="right">2.68 s</td></tr>
|
||||
<tr><td>16-bit aligned little endian</td><td align="right">2.42 s</td>
|
||||
<td align="right">2.40 s</td><td align="right">2.68 s</td><td align="right">2.45 s</td></tr>
|
||||
<tr><td>32-bit aligned big endian</td><td align="right">2.68 s</td>
|
||||
<td align="right">2.70 s</td><td align="right">2.70 s</td><td align="right">2.68 s</td></tr>
|
||||
<tr><td>32-bit aligned little endian</td><td align="right">2.68 s</td>
|
||||
<td align="right">2.68 s</td><td align="right">2.65 s</td><td align="right">2.68 s</td></tr>
|
||||
<tr><td>64-bit aligned big endian</td><td align="right" bgcolor="#FFFFCC">2.96 s</td>
|
||||
<td align="right" bgcolor="#FFFFCC">2.95 s</td>
|
||||
<td align="right" bgcolor="#FFFFCC">2.95 s</td>
|
||||
<td align="right" bgcolor="#FFFFCC">2.95 s</td></tr>
|
||||
<tr><td>64-bit aligned little endian</td><td align="right">2.42 s</td>
|
||||
<td align="right">2.40 s</td><td align="right">2.70 s</td><td align="right">2.42 s</td></tr>
|
||||
<tr><td colspan="6" align="center"><b> Iterations: 1,000,000,000, Intrinsics: no byte swap intrinsics</b></td></tr>
|
||||
<tr><td><b>Test Case</b></td>
|
||||
<td align="center"><b>int<br>arg</b></td>
|
||||
<td align="center"><b>int<br>value(arg)</b></td>
|
||||
<td align="center"><b>int<br>in place(arg)</b></td>
|
||||
<td align="center"><b>Endian<br>arg</b></td>
|
||||
</tr>
|
||||
<tr><td>16-bit aligned big endian</td><td align="right" bgcolor="#FFFFCC">2.71 s</td>
|
||||
<td align="right">2.42 s</td><td align="right">2.42 s</td><td align="right">2.68 s</td></tr>
|
||||
<tr><td>16-bit aligned little endian</td><td align="right">2.42 s</td>
|
||||
<td align="right">2.40 s</td><td align="right">2.68 s</td><td align="right">2.42 s</td></tr>
|
||||
<tr><td>32-bit aligned big endian</td><td align="right">2.68 s</td>
|
||||
<td align="right">2.70 s</td><td align="right">2.67 s</td><td align="right">2.70 s</td></tr>
|
||||
<tr><td>32-bit aligned little endian</td><td align="right">2.68 s</td>
|
||||
<td align="right">2.67 s</td><td align="right">2.70 s</td><td align="right">2.67 s</td></tr>
|
||||
<tr><td>64-bit aligned big endian</td><td align="right" bgcolor="#FFFFCC">2.96 s</td>
|
||||
<td align="right" bgcolor="#FFFFCC">2.95 s</td>
|
||||
<td align="right" bgcolor="#FFFFCC">2.95 s</td>
|
||||
<td align="right" bgcolor="#FFFFCC">2.93 s</td></tr>
|
||||
<tr><td>64-bit aligned little endian</td><td align="right">2.42 s</td>
|
||||
<td align="right">2.42 s</td><td align="right">2.67 s</td><td align="right">2.40 s</td></tr>
|
||||
|
||||
</table>
|
||||
<p></p>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0"style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr><td colspan="6" align="center"><b>Microsoft Visual C++ version 11.0</b></td></tr>
|
||||
<tr><td colspan="6" align="center"><b> Iterations: 1,000,000,000, Intrinsics: cstdlib _byteswap_ushort, etc.</b></td></tr>
|
||||
<tr><td><b>Test Case</b></td>
|
||||
<td align="center"><b>int<br>arg</b></td>
|
||||
<td align="center"><b>int<br>value(arg)</b></td>
|
||||
<td align="center"><b>int<br>in place(arg)</b></td>
|
||||
<td align="center"><b>Endian<br>arg</b></td>
|
||||
</tr>
|
||||
<tr><td>16-bit aligned big endian</td><td align="right">1.90 s</td>
|
||||
<td align="right">1.87 s</td><td align="right">1.89 s</td><td align="right">1.87 s</td></tr>
|
||||
<tr><td>16-bit aligned little endian</td><td align="right">1.89 s</td>
|
||||
<td align="right">1.87 s</td><td align="right">1.89 s</td><td align="right">1.87 s</td></tr>
|
||||
<tr><td>32-bit aligned big endian</td><td align="right">1.89 s</td>
|
||||
<td align="right">1.87 s</td><td align="right">1.89 s</td><td align="right">1.87 s</td></tr>
|
||||
<tr><td>32-bit aligned little endian</td><td align="right">1.89 s</td>
|
||||
<td align="right">1.87 s</td><td align="right">1.87 s</td><td align="right">1.89 s</td></tr>
|
||||
<tr><td>64-bit aligned big endian</td><td align="right">1.87 s</td>
|
||||
<td align="right">1.89 s</td><td align="right">1.87 s</td><td align="right">1.89 s</td></tr>
|
||||
<tr><td>64-bit aligned little endian</td><td align="right">1.87 s</td>
|
||||
<td align="right">1.87 s</td><td align="right">1.87 s</td><td align="right">1.89 s</td></tr>
|
||||
<tr><td colspan="6" align="center"><b> Iterations: 1,000,000,000, Intrinsics: no byte swap intrinsics</b></td></tr>
|
||||
<tr><td><b>Test Case</b></td>
|
||||
<td align="center"><b>int<br>arg</b></td>
|
||||
<td align="center"><b>int<br>value(arg)</b></td>
|
||||
<td align="center"><b>int<br>in place(arg)</b></td>
|
||||
<td align="center"><b>Endian<br>arg</b></td>
|
||||
</tr>
|
||||
<tr><td>16-bit aligned big endian</td><td align="right">1.90 s</td>
|
||||
<td align="right">1.89 s</td><td align="right">1.87 s</td><td align="right">1.87 s</td></tr>
|
||||
<tr><td>16-bit aligned little endian</td><td align="right">1.89 s</td>
|
||||
<td align="right">1.87 s</td><td align="right">1.89 s</td><td align="right">1.87 s</td></tr>
|
||||
<tr><td>32-bit aligned big endian</td><td align="right">1.89 s</td>
|
||||
<td align="right">1.87 s</td><td align="right">1.87 s</td><td align="right">1.89 s</td></tr>
|
||||
<tr><td>32-bit aligned little endian</td><td align="right">1.87 s</td>
|
||||
<td align="right">1.89 s</td><td align="right">1.87 s</td><td align="right">1.89 s</td></tr>
|
||||
<tr><td>64-bit aligned big endian</td><td align="right" bgcolor="#FFFFCC">2.32 s</td>
|
||||
<td align="right" bgcolor="#FFFFCC">2.46 s</td>
|
||||
<td align="right" bgcolor="#FFFFCC">2.45 s</td>
|
||||
<td align="right" bgcolor="#FFFFCC">2.34 s</td></tr>
|
||||
<tr><td>64-bit aligned little endian</td><td align="right">1.87 s</td>
|
||||
<td align="right">1.87 s</td><td align="right">1.89 s</td><td align="right">1.87 s</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<h2>Overall <a name="FAQ">FAQ</a></h2>
|
||||
<p><b>Why bother with endianness?</b></p>
|
||||
<blockquote>
|
||||
@ -226,7 +349,7 @@ Tim Blechmann, Tim Moore, tymofey, Tomas Puverle, Vincente Botet, Yuval Ronen
|
||||
and Vitaly Budovski,.</p>
|
||||
<hr>
|
||||
<p>Last revised:
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->22 May, 2013<!--webbot bot="Timestamp" endspan i-checksum="13980" --></p>
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->25 May, 2013<!--webbot bot="Timestamp" endspan i-checksum="13986" --></p>
|
||||
<p><EFBFBD> Copyright Beman Dawes, 2011, 2013</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>
|
||||
|
@ -80,6 +80,14 @@ namespace endian
|
||||
BOOST_SCOPED_ENUM(align) A = align::no>
|
||||
class endian;
|
||||
|
||||
// aligned big endian floating point types
|
||||
typedef boost::endian::endian<order::big, float, 32, align::yes> big_float32_t;
|
||||
typedef boost::endian::endian<order::big, double, 64, align::yes> big_float64_t;
|
||||
|
||||
// aligned little endian floating point types
|
||||
typedef boost::endian::endian<order::little, float, 32, align::yes> little_float32_t;
|
||||
typedef boost::endian::endian<order::little, double, 64, align::yes> little_float64_t;
|
||||
|
||||
// aligned big endian signed integer types
|
||||
typedef endian<order::big, int16_t, 16, align::yes> big_int16_t;
|
||||
typedef endian<order::big, int32_t, 32, align::yes> big_int32_t;
|
||||
|
@ -223,6 +223,17 @@ namespace
|
||||
little_uint32_t little_uint32 ;
|
||||
little_uint64_t little_uint64 ;
|
||||
|
||||
big_float32_t big_float32;
|
||||
big_float64_t big_float64;
|
||||
little_float32_t little_float32;
|
||||
little_float64_t little_float64;
|
||||
|
||||
VERIFY(big_float32.data() == reinterpret_cast<const char *>(&big_float32));
|
||||
VERIFY(big_float64.data() == reinterpret_cast<const char *>(&big_float64));
|
||||
|
||||
VERIFY(little_float32.data() == reinterpret_cast<const char *>(&little_float32));
|
||||
VERIFY(little_float64.data() == reinterpret_cast<const char *>(&little_float64));
|
||||
|
||||
VERIFY(big_8.data() == reinterpret_cast<const char *>(&big_8));
|
||||
VERIFY(big_16.data() == reinterpret_cast<const char *>(&big_16));
|
||||
VERIFY(big_24.data() == reinterpret_cast<const char *>(&big_24));
|
||||
@ -302,6 +313,11 @@ namespace
|
||||
VERIFY( numeric_limits<signed char>::digits == 7 );
|
||||
VERIFY( numeric_limits<unsigned char>::digits == 8 );
|
||||
|
||||
VERIFY_SIZE(sizeof( big_float32_t ), 4 );
|
||||
VERIFY_SIZE(sizeof( big_float64_t ), 8 );
|
||||
VERIFY_SIZE(sizeof( little_float32_t ), 4 );
|
||||
VERIFY_SIZE(sizeof( little_float64_t ), 8 );
|
||||
|
||||
VERIFY_SIZE( sizeof( big_8_t ), 1 );
|
||||
VERIFY_SIZE( sizeof( big_16_t ), 2 );
|
||||
VERIFY_SIZE( sizeof( big_24_t ), 3 );
|
||||
@ -510,6 +526,39 @@ namespace
|
||||
|
||||
void check_representation_and_range_and_ops()
|
||||
{
|
||||
float big_float32_expected = std::numeric_limits<float>::max();
|
||||
boost::endian::big_endian(big_float32_expected);
|
||||
big_float32_t big_float32(std::numeric_limits<float>::max());
|
||||
VERIFY(std::memcmp(big_float32.data(),
|
||||
reinterpret_cast<const char*>(&big_float32_expected), sizeof(float)) == 0);
|
||||
|
||||
float little_float32_expected = std::numeric_limits<float>::max();
|
||||
boost::endian::little_endian(little_float32_expected);
|
||||
little_float32_t little_float32(std::numeric_limits<float>::max());
|
||||
VERIFY(std::memcmp(little_float32.data(),
|
||||
reinterpret_cast<const char*>(&little_float32_expected), sizeof(float)) == 0);
|
||||
|
||||
double big_float64_expected = std::numeric_limits<double>::max();
|
||||
boost::endian::big_endian(big_float64_expected);
|
||||
big_float64_t big_float64(std::numeric_limits<double>::max());
|
||||
VERIFY(std::memcmp(big_float64.data(),
|
||||
reinterpret_cast<const char*>(&big_float64_expected), sizeof(double)) == 0);
|
||||
|
||||
double little_float64_expected = std::numeric_limits<double>::max();
|
||||
boost::endian::little_endian(little_float64_expected);
|
||||
little_float64_t little_float64(std::numeric_limits<double>::max());
|
||||
VERIFY(std::memcmp(little_float64.data(),
|
||||
reinterpret_cast<const char*>(&little_float64_expected), sizeof(double)) == 0);
|
||||
|
||||
VERIFY_VALUE_AND_OPS( big_float32_t, float, std::numeric_limits<float>::max() );
|
||||
VERIFY_VALUE_AND_OPS( big_float32_t, float, std::numeric_limits<float>::min() );
|
||||
VERIFY_VALUE_AND_OPS( big_float64_t, double, std::numeric_limits<double>::max() );
|
||||
VERIFY_VALUE_AND_OPS( big_float64_t, double, std::numeric_limits<double>::min() );
|
||||
|
||||
VERIFY_VALUE_AND_OPS( little_float32_t, float, std::numeric_limits<float>::max() );
|
||||
VERIFY_VALUE_AND_OPS( little_float32_t, float, std::numeric_limits<float>::min() );
|
||||
VERIFY_VALUE_AND_OPS( little_float64_t, double, std::numeric_limits<double>::max() );
|
||||
VERIFY_VALUE_AND_OPS( little_float64_t, double, std::numeric_limits<double>::min() );
|
||||
|
||||
VERIFY_BIG_REPRESENTATION( big_8_t );
|
||||
VERIFY_VALUE_AND_OPS( big_8_t, int_least8_t, 0x7f );
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
//#define BOOST_ENDIAN_NO_INTRINSICS
|
||||
#define BOOST_ENDIAN_NO_INTRINSICS
|
||||
//#define BOOST_ENDIAN_LOG
|
||||
|
||||
#include <boost/endian/detail/disable_warnings.hpp>
|
||||
@ -91,7 +91,7 @@ namespace
|
||||
f(x, y);
|
||||
}
|
||||
t.stop();
|
||||
cout << "<td>" << t.format(places, "%t") << " s</td>";
|
||||
cout << "<td align=\"right\">" << t.format(places, "%t") << " s</td>";
|
||||
}
|
||||
|
||||
void test_big_int16()
|
||||
@ -173,10 +173,10 @@ int cpp_main(int argc, char* argv[])
|
||||
<< ", Intrinsics: " BOOST_ENDIAN_INTRINSIC_MSG
|
||||
<< "</b></td></tr>\n"
|
||||
<< "<tr><td><b>Test Case</b></td>\n"
|
||||
"<td><b>int<br>arg</b></td>\n"
|
||||
"<td><b>int<br>value(arg)</b></td>\n"
|
||||
"<td><b>int<br>in place(arg)</b></td>\n"
|
||||
"<td><b>Endian<br>arg</b></td>\n"
|
||||
"<td align=\"center\"><b>int<br>arg</b></td>\n"
|
||||
"<td align=\"center\"><b>int<br>value(arg)</b></td>\n"
|
||||
"<td align=\"center\"><b>int<br>in place(arg)</b></td>\n"
|
||||
"<td align=\"center\"><b>Endian<br>arg</b></td>\n"
|
||||
"</tr>\n"
|
||||
;
|
||||
|
||||
|
Reference in New Issue
Block a user