Boost logo

Boost-Commit :

From: dwalker07_at_[hidden]
Date: 2008-07-15 05:59:20


Author: dlwalker
Date: 2008-07-15 05:59:19 EDT (Tue, 15 Jul 2008)
New Revision: 47434
URL: http://svn.boost.org/trac/boost/changeset/47434

Log:
Added exact-integer templates, which fixes #1225 (and completes #653)
Text files modified:
   trunk/boost/integer.hpp | 128 +++++++++++++++++++-
   trunk/boost/integer_fwd.hpp | 9 +
   trunk/libs/integer/integer.htm | 244 +++++++++++++++++++++++++++++++++++----
   trunk/libs/integer/test/integer_test.cpp | 204 +++++++++++++++++++++++++++++---
   4 files changed, 526 insertions(+), 59 deletions(-)

Modified: trunk/boost/integer.hpp
==============================================================================
--- trunk/boost/integer.hpp (original)
+++ trunk/boost/integer.hpp 2008-07-15 05:59:19 EDT (Tue, 15 Jul 2008)
@@ -7,6 +7,7 @@
 // See http://www.boost.org/libs/integer for documentation.
 
 // Revision History
+// 15 Jul 08 Added exact-integer templates. (Daryle Walker)
 // 14 Jul 08 Added extended-integer support. (Daryle Walker)
 // 13 Jul 08 Redid implmentation. (Daryle Walker)
 // 22 Sep 01 Added value-based integer templates. (Daryle Walker)
@@ -24,6 +25,8 @@
 #include <boost/integer_traits.hpp> // for boost::integer_traits
 #include <boost/limits.hpp> // for std::numeric_limits
 
+#include <climits> // for UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, etc.
+
 namespace boost
 {
 
@@ -85,7 +88,7 @@
   struct int_rank_helper
   {
       BOOST_STATIC_CONSTANT( int, mantissa = BitsIncludingSign - 1 );
- BOOST_STATIC_CONSTANT( int, rank =
+ BOOST_STATIC_CONSTANT( int, rank = (BitsIncludingSign > 0) * (
 #ifdef BOOST_HAS_LONG_LONG
        (mantissa <= std::numeric_limits< long_long_type >::digits) +
 #elif defined(BOOST_HAS_MS_INT64)
@@ -96,13 +99,13 @@
        (mantissa <= std::numeric_limits< long >::digits) +
        (mantissa <= std::numeric_limits< int >::digits) +
        (mantissa <= std::numeric_limits< short >::digits) +
- (mantissa <= std::numeric_limits< signed char >::digits) );
+ (mantissa <= std::numeric_limits< signed char >::digits)) );
   };
 
   template < int Bits >
   struct uint_rank_helper
   {
- BOOST_STATIC_CONSTANT( int, rank =
+ BOOST_STATIC_CONSTANT( int, rank = (Bits >= 0) * (
 #ifdef BOOST_HAS_LONG_LONG
        (Bits <= std::numeric_limits< ulong_long_type >::digits) +
 #elif defined(BOOST_HAS_MS_INT64)
@@ -113,14 +116,53 @@
        (Bits <= std::numeric_limits< unsigned long >::digits) +
        (Bits <= std::numeric_limits< unsigned int >::digits) +
        (Bits <= std::numeric_limits< unsigned short >::digits) +
- (Bits <= std::numeric_limits< unsigned char >::digits) );
+ (Bits <= std::numeric_limits< unsigned char >::digits)) );
   };
 
+ template < int BitsIncludingSign >
+ struct int_exact_rank_helper { BOOST_STATIC_CONSTANT( int, rank = 0 ); };
+ template < int Bits >
+ struct uint_exact_rank_helper { BOOST_STATIC_CONSTANT( int, rank = 0 ); };
+
+#define BOOST_PRIVATE_INT_EXACT_BUILDER(Type, Rank) \
+ template < > \
+ struct int_exact_rank_helper<std::numeric_limits< Type >::digits + 1> \
+ { BOOST_STATIC_CONSTANT( int, rank = Rank ); }
+#define BOOST_PRIVATE_UINT_EXACT_BUILDER(Type, Rank) \
+ template < > \
+ struct uint_exact_rank_helper<std::numeric_limits< Type >::digits> \
+ { BOOST_STATIC_CONSTANT( int, rank = Rank ); }
+
+#if defined(BOOST_HAS_LONG_LONG) && ((ULLONG_MAX > ULONG_MAX) || (ULONGLONG_MAX > ULONG_MAX))
+ BOOST_PRIVATE_INT_EXACT_BUILDER( long_long_type, 1 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( ulong_long_type, 1 );
+#elif defined(BOOST_HAS_MS_INT64) && (0xFFFFFFFFFFFFFFFFui64 > ULONG_MAX)
+ BOOST_PRIVATE_INT_EXACT_BUILDER( __int64, 1 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned __int64, 1 );
+#endif
+#if ULONG_MAX > UINT_MAX
+ BOOST_PRIVATE_INT_EXACT_BUILDER( long, 2 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned long, 2 );
+#endif
+#if UINT_MAX > USHRT_MAX
+ BOOST_PRIVATE_INT_EXACT_BUILDER( int, 3 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned, 3 );
+#endif
+#if USHRT_MAX > UCHAR_MAX
+ BOOST_PRIVATE_INT_EXACT_BUILDER( short, 4 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned short, 4 );
+#endif
+ BOOST_PRIVATE_INT_EXACT_BUILDER( signed char, 5 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned char, 5 );
+
+#undef BOOST_PRIVATE_INT_EXACT_BUILDER
+#undef BOOST_PRIVATE_UINT_EXACT_BUILDER
+
   // map an extreme value to a category
   template < intmax_t MaxValue >
   struct int_max_rank_helper
   {
- BOOST_STATIC_CONSTANT( int, rank =
+ BOOST_STATIC_CONSTANT( int, rank = (MaxValue > 0) * (
 #ifdef BOOST_HAS_LONG_LONG
        (MaxValue <= integer_traits< long_long_type >::const_max) +
 #elif defined(BOOST_HAS_MS_INT64)
@@ -131,13 +173,13 @@
        (MaxValue <= integer_traits< long >::const_max) +
        (MaxValue <= integer_traits< int >::const_max) +
        (MaxValue <= integer_traits< short >::const_max) +
- (MaxValue <= integer_traits< signed char >::const_max) );
+ (MaxValue <= integer_traits< signed char >::const_max)) );
   };
 
   template < intmax_t MinValue >
   struct int_min_rank_helper
   {
- BOOST_STATIC_CONSTANT( int, rank =
+ BOOST_STATIC_CONSTANT( int, rank = (MinValue < 0) * (
 #ifdef BOOST_HAS_LONG_LONG
        (MinValue >= integer_traits< long_long_type >::const_min) +
 #elif defined(BOOST_HAS_MS_INT64)
@@ -148,7 +190,7 @@
        (MinValue >= integer_traits< long >::const_min) +
        (MinValue >= integer_traits< int >::const_min) +
        (MinValue >= integer_traits< short >::const_min) +
- (MinValue >= integer_traits< signed char >::const_min) );
+ (MinValue >= integer_traits< signed char >::const_min)) );
   };
 
   template < uintmax_t Value >
@@ -168,12 +210,66 @@
        (Value <= integer_traits< unsigned char >::const_max) );
   };
 
+ // convert rank to type, Boost.MPL-style
+ template < int Rank, typename Signedness, class Enable = void >
+ struct integral_rank_to_type
+ {
+ BOOST_STATIC_CONSTANT( bool, is_specialized = false );
+ // No "signed" nor "type" here
+ };
+
+ template < int Rank >
+ struct integral_rank_to_type< Rank, signed, typename
+ enable_if_c<(lowest_integral_rank <= Rank) && (Rank <=
+ highest_integral_rank)>::type >
+ {
+ BOOST_STATIC_CONSTANT( bool, is_specialized = true );
+ BOOST_STATIC_CONSTANT( bool, is_signed = true );
+ typedef typename int_least_helper< Rank, signed >::least type;
+ };
+
+ template < int Rank >
+ struct integral_rank_to_type< Rank, unsigned, typename
+ enable_if_c<(lowest_integral_rank <= Rank) && (Rank <=
+ highest_integral_rank)>::type >
+ {
+ BOOST_STATIC_CONSTANT( bool, is_specialized = true );
+ BOOST_STATIC_CONSTANT( bool, is_signed = false );
+ typedef typename int_least_helper< Rank, unsigned >::least type;
+ };
+
 } // namespace detail
 
+ // MPL-compatible integer-mapping class templates ------------------------//
+
+ // exact number of bits
+ template < int Bits, typename Signedness >
+ struct exact_integral
+ {
+ BOOST_STATIC_CONSTANT( bool, is_specialized = false );
+ BOOST_STATIC_CONSTANT( int, bit_count = Bits );
+ };
+
+ template < int BitsIncludingSign >
+ struct exact_integral< BitsIncludingSign, signed >
+ : detail::integral_rank_to_type<
+ detail::int_exact_rank_helper<BitsIncludingSign>::rank, signed >
+ {
+ BOOST_STATIC_CONSTANT( int, bit_count = BitsIncludingSign );
+ };
+
+ template < int Bits >
+ struct exact_integral< Bits, unsigned >
+ : detail::integral_rank_to_type<
+ detail::uint_exact_rank_helper<Bits>::rank, unsigned >
+ {
+ BOOST_STATIC_CONSTANT( int, bit_count = Bits );
+ };
+
   // integer templates specifying number of bits ---------------------------//
 
   // signed
- template< int Bits > // bits (including sign) required
+ template< int Bits > // minimum bits (including sign) required
   struct int_t
   {
       typedef typename detail::int_least_helper
@@ -183,8 +279,14 @@
       typedef typename int_fast_t<least>::fast fast;
   };
 
+ template< int Bits > // exact bits (including sign) desired
+ struct int_exact_t
+ {
+ typedef typename exact_integral<Bits, signed>::type exact;
+ };
+
   // unsigned
- template< int Bits > // bits required
+ template< int Bits > // minimum bits required
   struct uint_t
   {
       typedef typename detail::int_least_helper
@@ -195,6 +297,12 @@
       // int_fast_t<> works correctly for unsigned too, in spite of the name.
   };
 
+ template< int Bits > // exact bits desired
+ struct uint_exact_t
+ {
+ typedef typename exact_integral<Bits, unsigned>::type exact;
+ };
+
   // integer templates specifying extreme value ----------------------------//
 
   // signed

Modified: trunk/boost/integer_fwd.hpp
==============================================================================
--- trunk/boost/integer_fwd.hpp (original)
+++ trunk/boost/integer_fwd.hpp 2008-07-15 05:59:19 EDT (Tue, 15 Jul 2008)
@@ -87,12 +87,21 @@
 template < typename LeastInt >
     struct int_fast_t;
 
+template < int Bits, typename Signedness >
+ struct exact_integral;
+
 template< int Bits >
     struct int_t;
 
 template< int Bits >
+ struct int_exact_t;
+
+template< int Bits >
     struct uint_t;
 
+template< int Bits >
+ struct uint_exact_t;
+
 template< intmax_t MaxValue >
     struct int_max_value_t;
 

Modified: trunk/libs/integer/integer.htm
==============================================================================
--- trunk/libs/integer/integer.htm (original)
+++ trunk/libs/integer/integer.htm 2008-07-15 05:59:19 EDT (Tue, 15 Jul 2008)
@@ -23,6 +23,7 @@
         <li>Synopsis</li>
         <li>Processor-Optimized Types</li>
         <li>Sized Types</li>
+ <li>MPL-Compatible Variants</li>
         <li>Example</li>
         <li>Demonstration Program</li>
         <li>Rationale</li>
@@ -32,7 +33,8 @@
 
 <h2><a name="synopsis">Synopsis</a></h2>
 
-<blockquote><pre>#include &lt;boost/integer_fwd.hpp&gt; // forwarding header
+<blockquote><pre>
+#include &lt;boost/integer_fwd.hpp&gt; // forwarding header
 #include &lt;boost/cstdint.hpp&gt; // for boost::uintmax_t, intmax_t
 
 namespace boost
@@ -52,6 +54,12 @@
       typedef int_fast_t&lt;least&gt;::fast fast;
   };
 
+ template&lt; int Bits &gt;
+ struct int_exact_t
+ {
+ typedef <em>implementation_supplied</em> exact;
+ };
+
   // unsigned
   template&lt; int Bits &gt;
   struct uint_t
@@ -60,6 +68,12 @@
       typedef int_fast_t&lt;least&gt;::fast fast;
   };
 
+ template&lt; int Bits &gt;
+ struct uint_exact_t
+ {
+ typedef <em>implementation_supplied</em> exact;
+ };
+
   // signed
   template&lt; intmax_t MaxValue &gt;
   struct int_max_value_t
@@ -82,6 +96,17 @@
       typedef <em>implementation_supplied</em> least;
       typedef int_fast_t&lt;least&gt;::fast fast;
   };
+
+ // MPL-compatible
+ template&lt; int Bits, typename Signedness &gt;
+ struct exact_integral
+ {
+ static bool const is_specialized = <em>implementation_supplied</em>;
+ static bool const is_signed = <em>implementation_supplied</em>;
+ static int const bit_count = Bits;
+
+ typedef <em>implementation_supplied</em> type;
+ };
 } // namespace boost
 </pre></blockquote>
 
@@ -107,65 +132,230 @@
 
 <h2><a name="sized">Sized Types</a></h2>
 
-<p>The <code>int_t</code>, <code>uint_t</code>,
-<code>int_max_value_t</code>, <code>int_min_value_t</code>, and
-<code>uint_value_t</code> class templates find the most appropiate
-built-in integral type for the given template parameter. This type is
-given by the class member <code>least</code>. The easiest-to-manipulate
-version of that type is given by the class member <code>fast</code>.
-The following table describes each template's criteria.</p>
+<p>The <code>int_t</code>, <code>int_exact_t</code>, <code>uint_t</code>,
+<code>uint_exact_t</code>, <code>int_max_value_t</code>,
+<code>int_min_value_t</code>, and <code>uint_value_t</code> class templates find
+the most appropriate built-in integral type for the given template parameter.
+This type is given by the class member <code>least</code> or <code>exact</code>.
+For the non-exact class templates, the easiest-to-manipulate version of that
+type is given by the class member <code>fast</code>. The following table
+describes each template's criteria.</p>
 
-<table border="1" cellpadding="5">
+<table border="2" cellpadding="5">
         <caption>Criteria for the Sized Type Class Templates</caption>
         <tr>
- <th>Class Template</th>
+ <th>Class Template (all in name-space <code>boost</code>)</th>
                 <th>Template Parameter Mapping</th>
         </tr>
         <tr>
- <td><code>boost::int_t</code></td>
+ <td><code>int_t</code></td>
                 <td>The smallest built-in signed integral type with at least the
                         given number of bits, including the sign bit. The parameter
- should be a positive number. A compile-time error results if
+ <em>must</em> be a positive number. A compile-time error results if
                         the parameter is larger than the number of bits in a
- <code>long</code>.</td>
+ <code>boost::intmax_t</code>.</td>
         </tr>
         <tr>
- <td><code>boost::uint_t</code></td>
+ <td><code>int_exact_t</code></td>
+ <td>The smallest built-in signed integral type with exactly the
+ given number of bits, including the sign bit. A compile-time error
+ results if no qualifying type exists.</td>
+ </tr>
+ <tr>
+ <td><code>uint_t</code></td>
                 <td>The smallest built-in unsigned integral type with at least
- the given number of bits. The parameter should be a positive
- number. A compile-time error results if the parameter is
- larger than the number of bits in an <code>unsigned
- long</code>.</td>
+ the given number of bits. The parameter <em>must</em> be a
+ non-negative number. A compile-time error results if the parameter
+ is larger than the number of bits in a
+ <code>boost::uintmax_t</code>.</td>
+ </tr>
+ <tr>
+ <td><code>uint_exact_t</code></td>
+ <td>The smallest built-in unsigned integral type with exactly the given
+ number of bits. A compile-time error results if no qualifying type
+ exists.</td>
         </tr>
         <tr>
- <td><code>boost::int_max_value_t</code></td>
+ <td><code>int_max_value_t</code></td>
                 <td>The smallest built-in signed integral type that supports the
- given value as a maximum. The parameter should be a
+ given value as a maximum. The parameter <em>must</em> be a
                         positive number.</td>
         </tr>
         <tr>
- <td><code>boost::int_min_value_t</code></td>
+ <td><code>int_min_value_t</code></td>
                 <td>The smallest built-in signed integral type that supports the
- given value as a minimum. The parameter should be a
+ given value as a minimum. The parameter <em>must</em> be a
                         negative number.</td>
         </tr>
         <tr>
- <td><code>boost::uint_value_t</code></td>
+ <td><code>uint_value_t</code></td>
                 <td>The smallest built-in unsigned integral type that supports
                         the given value as a maximum. The parameter should be a
                         positive number.</td>
         </tr>
 </table>
 
+<h2><a name="mpl">MPL-Compatible Variants</a></h2>
+
+<p>The bit-length sized-type class templates have several drawbacks:</p>
+
+<ul>
+ <li>You must know the valid bit-lengths in advance.</li>
+ <li>There is no way to inspect the parameter used after a size-type template
+ class is aliased.</li>
+ <li>Using an inappropriate parameter value results in a compiler
+ diagnostic.</li>
+ <li>The type names used are inconsistent with other transformations in
+ Boost, like in MPL.</li>
+ <li>The above two facts make use of the size-type class templates
+ incompatible with template meta-programming techniques.</li>
+</ul>
+
+<p>The <code>exact_integral</code> class template provides an MPL-compatible
+alternative. This alternative has the form:</p>
+
+<blockquote><pre>
+template&lt; <var>SwitchType</var> <var>SwitchValue</var>, typename Signedness &gt;
+struct <var>name</var>
+{
+ static bool const is_specialized = <em>implementation_supplied</em>;
+ static bool const is_signed = <em>implementation_supplied</em>;
+ static <var>SwitchType</var> const <var>switch_id</var> = <var>SwitchValue</var>;
+
+ typedef <em>implementation_supplied</em> type;
+};
+</pre></blockquote>
+
+<p>Each member, if present, is defined by:</p>
+
+<table border="2" cellpadding="5">
+ <caption>Members in MPL-Compatible Class Templates</caption>
+ <tr>
+ <th>Class Template Member</th>
+ <th>When Defined</th>
+ <th>Meaning</th>
+ </tr>
+ <tr>
+ <td><code>is_specialized</code></td>
+ <td>Always</td>
+ <td>Flag indicating when a particular template class instantiation is a
+ valid meta-function (<code>true</code>) or not (<code>false</code>).</td>
+ </tr>
+ <tr>
+ <td><code>is_signed</code></td>
+ <td><code>is_specialized == true</code></td>
+ <td>Flag indicating whether the signed-variant (<code>true</code>) or
+ the unsigned-variant (<code>false</code>) of the meta-function is
+ used. This is controlled by the <code>Signedness</code> template
+ parameter:
+ <table border="1" cellpadding="3" align="center">
+ <caption>Effect of <code>Signedness</code> Setting</caption>
+ <tr>
+ <th><code>Signedness</code> Type</th>
+ <th><code>is_signed</code></th>
+ </tr>
+ <tr>
+ <td><code>signed</code></td>
+ <td><code>true</code></td>
+ </tr>
+ <tr>
+ <td><code>unsigned</code></td>
+ <td><code>false</code></td>
+ </tr>
+ <tr>
+ <td>anything else</td>
+ <td><em>not defined</em></td>
+ </tr>
+ </table>
+ The type used is a programmer mnemonic; the compiler cannot prevent
+ someone from using <code>int</code> or <code>signed int</code>
+ instead of <code>signed</code>, or <code>unsigned int</code> instead
+ of <code>unsigned</code>.</td>
+ </tr>
+ <tr>
+ <td><code><var>switch_id</var></code> (Actual name is template-specific.)</td>
+ <td>Always</td>
+ <td>The value of the main control parameter, accessible even if the
+ template class instantiation is aliased.</td>
+ </tr>
+ <tr>
+ <td><code>type</code></td>
+ <td><code>is_specialized == true</code></td>
+ <td>The meta-function's result. It appears only if the input parameters
+ satisfy the template's requirements. It's presence, or lack thereof,
+ enables &quot;Substitution Failure Is Not An Error&quot; (SFINAE)
+ techniques, instead of a hard compiler diagnostic.</td>
+ </tr>
+</table>
+
+<p>The following table describes each template's criteria. The classic signed
+and unsigned equivalents are the sized-type class templates that each
+MPL-compatible class template emulates. (The setting of <var>Signedness</var>
+controls the appropriate emulation.)</p>
+
+<table border="2" cellpadding="5">
+ <caption>Criteria for the MPL-Compatible Class Templates</caption>
+ <tr>
+ <th rowspan="2">Class Template (all in name-space <code>boost</code>)</th>
+ <th rowspan="2">Parameter Type</th>
+ <th rowspan="2">Parameter Member ID</th>
+ <th colspan="2">Classic Equivalent</th>
+ <th rowspan="2">Template Parameter Mapping (when <code>type</code> is defined)</th>
+ </tr>
+ <tr>
+ <th>Signed</th>
+ <th>Unsigned</th>
+ </tr>
+ <tr>
+ <td><code>exact_integral</code></td>
+ <td><code>int</code></td>
+ <td><code>bit_count</code></td>
+ <td><code>int_exact_t</code></td>
+ <td><code>uint_exact_t</code></td>
+ <td>The smallest built-in integral type with exactly <code>bit_count</code>
+ bits (including the sign bit when <var>Signedness</var> is
+ <code>signed</code>). Not present if no type qualifies.</td>
+ </tr>
+</table>
+
 <h2><a name="example">Example</a></h2>
 
-<blockquote><pre>#include &lt;boost/integer.hpp&gt;
+<blockquote><pre>
+#include &lt;boost/integer.hpp&gt;
+#include &lt;boost/mpl/int.hpp&gt;
+#include &lt;iostream&gt;
+#include &lt;ostream&gt;
+
+//...
+
+template &lt; int Bits &gt;
+bool
+fit_exactly( boost::mpl::int_&lt;Bits&gt; const &amp;x,
+ typename boost::exact_integral&lt;Bits, signed&gt;::type *unused = 0 )
+{
+ return true;
+}
+
+template &lt; typename T &gt;
+bool
+fit_exactly( T const &amp;x )
+{
+ return false;
+}
 
 //...
 
 int main()
 {
- boost::int_t&lt;24&gt;::least my_var;
+ typedef boost::mpl::int_&lt;24&gt; twenty_four;
+
+ boost::int_t&lt;twenty_four::value&gt;::least my_var;
+
+ //...
+
+ std::cout &lt;&lt; &quot;my_var &quot; &lt;&lt; ( fit_exactly(twenty_four()) ? &quot;does&quot; :
+ &quot;does not&quot; ) &lt;&lt; &quot; fit its type exactly.&quot; &lt;&lt; std::endl;
+
     //...
 }
 </pre></blockquote>
@@ -201,11 +391,11 @@
 <a href="http://www.boost.org/people/kevlin_henney.htm"> Kevlin Henney</a> for sharing
 their designs for similar templates. <a
 href="http://www.boost.org/people/daryle_walker.html">Daryle Walker</a> designed the
-value-based sized templates.</p>
+exact and value-based sized templates, and the MPL-compatible templates.</p>
 
 <hr>
 
-<p>Revised July 14, 2008</p>
+<p>Revised July 15, 2008</p>
 
 <p>&copy; Copyright Beman Dawes 1999. Use, modification, and distribution are
 subject to the Boost Software License, Version 1.0. (See accompanying file <a

Modified: trunk/libs/integer/test/integer_test.cpp
==============================================================================
--- trunk/libs/integer/test/integer_test.cpp (original)
+++ trunk/libs/integer/test/integer_test.cpp 2008-07-15 05:59:19 EDT (Tue, 15 Jul 2008)
@@ -8,6 +8,7 @@
 // See http://www.boost.org/libs/integer for documentation.
 
 // Revision History
+// 15 Jul 08 Added exact-integer templates. (Daryle Walker)
 // 14 Jul 08 Improved testing of processor-optimized integer template; added
 // extended-integer support. (Daryle Walker)
 // 13 Jul 08 Modernized tests w/ MPL instead of giant macros (Daryle Walker)
@@ -19,7 +20,7 @@
 #define BOOST_TEST_MODULE "Integer size-selection tests"
 
 #include <boost/test/unit_test.hpp> // unit testing framework
-#include <boost/test/test_case_template.hpp> // ..BOOST_AUTO_TEST_CASE_TEMPLATE
+#include <boost/test/test_case_template.hpp>
 
 #include <boost/config.hpp> // for BOOST_NO_USING_TEMPLATE, etc.
 #include <boost/cstdint.hpp> // for boost::uintmax_t, intmax_t
@@ -47,10 +48,12 @@
 #include <boost/type_traits/is_same.hpp> // for boost::is_same
 #include <boost/type_traits/make_signed.hpp> // for boost::make_signed
 
-#include <climits> // for ULONG_MAX, LONG_MAX, LONG_MIN, etc.
-#include <iostream> // for std::cout
-#include <ostream> // for std::endl
-#include <typeinfo> // for std::type_info
+#include <algorithm> // for std::binary_search
+#include <climits> // for ULONG_MAX, LONG_MAX, LONG_MIN, etc.
+#include <cstddef> // for std::size_t
+#include <iostream> // for std::cout
+#include <ostream> // for std::endl
+#include <typeinfo> // for std::type_info
 
 
 // Control what the "fast" specialization of "short" is
@@ -104,9 +107,9 @@
 #if ULONG_MAX > UINT_MAX
     , unsigned long
 #endif
-#ifdef BOOST_HAS_LONG_LONG
+#if defined(BOOST_HAS_LONG_LONG) && ((ULLONG_MAX > ULONG_MAX) || (ULONGLONG_MAX > ULONG_MAX))
     , boost::ulong_long_type
-#elif defined(BOOST_HAS_MS_INT64)
+#elif defined(BOOST_HAS_MS_INT64) && (0xFFFFFFFFFFFFFFFFui64 > ULONG_MAX)
     , unsigned __int64
 #endif
> distinct_unsigned_types;
@@ -188,9 +191,77 @@
 // mantissa (don't want to shift into the sign bit)
 typedef boost::mpl::push_back<
     boost::mpl::pop_back< valid_bits_list >::type,
- boost::mpl::integral_c< int, intmax_bits - 2 >
+ boost::mpl::integral_c< int, intmax_bits - 3 >
>::type valid_to_increase_sbits_list;
 
+// List the digit counts for each integral type, this time as an object, an
+// array working as a sorted list
+int const integral_bit_lengths[] = {
+ std::numeric_limits< unsigned char >::digits
+#if USHRT_MAX > UCHAR_MAX
+ , std::numeric_limits< unsigned short >::digits
+#endif
+#if UINT_MAX > USHRT_MAX
+ , std::numeric_limits< unsigned int >::digits
+#endif
+#if ULONG_MAX > UINT_MAX
+ , std::numeric_limits< unsigned long >::digits
+#endif
+#if defined(BOOST_HAS_LONG_LONG) && ((ULLONG_MAX > ULONG_MAX) || (ULONGLONG_MAX > ULONG_MAX))
+ , std::numeric_limits< boost::ulong_long_type >::digits
+#elif defined(BOOST_HAS_MS_INT64) && (0xFFFFFFFFFFFFFFFFui64 > ULONG_MAX)
+ , std::numeric_limits< unsigned __int64 >::digits
+#endif
+};
+
+std::size_t const integral_type_count = sizeof(integral_bit_lengths) /
+ sizeof(integral_bit_lengths[0]);
+
+// Use SFINAE to check if a particular bit-count is supported
+template < int Bits >
+bool
+print_out_exact_signed( boost::mpl::integral_c<int, Bits> const &x, int bits,
+ typename boost::exact_integral<Bits, signed>::type *unused = 0 )
+{
+ // Too bad the type-id expression couldn't use the compact form "*unused",
+ // but type-ids of dereferenced null pointers throw by order of C++ 2003,
+ // sect. 5.2.8, para. 2 (although the result is not conceptually needed).
+
+ PRIVATE_SHOW_MESSAGE( "There is an exact_integral<" << bits <<
+ ", signed> specialization, with type '" << typeid(typename
+ boost::exact_integral<Bits, signed>::type).name() << "'." );
+ return true;
+}
+
+template < typename T >
+bool
+print_out_exact_signed( T const &x, int bits )
+{
+ PRIVATE_SHOW_MESSAGE( "There is no exact_integral<" << bits <<
+ ", signed> specialization." );
+ return false;
+}
+
+template < int Bits >
+bool
+print_out_exact_unsigned( boost::mpl::integral_c<int, Bits> const &x, int bits,
+ typename boost::exact_integral<Bits, unsigned>::type *unused = 0 )
+{
+ PRIVATE_SHOW_MESSAGE( "There is an exact_integral<" << bits <<
+ ", unsigned> specialization, with type '" << typeid(typename
+ boost::exact_integral<Bits, unsigned>::type).name() << "'." );
+ return true;
+}
+
+template < typename T >
+bool
+print_out_exact_unsigned( T const &x, int bits )
+{
+ PRIVATE_SHOW_MESSAGE( "There is no exact_integral<" << bits <<
+ ", unsigned> specialization." );
+ return false;
+}
+
 } // unnamed namespace
 
 
@@ -225,7 +296,7 @@
 // Check if given types can support given size parameters
 BOOST_AUTO_TEST_SUITE( show_type_tests )
 
-// Check the specialization type status of given bit lengths
+// Check the specialization type status of given bit lengths, exact or higher
 BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_lengths_test, T, valid_bits_list )
 {
     // This test is supposed to replace the following printouts given in
@@ -348,6 +419,42 @@
      typename int_t<count + 1>::least>::value) );
 }
 
+// Check the specialization type status of given bit lengths, exact only
+BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_exact_lengths_test, T, bits_list )
+{
+#ifndef BOOST_NO_USING_TEMPLATE
+ using std::binary_search;
+#else
+ using namespace std;
+#endif
+
+ BOOST_CHECK_EQUAL( print_out_exact_signed(T(), T::value),
+ binary_search(integral_bit_lengths, integral_bit_lengths +
+ integral_type_count, T::value) );
+ BOOST_CHECK_EQUAL( print_out_exact_unsigned(T(), T::value),
+ binary_search(integral_bit_lengths, integral_bit_lengths +
+ integral_type_count, T::value) );
+}
+
+// Check the classic specialization type status of given bit lengths, exact only
+BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_exact_lengths_test, T,
+ distinct_integral_bit_counts )
+{
+#ifndef BOOST_NO_USING_TEMPLATE
+ using std::numeric_limits;
+ using boost::int_exact_t;
+ using boost::uint_exact_t;
+#else
+ using namespace std;
+ using namespace boost;
+#endif
+
+ BOOST_MPL_ASSERT_RELATION( numeric_limits<typename
+ int_exact_t<T::value>::exact>::digits, ==, T::value - 1 );
+ BOOST_MPL_ASSERT_RELATION( numeric_limits<typename
+ uint_exact_t<T::value>::exact>::digits, ==, T::value );
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 // Check if given constants can fit in given types
@@ -398,8 +505,36 @@
      1 );
 }
 
-// Check if large value can fit its minimum required size, by value
-BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_values_test, T,
+// Check if a large value can only fit of its exact bit length
+BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_exact_lengths_test, T,
+ distinct_integral_bit_counts )
+{
+#ifndef BOOST_NO_USING_TEMPLATE
+ using boost::exact_integral;
+#else
+ using namespace boost;
+#endif
+
+ typedef typename exact_integral<T::value, unsigned>::type uexact_type;
+ typedef typename exact_integral<T::value, signed>::type sexact_type;
+
+ uexact_type const one_u( 1u ), high_bit_u( one_u << (T::value - 1) ),
+ repeated_bits_u( (high_bit_u << 1) | high_bit_u );
+
+ BOOST_CHECK( high_bit_u );
+ BOOST_CHECK_EQUAL( repeated_bits_u, high_bit_u );
+
+ sexact_type const one_s( 1 ), high_bit_s( one_s << (T::value - 2) ),
+ repeated_bits_s( (high_bit_s << 1) | high_bit_s ),
+ repeated_2bits_s( (repeated_bits_s << 1) | high_bit_s );
+
+ BOOST_CHECK( high_bit_s > 0 );
+ BOOST_CHECK( repeated_bits_s < 0 );
+ BOOST_CHECK_EQUAL( repeated_bits_s, repeated_2bits_s );
+}
+
+// Check if large value can fit its minimum required size, by value, unsigned
+BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_unsigned_values_test, T,
  valid_to_increase_ubits_list )
 {
     // This test is supposed to replace the following checks given in
@@ -409,28 +544,21 @@
     // Confirm( static_cast<typename Template<V>::Type>(V) == V );
     // end for
     // end Routine
- // with Template = {uint_value_t, int_max_value_t, int_min_value_t}; Type =
- // {least, fast}; Template:Extreme = {intmax_t.Min for int_min_value_t,
- // intmax_t.Max for int_max_value_t, uintmax_t.Max for uint_value_t}
+ // with Template = {uint_value_t}; Type = {least, fast}; Template:Extreme =
+ // {uintmax_t.Max for uint_value_t}
     // In other words, the selected type doesn't mask out any bits it's not
     // supposed to. But now we'll use template meta-programming instead of
     // macros. The limit of type-lists is usually less than 32 (not to mention
     // 64) elements, so we have to take selected values.
     using boost::uintmax_t;
- using boost::intmax_t;
 #ifndef BOOST_NO_USING_TEMPLATE
- using boost::integer_traits;
     using boost::uint_value_t;
- using boost::int_max_value_t;
- using boost::int_min_value_t;
 #else
     using namespace boost;
 #endif
 
- int const shift = T::value;
- uintmax_t const max_u = integer_traits<uintmax_t>::const_max >> shift;
- intmax_t const max_s = integer_traits<intmax_t>::const_max >> shift,
- min_s = integer_traits<intmax_t>::const_min >> shift;
+ uintmax_t const max_u = boost::integer_traits<uintmax_t>::const_max >>
+ T::value;
 
     BOOST_CHECK_EQUAL( typename uint_value_t<max_u>::least(max_u), max_u );
     BOOST_CHECK_EQUAL( typename uint_value_t<(max_u >> 1)>::least(max_u >> 1),
@@ -438,6 +566,38 @@
     BOOST_CHECK_EQUAL( typename uint_value_t<max_u>::fast(max_u), max_u );
     BOOST_CHECK_EQUAL( typename uint_value_t<(max_u >> 1)>::fast(max_u >> 1),
      max_u >> 1 );
+}
+
+// Check if large value can fit its minimum required size, by value, signed
+BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_signed_values_test, T,
+ valid_to_increase_sbits_list )
+{
+ // This test is supposed to replace the following checks given in
+ // puesdo-code by:
+ // Routine: Template, Type
+ // for ( N = 0, V = Template:Extreme ; N < 32 ; ++N, V >>= 1 )
+ // Confirm( static_cast<typename Template<V>::Type>(V) == V );
+ // end for
+ // end Routine
+ // with Template = {int_max_value_t, int_min_value_t}; Type = {least, fast};
+ // Template:Extreme = {intmax_t.Min for int_min_value_t, intmax_t.Max
+ // for int_max_value_t}
+ // In other words, the selected type doesn't mask out any bits it's not
+ // supposed to. But now we'll use template meta-programming instead of
+ // macros. The limit of type-lists is usually less than 32 (not to mention
+ // 64) elements, so we have to take selected values.
+ using boost::intmax_t;
+#ifndef BOOST_NO_USING_TEMPLATE
+ using boost::integer_traits;
+ using boost::int_max_value_t;
+ using boost::int_min_value_t;
+#else
+ using namespace boost;
+#endif
+
+ int const shift = T::value;
+ intmax_t const max_s = integer_traits<intmax_t>::const_max >> shift,
+ min_s = integer_traits<intmax_t>::const_min >> shift;
 
     BOOST_CHECK_EQUAL( typename int_max_value_t<max_s>::least(max_s), max_s );
     BOOST_CHECK_EQUAL( typename int_max_value_t<(max_s >> 1)>::least(max_s >>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk