$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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 <boost/integer_fwd.hpp>  // forwarding header
+<blockquote><pre>
+#include <boost/integer_fwd.hpp>  // forwarding header
 #include <boost/cstdint.hpp>      // for boost::uintmax_t, intmax_t
 
 namespace boost
@@ -52,6 +54,12 @@
       typedef int_fast_t<least>::fast  fast;
   };
 
+  template< int Bits >
+  struct int_exact_t
+  {
+      typedef <em>implementation_supplied</em>  exact;
+  };
+
   //  unsigned
   template< int Bits >
   struct uint_t 
@@ -60,6 +68,12 @@
       typedef int_fast_t<least>::fast  fast;
   };
 
+  template< int Bits >
+  struct uint_exact_t
+  {
+      typedef <em>implementation_supplied</em>  exact;
+  };
+
   //  signed
   template< intmax_t MaxValue >
   struct int_max_value_t 
@@ -82,6 +96,17 @@
       typedef <em>implementation_supplied</em>  least;
       typedef int_fast_t<least>::fast  fast;
   };
+
+  //  MPL-compatible
+  template< int Bits, typename Signedness >
+  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< <var>SwitchType</var> <var>SwitchValue</var>, typename Signedness >
+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 "Substitution Failure Is Not An Error" (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 <boost/integer.hpp>
+<blockquote><pre>
+#include <boost/integer.hpp>
+#include <boost/mpl/int.hpp>
+#include <iostream>
+#include <ostream>
+
+//...
+
+template < int Bits >
+bool
+fit_exactly( boost::mpl::int_<Bits> const &x,
+ typename boost::exact_integral<Bits, signed>::type *unused = 0 )
+{
+    return true;
+}
+
+template < typename T >
+bool
+fit_exactly( T const &x )
+{
+    return false;
+}
 
 //...
 
 int main()
 {
-    boost::int_t<24>::least my_var;
+    typedef boost::mpl::int_<24>  twenty_four;
+
+    boost::int_t<twenty_four::value>::least my_var;
+
+    //...
+
+    std::cout << "my_var " << ( fit_exactly(twenty_four()) ? "does" :
+     "does not" ) << " fit its type exactly." << 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>© 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 >>