Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84972 - in trunk: boost/multiprecision boost/multiprecision/cpp_int boost/multiprecision/detail libs/multiprecision/test
From: john_at_[hidden]
Date: 2013-07-07 11:29:02


Author: johnmaddock
Date: 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013)
New Revision: 84972
URL: http://svn.boost.org/trac/boost/changeset/84972

Log:
Reorganise bit scanning code.
Add tests for msb function.

Added:
   trunk/boost/multiprecision/detail/bitscan.hpp (contents, props changed)
Text files modified:
   trunk/boost/multiprecision/cpp_int/misc.hpp | 110 ++++++++-----------
   trunk/boost/multiprecision/detail/bitscan.hpp | 218 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/multiprecision/detail/default_ops.hpp | 8 +
   trunk/boost/multiprecision/gmp.hpp | 14 ++
   trunk/boost/multiprecision/integer.hpp | 20 ---
   trunk/boost/multiprecision/tommath.hpp | 14 ++
   trunk/libs/multiprecision/test/test_arithmetic.hpp | 1
   trunk/libs/multiprecision/test/test_cpp_int.cpp | 2
   trunk/libs/multiprecision/test/test_native_integer.cpp | 9 +
   9 files changed, 317 insertions(+), 79 deletions(-)

Modified: trunk/boost/multiprecision/cpp_int/misc.hpp
==============================================================================
--- trunk/boost/multiprecision/cpp_int/misc.hpp Sun Jul 7 08:59:57 2013 (r84971)
+++ trunk/boost/multiprecision/cpp_int/misc.hpp 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013) (r84972)
@@ -8,6 +8,8 @@
 #ifndef BOOST_MP_CPP_INT_MISC_HPP
 #define BOOST_MP_CPP_INT_MISC_HPP
 
+#include <boost/multiprecision/detail/bitscan.hpp> // lsb etc
+
 #ifdef BOOST_MSVC
 #pragma warning(push)
 #pragma warning(disable:4702)
@@ -107,64 +109,6 @@
    result.sign(false);
 }
 
-template <class Unsigned, class Tag>
-inline unsigned find_lsb(Unsigned mask, const Tag&)
-{
- unsigned result = 0;
- while(!(mask & 1u))
- {
- mask >>= 1;
- ++result;
- }
- return result;
-}
-
-#if defined(BOOST_MSVC) && (defined(_M_IX86) || defined(_M_X64))
-BOOST_FORCEINLINE unsigned find_lsb(limb_type mask, const mpl::int_<32>&)
-{
- unsigned long result;
- _BitScanForward(&result, mask);
- return result;
-}
-#ifdef _M_X64
-BOOST_FORCEINLINE unsigned find_lsb(limb_type mask, const mpl::int_<64>&)
-{
- unsigned long result;
- _BitScanForward64(&result, mask);
- return result;
-}
-#endif
-#endif
-
-#if defined(__GNUC__)
-BOOST_FORCEINLINE unsigned find_lsb_imp(limb_type mask, mpl::true_ const&)
-{
- return __builtin_ctz(mask);
-}
-BOOST_FORCEINLINE unsigned find_lsb_imp(limb_type mask, mpl::false_ const&)
-{
- return __builtin_ctzll(mask);
-}
-template <class Tag>
-BOOST_FORCEINLINE unsigned find_lsb(limb_type mask, const Tag&)
-{
- return find_lsb_imp(mask, mpl::bool_<Tag::value <= static_cast<int>(sizeof(unsigned int) * CHAR_BIT)>());
-}
-#elif defined(BOOST_INTEL)
-BOOST_FORCEINLINE unsigned find_lsb_imp(limb_type mask, mpl::true_ const&)
-{
- return _bit_scan_forward(mask);
-}
-BOOST_FORCEINLINE unsigned find_lsb_imp(limb_type mask, mpl::false_ const&)
-{
- return find_lsb<limb_type, mpl::int_<0> >(mask, mpl::int_<0>());
-}
-template <class Tag>
-BOOST_FORCEINLINE unsigned find_lsb(limb_type mask, const Tag&)
-{
- return find_lsb_imp(mask, mpl::bool_<Tag::value <= sizeof(int) * CHAR_BIT>());
-}
-#endif
 //
 // Get the location of the least-significant-bit:
 //
@@ -191,11 +135,34 @@
    //
    // Find the index of the least significant bit within that limb:
    //
- unsigned result = find_lsb(a.limbs()[index], mpl::int_<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits>());
+ unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]);
 
    return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
 }
 
+//
+// Get the location of the most-significant-bit:
+//
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
+ eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
+{
+ using default_ops::eval_get_sign;
+ if(eval_get_sign(a) == 0)
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ }
+ if(a.sign())
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ }
+
+ //
+ // Find the index of the most significant bit that is non-zero:
+ //
+ return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);
+}
+
 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
    eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
@@ -307,7 +274,7 @@
       if(u == v)
          break;
       v -= u;
- v >>= find_lsb(v, mpl::int_<CHAR_BIT * sizeof(limb_type)>());
+ v >>= boost::multiprecision::detail::find_lsb(v);
    } while(true);
    return u;
 }
@@ -369,7 +336,7 @@
    dividing both u and v. */
 
    unsigned us = eval_lsb(u);
- unsigned vs = find_lsb(v, mpl::int_<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits>());
+ unsigned vs = boost::multiprecision::detail::find_lsb(v);
    shift = (std::min)(us, vs);
    eval_right_shift(u, us);
    if(vs)
@@ -587,7 +554,26 @@
    //
    // Find the index of the least significant bit within that limb:
    //
- return find_lsb(*a.limbs(), mpl::int_<CHAR_BIT * sizeof(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type)>());
+ return boost::multiprecision::detail::find_lsb(*a.limbs());
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
+ eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
+{
+ using default_ops::eval_get_sign;
+ if(eval_get_sign(a) == 0)
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ }
+ if(a.sign())
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ }
+ //
+ // Find the index of the least significant bit within that limb:
+ //
+ return boost::multiprecision::detail::find_msb(*a.limbs());
 }
 
 #ifdef BOOST_MSVC

Added: trunk/boost/multiprecision/detail/bitscan.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/multiprecision/detail/bitscan.hpp 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013) (r84972)
@@ -0,0 +1,218 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2013 John Maddock. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+//
+// Comparison operators for cpp_int_backend:
+//
+#ifndef BOOST_MP_DETAIL_BITSCAN_HPP
+#define BOOST_MP_DETAIL_BITSCAN_HPP
+
+namespace boost{ namespace multiprecision{ namespace detail{
+
+template <class Unsigned>
+inline unsigned find_lsb(Unsigned mask, const mpl::int_<0>&)
+{
+ unsigned result = 0;
+ while(!(mask & 1u))
+ {
+ mask >>= 1;
+ ++result;
+ }
+ return result;
+}
+
+template <class Unsigned>
+inline unsigned find_msb(Unsigned mask, const mpl::int_<0>&)
+{
+ unsigned index = 0;
+ while(mask)
+ {
+ ++index;
+ mask >>= 1;
+ }
+ return --index;
+}
+
+#if defined(BOOST_MSVC) && (defined(_M_IX86) || defined(_M_X64))
+BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, const mpl::int_<1>&)
+{
+ unsigned long result;
+ _BitScanForward(&result, mask);
+ return result;
+}
+
+BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, const mpl::int_<1>&)
+{
+ unsigned long result;
+ _BitScanReverse(&result, mask);
+ return result;
+}
+#ifdef _M_X64
+BOOST_FORCEINLINE unsigned find_lsb(unsigned __int64, const mpl::int_<2>&)
+{
+ unsigned long result;
+ _BitScanForward64(&result, mask);
+ return result;
+}
+template <class Unsigned>
+BOOST_FORCEINLINE unsigned find_msb(Unsigned mask, const mpl::int_<2>&)
+{
+ unsigned long result;
+ _BitScanReverse64(&result, mask);
+ return result;
+}
+#endif
+
+template <class Unsigned>
+BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
+{
+ typedef typename make_unsigned<Unsigned>::type ui_type;
+ typedef typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned long),
+ mpl::int_<1>,
+#ifdef _M_X64
+ typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(__int64),
+ mpl::int_<2>,
+ mpl::int_<0>
+ >::type
+#else
+ mpl::int_<0>
+#endif
+ >::type tag_type;
+ return find_lsb(static_cast<ui_type>(mask), tag_type());
+}
+
+template <class Unsigned>
+BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
+{
+ typedef typename make_unsigned<Unsigned>::type ui_type;
+ typedef typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned long),
+ mpl::int_<1>,
+#ifdef _M_X64
+ typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(__int64),
+ mpl::int_<2>,
+ mpl::int_<0>
+ >::type
+#else
+ mpl::int_<0>
+#endif
+ >::type tag_type;
+ return find_msb(static_cast<ui_type>(mask), tag_type());
+}
+
+#elif defined(BOOST_GCC)
+BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
+{
+ return __builtin_ctz(mask);
+}
+BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, mpl::int_<2> const&)
+{
+ return __builtin_ctzl(mask);
+}
+BOOST_FORCEINLINE unsigned find_lsb(unsigned long long mask, mpl::int_<3> const&)
+{
+ return __builtin_ctzll(mask);
+}
+BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
+{
+ return sizeof(unsigned) * CHAR_BIT - 1 - __builtin_clz(mask);
+}
+BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, mpl::int_<2> const&)
+{
+ return sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(mask);
+}
+BOOST_FORCEINLINE unsigned find_msb(unsigned long long mask, mpl::int_<3> const&)
+{
+ return sizeof(unsigned long long) * CHAR_BIT - 1 - __builtin_clzll(mask);
+}
+
+template <class Unsigned>
+BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
+{
+ typedef typename make_unsigned<Unsigned>::type ui_type;
+ typedef typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned),
+ mpl::int_<1>,
+ typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned long),
+ mpl::int_<2>,
+ typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned long long),
+ mpl::int_<3>,
+ mpl::int_<0>
+ >::type
+ >::type
+ >::type tag_type;
+ return find_lsb(static_cast<ui_type>(mask), tag_type());
+}
+template <class Unsigned>
+BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
+{
+ typedef typename make_unsigned<Unsigned>::type ui_type;
+ typedef typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned),
+ mpl::int_<1>,
+ typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned long),
+ mpl::int_<2>,
+ typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned long long),
+ mpl::int_<3>,
+ mpl::int_<0>
+ >::type
+ >::type
+ >::type tag_type;
+ return find_msb(static_cast<ui_type>(mask), tag_type());
+}
+#elif defined(BOOST_INTEL)
+BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
+{
+ return _bit_scan_forward(mask);
+}
+BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
+{
+ return _bit_scan_reverse(mask);
+}
+template <class Unsigned>
+BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
+{
+ typedef typename make_unsigned<Unsigned>::type ui_type;
+ typedef typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned),
+ mpl::int_<1>,
+ mpl::int_<0>
+ >::type tag_type;
+ return find_lsb(static_cast<ui_type>(mask), tag_type());
+}
+template <class Unsigned>
+BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
+{
+ typedef typename make_unsigned<Unsigned>::type ui_type;
+ typedef typename mpl::if_c<
+ sizeof(Unsigned) <= sizeof(unsigned),
+ mpl::int_<1>,
+ mpl::int_<0>
+ >::type tag_type;
+ return find_msb(static_cast<ui_type>(mask), tag_type());
+}
+#else
+template <class Unsigned>
+BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
+{
+ return find_lsb(mask, mpl::int_<0>());
+}
+template <class Unsigned>
+BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
+{
+ return find_msb(mask, mpl::int_<0>());
+}
+#endif
+
+}}}
+
+#endif
+

Modified: trunk/boost/multiprecision/detail/default_ops.hpp
==============================================================================
--- trunk/boost/multiprecision/detail/default_ops.hpp Sun Jul 7 08:59:57 2013 (r84971)
+++ trunk/boost/multiprecision/detail/default_ops.hpp 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013) (r84972)
@@ -1055,6 +1055,14 @@
    {
       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
    }
+ //
+ // This implementation is really really rubbish - it does
+ // a linear scan for the most-significant-bit. We should really
+ // do a binary search, but as none of our backends actually needs
+ // this implementation, we'll leave it for now. In fact for most
+ // backends it's likely that there will always be a more efficient
+ // native implementation possible.
+ //
    unsigned result = 0;
    T t(val);
    while(!eval_is_zero(t))

Modified: trunk/boost/multiprecision/gmp.hpp
==============================================================================
--- trunk/boost/multiprecision/gmp.hpp Sun Jul 7 08:59:57 2013 (r84971)
+++ trunk/boost/multiprecision/gmp.hpp 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013) (r84972)
@@ -1606,6 +1606,20 @@
    return mpz_scan1(val.data(), 0);
 }
 
+inline unsigned eval_msb(const gmp_int& val)
+{
+ int c = eval_get_sign(val);
+ if(c == 0)
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ }
+ if(c < 0)
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ }
+ return mpz_sizeinbase(val.data(), 2) - 1;
+}
+
 inline bool eval_bit_test(const gmp_int& val, unsigned index)
 {
    return mpz_tstbit(val.data(), index) ? true : false;

Modified: trunk/boost/multiprecision/integer.hpp
==============================================================================
--- trunk/boost/multiprecision/integer.hpp Sun Jul 7 08:59:57 2013 (r84971)
+++ trunk/boost/multiprecision/integer.hpp 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013) (r84972)
@@ -7,6 +7,7 @@
 #define BOOST_MP_INTEGER_HPP
 
 #include <boost/multiprecision/cpp_int.hpp>
+#include <boost/multiprecision/detail/bitscan.hpp>
 
 namespace boost{
 namespace multiprecision{
@@ -114,15 +115,7 @@
          BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
       }
    }
- unsigned index = 0;
- Integer mask = 1;
-
- while(((mask & val) == 0) && (index < sizeof(Integer) * CHAR_BIT))
- {
- ++index;
- mask <<= 1;
- }
- return index;
+ return detail::find_lsb(val);
 }
 
 template <class Integer>
@@ -139,14 +132,7 @@
          BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
       }
    }
- unsigned index = 0;
-
- while(val)
- {
- ++index;
- val >>= 1;
- }
- return --index;
+ return detail::find_msb(val);
 }
 
 template <class Integer>

Modified: trunk/boost/multiprecision/tommath.hpp
==============================================================================
--- trunk/boost/multiprecision/tommath.hpp Sun Jul 7 08:59:57 2013 (r84971)
+++ trunk/boost/multiprecision/tommath.hpp 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013) (r84972)
@@ -609,6 +609,20 @@
    return mp_cnt_lsb(const_cast< ::mp_int*>(&val.data()));
 }
 
+inline unsigned eval_msb(const tommath_int& val)
+{
+ int c = eval_get_sign(val);
+ if(c == 0)
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ }
+ if(c < 0)
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ }
+ return mp_count_bits(const_cast< ::mp_int*>(&val.data())) - 1;
+}
+
 template <class Integer>
 inline typename enable_if<is_unsigned<Integer>, Integer>::type eval_integer_modulus(const tommath_int& x, Integer val)
 {

Modified: trunk/libs/multiprecision/test/test_arithmetic.hpp
==============================================================================
--- trunk/libs/multiprecision/test/test_arithmetic.hpp Sun Jul 7 08:59:57 2013 (r84971)
+++ trunk/libs/multiprecision/test/test_arithmetic.hpp 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013) (r84972)
@@ -557,6 +557,7 @@
       if(std::numeric_limits<Real>::is_specialized && (!std::numeric_limits<Real>::is_bounded || ((int)i * 17 < std::numeric_limits<Real>::digits)))
       {
          BOOST_CHECK_EQUAL(lsb(Real(1) << (i * 17)) , i * 17);
+ BOOST_CHECK_EQUAL(msb(Real(1) << (i * 17)) , i * 17);
          BOOST_CHECK(bit_test(Real(1) << (i * 17), i * 17));
          BOOST_CHECK(!bit_test(Real(1) << (i * 17), i * 17 + 1));
          if(i)

Modified: trunk/libs/multiprecision/test/test_cpp_int.cpp
==============================================================================
--- trunk/libs/multiprecision/test/test_cpp_int.cpp Sun Jul 7 08:59:57 2013 (r84971)
+++ trunk/libs/multiprecision/test/test_cpp_int.cpp 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013) (r84972)
@@ -341,6 +341,7 @@
       BOOST_CHECK_EQUAL(z2.str(), t2.str());
       BOOST_CHECK_EQUAL(integer_modulus(a, si), integer_modulus(a1, si));
       BOOST_CHECK_EQUAL(lsb(a), lsb(a1));
+ BOOST_CHECK_EQUAL(msb(a), msb(a1));
 
       for(unsigned i = 0; i < 1000; i += 13)
       {
@@ -357,6 +358,7 @@
          BOOST_CHECK_EQUAL(mpz_int(powm(a, ui, c)).str(), test_type(powm(a1, ui, c1)).str());
       }
       BOOST_CHECK_EQUAL(lsb(a), lsb(a1));
+ BOOST_CHECK_EQUAL(msb(a), msb(a1));
    }
 
    void test_bug_cases()

Modified: trunk/libs/multiprecision/test/test_native_integer.cpp
==============================================================================
--- trunk/libs/multiprecision/test/test_native_integer.cpp Sun Jul 7 08:59:57 2013 (r84971)
+++ trunk/libs/multiprecision/test/test_native_integer.cpp 2013-07-07 11:29:01 EDT (Sun, 07 Jul 2013) (r84972)
@@ -35,6 +35,13 @@
    BOOST_CHECK(bit_test(bit_set(i, max_index), max_index));
    BOOST_CHECK_EQUAL(bit_unset(i, max_index), 0);
    BOOST_CHECK_EQUAL(bit_flip(bit_set(i, max_index), max_index), 0);
+ i = 0;
+ bit_set(i, max_index);
+ BOOST_CHECK_EQUAL(lsb(i), max_index);
+ BOOST_CHECK_EQUAL(msb(i), max_index);
+ bit_set(i, max_index / 2);
+ BOOST_CHECK_EQUAL(lsb(i), max_index / 2);
+ BOOST_CHECK_EQUAL(msb(i), max_index);
 
    if(std::numeric_limits<I>::is_signed)
    {
@@ -67,8 +74,10 @@
 {
    using namespace boost::multiprecision;
 
+ test<boost::int16_t, boost::int8_t>();
    test<boost::int32_t, boost::int16_t>();
    test<boost::int64_t, boost::int32_t>();
+ test<boost::uint16_t, boost::uint8_t>();
    test<boost::uint32_t, boost::uint16_t>();
    test<boost::uint64_t, boost::uint32_t>();
    


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