From 0d058f42cc2d7efbf3f6e241cd995e0954e97ca6 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Tue, 6 Nov 2007 13:41:19 +0000 Subject: [PATCH 01/23] Add missing copyright and license [SVN r40835] --- cstdint.htm | 11 +++++++---- index.html | 9 +++++++-- integer_traits.html | 9 +++++++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/cstdint.htm b/cstdint.htm index 43b828f..9492827 100644 --- a/cstdint.htm +++ b/cstdint.htm @@ -2,7 +2,7 @@ - + Header boost/cstdint.hpp @@ -69,10 +69,13 @@ representing any value of any signed integer type.

capable of representing any value of any unsigned integer type.

These types are required.


-

Revised 19 Aug 2001 +

Revised 06 Nov 2007

-

 

+

© Copyright Beman Dawes 2000

+ +

Distributed under the Boost Software License, Version 1.0. See +www.boost.org/LICENSE_1_0.txt

- + \ No newline at end of file diff --git a/index.html b/index.html index 7ab3ea0..0a6bbb0 100644 --- a/index.html +++ b/index.html @@ -121,8 +121,13 @@ instead.


-

Revised: 03 Oct 2001 +

Revised: 06 Nov 2007

+

© Copyright Beman Dawes 2003

+ +

Distributed under the Boost Software License, Version 1.0. See +www.boost.org/LICENSE_1_0.txt

+ - + \ No newline at end of file diff --git a/integer_traits.html b/integer_traits.html index b52b76a..6fc75b8 100644 --- a/integer_traits.html +++ b/integer_traits.html @@ -85,5 +85,10 @@ exercises the integer_traits class. Beman Dawes, Ed Brey, Steve Cleary, and Nathan Myers discussed the integer traits idea on the boost mailing list in August 1999.
- -Jens Maurer, 2000-02-20 \ No newline at end of file +

Revised +06 November 2007

+

© Copyright Beman Dawes 2000

+ +

Distributed under the Boost Software License, Version 1.0. See +www.boost.org/LICENSE_1_0.txt

+ From cd6a9565ff450559c84f6cdcf4d12864e34766b6 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 9 Feb 2008 13:02:45 +0000 Subject: [PATCH 02/23] Fix the link to the license. [SVN r43193] --- integer.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integer.htm b/integer.htm index 4dfd977..37f6c19 100644 --- a/integer.htm +++ b/integer.htm @@ -206,7 +206,7 @@ value-based sized templates.

© Copyright Beman Dawes 1999. Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or a copy at <LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

- \ No newline at end of file + From 94ace806183f7e9d8a2cb97e20e7617d4f1b9e42 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 14:56:22 +0000 Subject: [PATCH 03/23] Link to people pages on the website, as they've been removed from the download. [SVN r43209] --- doc/integer_mask.html | 2 +- doc/static_log2.html | 2 +- doc/static_min_max.html | 2 +- index.html | 2 +- integer.htm | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/integer_mask.html b/doc/integer_mask.html index 0328bbc..5bc7301 100644 --- a/doc/integer_mask.html +++ b/doc/integer_mask.html @@ -196,7 +196,7 @@ contaimination of values by the higher, unused bits.

Credits

The author of the Boost bit mask class templates is Daryle Walker.

+href="http://www.boost.org/people/daryle_walker.html">Daryle Walker.


diff --git a/doc/static_log2.html b/doc/static_log2.html index e353da4..b77874c 100644 --- a/doc/static_log2.html +++ b/doc/static_log2.html @@ -186,7 +186,7 @@ code (and update old code as soon as possible).

The original version of the Boost binary logarithm class template was -written by Daryle Walker +written by Daryle Walker and then enhanced by Giovanni Bajo with support for compilers without partial template specialization. The current version was suggested, together with a reference implementation, by Vesa Karvonen. Gennaro Prota diff --git a/doc/static_min_max.html b/doc/static_min_max.html index 8163aa4..1beb503 100644 --- a/doc/static_min_max.html +++ b/doc/static_min_max.html @@ -106,7 +106,7 @@ class template.

Credits

The author of the Boost compile-time extrema class templates is Daryle Walker.

+href="http://www.boost.org/people/daryle_walker.html">Daryle Walker.


diff --git a/index.html b/index.html index 0a6bbb0..033af09 100644 --- a/index.html +++ b/index.html @@ -10,7 +10,7 @@ boost.png (6897 bytes) Home Libraries - People + People FAQ More diff --git a/integer.htm b/integer.htm index 37f6c19..3d3f9c5 100644 --- a/integer.htm +++ b/integer.htm @@ -193,11 +193,11 @@ href="../../boost/cstdint.hpp"><boost/cstdint.hpp>.

Credits

The author of most of the Boost integer type choosing templates is Beman Dawes. He gives thanks +href="http://www.boost.org/people/beman_dawes.html">Beman Dawes. He gives thanks to Valentin Bonnard and - Kevlin Henney for sharing + Kevlin Henney for sharing their designs for similar templates. Daryle Walker designed the +href="http://www.boost.org/people/daryle_walker.html">Daryle Walker designed the value-based sized templates.


From 4e2c8440b559cec5bd3a967a7b09dac406a9416f Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 15:02:17 +0000 Subject: [PATCH 04/23] Point links to the pages that used to be in 'more' to the site. [SVN r43210] --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 033af09..1f0f83c 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,7 @@ Home Libraries People - FAQ + FAQ More From 600801670ea4fcfd4a3ad2f3ff0357e157115079 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sun, 13 Apr 2008 23:00:19 +0000 Subject: [PATCH 05/23] Move integer tests into canonical test subdir structure. [SVN r44384] --- integer_traits.html | 2 +- test/Jamfile.v2 | 12 ++++++++++++ cstdint_test.cpp => test/cstdint_test.cpp | 0 integer_test.cpp => test/integer_test.cpp | 0 .../integer_traits_test.cpp | 0 5 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/Jamfile.v2 rename cstdint_test.cpp => test/cstdint_test.cpp (100%) rename integer_test.cpp => test/integer_test.cpp (100%) rename integer_traits_test.cpp => test/integer_traits_test.cpp (100%) diff --git a/integer_traits.html b/integer_traits.html index 6fc75b8..0a9f80d 100644 --- a/integer_traits.html +++ b/integer_traits.html @@ -77,7 +77,7 @@ Test Program

-The program integer_traits_test.cpp +The program integer_traits_test.cpp exercises the integer_traits class.

Acknowledgements

diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 0000000..c75db05 --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,12 @@ +#~ Copyright Rene Rivera 2008 +#~ 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_0.txt) + +import testing ; + +test-suite integer + : [ run cstdint_test.cpp ] + [ run integer_test.cpp ] + [ run integer_traits_test.cpp + /boost/test//boost_test_exec_monitor/static ] + ; diff --git a/cstdint_test.cpp b/test/cstdint_test.cpp similarity index 100% rename from cstdint_test.cpp rename to test/cstdint_test.cpp diff --git a/integer_test.cpp b/test/integer_test.cpp similarity index 100% rename from integer_test.cpp rename to test/integer_test.cpp diff --git a/integer_traits_test.cpp b/test/integer_traits_test.cpp similarity index 100% rename from integer_traits_test.cpp rename to test/integer_traits_test.cpp From 3c7910fad3c5709cc89c8906905553ab69df9bc1 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Sun, 6 Jul 2008 00:58:34 +0000 Subject: [PATCH 06/23] Added entries for the forgotten tests [SVN r47123] --- test/Jamfile.v2 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c75db05..9ad6eec 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -9,4 +9,10 @@ test-suite integer [ run integer_test.cpp ] [ run integer_traits_test.cpp /boost/test//boost_test_exec_monitor/static ] + [ run integer_mask_test.cpp + /boost/test//boost_test_exec_monitor/static ] + [ run static_log2_test.cpp + /boost/test//boost_test_exec_monitor/static ] + [ run static_min_max_test.cpp + /boost/test//boost_test_exec_monitor/static ] ; From edfaeb6c0e3362ea965173683f2491b55a9b7ee7 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Mon, 7 Jul 2008 23:13:43 +0000 Subject: [PATCH 07/23] Changed the Integer-selection test to use the unit-test system [SVN r47200] --- test/Jamfile.v2 | 3 +- test/integer_test.cpp | 89 ++++++++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 9ad6eec..f85e614 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -6,7 +6,8 @@ import testing ; test-suite integer : [ run cstdint_test.cpp ] - [ run integer_test.cpp ] + [ run integer_test.cpp + /boost/test//boost_unit_test_framework ] [ run integer_traits_test.cpp /boost/test//boost_test_exec_monitor/static ] [ run integer_mask_test.cpp diff --git a/test/integer_test.cpp b/test/integer_test.cpp index 6bfff11..f572ebf 100644 --- a/test/integer_test.cpp +++ b/test/integer_test.cpp @@ -12,11 +12,12 @@ // 10 Mar 01 Boost Test Library now used for tests (Beman Dawes) // 31 Aug 99 Initial version -#include // for main, BOOST_CHECK +#define BOOST_TEST_MODULE "Integer size-selection tests" + +#include // unit testing framework #include // for BOOST_NO_USING_TEMPLATE -#include // for boost::exit_success -#include // for boost::int_t, boost::uint_t +#include // for boost::int_t, boost::uint_t, etc. #include // for ULONG_MAX, LONG_MAX, LONG_MIN #include // for std::cout (std::endl indirectly) @@ -128,7 +129,7 @@ namespace boost // Test if a constant can fit within a certain type -#define PRIVATE_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK( Template < Number > :: Type ( Value ) == Value ) +#define PRIVATE_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK_EQUAL( Template < Number > :: Type ( Value ) , Value ) #if ULONG_MAX > 0xFFFFFFFFL #define PRIVATE_FIT_TESTS(Template, Type, ValType, InitVal) do { ValType v = InitVal ; \ @@ -186,7 +187,7 @@ namespace boost PRIVATE_FIT_TEST(Template, 1, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 0, Type, v); } while ( false ) #endif -#define PRIVATE_SHIFTED_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK( Template < (ULONG_MAX >> Number) > :: Type ( Value ) == Value ) +#define PRIVATE_SHIFTED_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK_EQUAL( Template < (ULONG_MAX >> Number) > :: Type ( Value ) , Value ) #define PRIVATE_SHIFTED_FIT_TESTS(Template, Type, ValType, InitVal) do { ValType v = InitVal ; \ PRIVATE_SHIFTED_FIT_TEST(Template, 0, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 1, Type, v); v >>= 1; \ @@ -206,7 +207,7 @@ namespace boost PRIVATE_SHIFTED_FIT_TEST(Template, 28, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 29, Type, v); v >>= 1; \ PRIVATE_SHIFTED_FIT_TEST(Template, 30, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 31, Type, v); } while ( false ) -#define PRIVATE_POS_SHIFTED_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK( Template < (LONG_MAX >> Number) > :: Type ( Value ) == Value ) +#define PRIVATE_POS_SHIFTED_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK_EQUAL( Template < (LONG_MAX >> Number) > :: Type ( Value ) , Value ) #define PRIVATE_POS_FIT_TESTS(Template, Type, ValType, InitVal) do { ValType v = InitVal ; \ PRIVATE_POS_SHIFTED_FIT_TEST(Template, 0, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 1, Type, v); v >>= 1; \ @@ -226,7 +227,7 @@ namespace boost PRIVATE_POS_SHIFTED_FIT_TEST(Template, 28, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 29, Type, v); v >>= 1; \ PRIVATE_POS_SHIFTED_FIT_TEST(Template, 30, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 31, Type, v); } while ( false ) -#define PRIVATE_NEG_SHIFTED_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK( Template < (LONG_MIN >> Number) > :: Type ( Value ) == Value ) +#define PRIVATE_NEG_SHIFTED_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK_EQUAL( Template < (LONG_MIN >> Number) > :: Type ( Value ) , Value ) #define PRIVATE_NEG_FIT_TESTS(Template, Type, ValType, InitVal) do { ValType v = InitVal ; \ PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 0, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 1, Type, v); v >>= 1; \ @@ -247,17 +248,56 @@ namespace boost PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 30, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 31, Type, v); } while ( false ) -// Test program -int -test_main -( - int, - char*[] -) +// Check if given types can support given size parameters +BOOST_AUTO_TEST_SUITE( show_type_tests ) + +// Check size parameters given by bit length +BOOST_AUTO_TEST_CASE( show_bit_length_type_test ) +{ + SHOW_TYPES( boost::int_t, least ); + SHOW_TYPES( boost::int_t, fast ); + SHOW_TYPES( boost::uint_t, least ); + SHOW_TYPES( boost::uint_t, fast ); +} + +// Check size parameters given by maximum or minimum (i.e. extreme) value +BOOST_AUTO_TEST_CASE( show_extreme_type_test ) +{ + SHOW_POS_SHIFTED_TYPES( boost::int_max_value_t, least ); + SHOW_POS_SHIFTED_TYPES( boost::int_max_value_t, fast ); + + SHOW_NEG_SHIFTED_TYPES( boost::int_min_value_t, least ); + SHOW_NEG_SHIFTED_TYPES( boost::int_min_value_t, fast ); + + SHOW_SHIFTED_TYPES( boost::uint_value_t, least ); + SHOW_SHIFTED_TYPES( boost::uint_value_t, fast ); +} + +BOOST_AUTO_TEST_SUITE_END() + +// Check if given constants can fit in given types +BOOST_AUTO_TEST_SUITE( fit_type_tests ) + +// Check against large initial value +BOOST_AUTO_TEST_CASE( show_bit_length_type_test ) { #ifndef BOOST_NO_USING_TEMPLATE using boost::int_t; using boost::uint_t; +#else + using namespace boost; +#endif + + PRIVATE_FIT_TESTS( int_t, least, long, LONG_MAX ); + PRIVATE_FIT_TESTS( int_t, fast, long, LONG_MAX ); + PRIVATE_FIT_TESTS( uint_t, least, unsigned long, ULONG_MAX ); + PRIVATE_FIT_TESTS( uint_t, fast, unsigned long, ULONG_MAX ); +} + +// Check against (absolutely) large initial value +BOOST_AUTO_TEST_CASE( show_extreme_type_test ) +{ +#ifndef BOOST_NO_USING_TEMPLATE using boost::int_max_value_t; using boost::int_min_value_t; using boost::uint_value_t; @@ -265,27 +305,14 @@ test_main using namespace boost; #endif - SHOW_TYPES( int_t, least ); - SHOW_TYPES( int_t, fast ); - SHOW_TYPES( uint_t, least ); - SHOW_TYPES( uint_t, fast ); - SHOW_POS_SHIFTED_TYPES( int_max_value_t, least ); - SHOW_POS_SHIFTED_TYPES( int_max_value_t, fast ); - SHOW_NEG_SHIFTED_TYPES( int_min_value_t, least ); - SHOW_NEG_SHIFTED_TYPES( int_min_value_t, fast ); - SHOW_SHIFTED_TYPES( uint_value_t, least ); - SHOW_SHIFTED_TYPES( uint_value_t, fast ); - - PRIVATE_FIT_TESTS( int_t, least, long, LONG_MAX ); - PRIVATE_FIT_TESTS( int_t, fast, long, LONG_MAX ); - PRIVATE_FIT_TESTS( uint_t, least, unsigned long, ULONG_MAX ); - PRIVATE_FIT_TESTS( uint_t, fast, unsigned long, ULONG_MAX ); PRIVATE_POS_FIT_TESTS( int_max_value_t, least, long, LONG_MAX ); PRIVATE_POS_FIT_TESTS( int_max_value_t, fast, long, LONG_MAX ); + PRIVATE_NEG_FIT_TESTS( int_min_value_t, least, long, LONG_MIN ); PRIVATE_NEG_FIT_TESTS( int_min_value_t, fast, long, LONG_MIN ); + PRIVATE_SHIFTED_FIT_TESTS( uint_value_t, least, unsigned long, ULONG_MAX ); PRIVATE_SHIFTED_FIT_TESTS( uint_value_t, fast, unsigned long, ULONG_MAX ); - - return boost::exit_success; } + +BOOST_AUTO_TEST_SUITE_END() From 422ef1ebe607b6ff4830c9ebf40a4c51f3801b43 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Sun, 13 Jul 2008 21:08:16 +0000 Subject: [PATCH 08/23] Replaced comprehensive macros with focused templates [SVN r47404] --- test/integer_test.cpp | 534 ++++++++++++++++++++++++------------------ 1 file changed, 311 insertions(+), 223 deletions(-) diff --git a/test/integer_test.cpp b/test/integer_test.cpp index f572ebf..d296011 100644 --- a/test/integer_test.cpp +++ b/test/integer_test.cpp @@ -8,19 +8,44 @@ // See http://www.boost.org/libs/integer for documentation. // Revision History +// 13 Jul 08 Modernized tests w/ MPL instead of giant macros (Daryle Walker) +// 07 Jul 08 Changed tests to use the unit-test system (Daryle Walker) // 04 Oct 01 Added tests for new templates; rewrote code (Daryle Walker) // 10 Mar 01 Boost Test Library now used for tests (Beman Dawes) // 31 Aug 99 Initial version #define BOOST_TEST_MODULE "Integer size-selection tests" -#include // unit testing framework +#include // unit testing framework +#include // ..BOOST_AUTO_TEST_CASE_TEMPLATE #include // for BOOST_NO_USING_TEMPLATE #include // for boost::int_t, boost::uint_t, etc. +#include // for std::numeric_limits -#include // for ULONG_MAX, LONG_MAX, LONG_MIN -#include // for std::cout (std::endl indirectly) +#include // for boost::mpl::plus, divides +#include // for BOOST_MPL_ASSERT_RELATION, etc. +#include // for boost::mpl::back +#include // for boost::mpl::copy +#include // for boost::mpl::front_inserter +#include // for boost::mpl::integral_c +#include // for boost::mpl::joint_view +#include // for boost::mpl::pop_back +#include // for boost::mpl::push_back +#include // for boost::mpl::push_front +#include // for boost::mpl::sort +#include // for boost::mpl::transform +#include // for boost::mpl::transform_view +#include // for boost::mpl::unpack_args +#include // for boost::mpl::vector +#include // for boost::mpl::zip_view + +#include // for boost::is_same +#include // for boost::make_signed + +#include // for ULONG_MAX, LONG_MAX, LONG_MIN, etc. +#include // for std::cout +#include // for std::endl #include // for std::type_info @@ -43,234 +68,239 @@ namespace boost } -// Show the types of an integer template version +// Logging #if CONTROL_SHOW_TYPES -#define SHOW_TYPE(Template, Number, Type) ::std::cout << "Type \"" \ - #Template "<" #Number ">::" #Type "\" is \"" << typeid(Template < \ - Number > :: Type).name() << ".\"\n" +#define PRIVATE_SHOW_MESSAGE( m ) std::cout << m << std::endl #else -#define SHOW_TYPE(Template, Number, Type) +#define PRIVATE_SHOW_MESSAGE( m ) BOOST_TEST_MESSAGE( m ) #endif -#define SHOW_TYPES(Template, Type) SHOW_TYPE(Template, 32, Type); \ - SHOW_TYPE(Template, 31, Type); SHOW_TYPE(Template, 30, Type); \ - SHOW_TYPE(Template, 29, Type); SHOW_TYPE(Template, 28, Type); \ - SHOW_TYPE(Template, 27, Type); SHOW_TYPE(Template, 26, Type); \ - SHOW_TYPE(Template, 25, Type); SHOW_TYPE(Template, 24, Type); \ - SHOW_TYPE(Template, 23, Type); SHOW_TYPE(Template, 22, Type); \ - SHOW_TYPE(Template, 21, Type); SHOW_TYPE(Template, 20, Type); \ - SHOW_TYPE(Template, 19, Type); SHOW_TYPE(Template, 18, Type); \ - SHOW_TYPE(Template, 17, Type); SHOW_TYPE(Template, 16, Type); \ - SHOW_TYPE(Template, 15, Type); SHOW_TYPE(Template, 14, Type); \ - SHOW_TYPE(Template, 13, Type); SHOW_TYPE(Template, 12, Type); \ - SHOW_TYPE(Template, 11, Type); SHOW_TYPE(Template, 10, Type); \ - SHOW_TYPE(Template, 9, Type); SHOW_TYPE(Template, 8, Type); \ - SHOW_TYPE(Template, 7, Type); SHOW_TYPE(Template, 6, Type); \ - SHOW_TYPE(Template, 5, Type); SHOW_TYPE(Template, 4, Type); \ - SHOW_TYPE(Template, 3, Type); SHOW_TYPE(Template, 2, Type); \ - SHOW_TYPE(Template, 1, Type); SHOW_TYPE(Template, 0, Type) -#define SHOW_SHIFTED_TYPE(Template, Number, Type) SHOW_TYPE(Template, (1UL << Number), Type) +// Custom types/templates, helper functions, and objects +namespace +{ -#define SHOW_SHIFTED_TYPES(Template, Type) SHOW_SHIFTED_TYPE(Template, 30, Type); \ - SHOW_SHIFTED_TYPE(Template, 29, Type); SHOW_SHIFTED_TYPE(Template, 28, Type); \ - SHOW_SHIFTED_TYPE(Template, 27, Type); SHOW_SHIFTED_TYPE(Template, 26, Type); \ - SHOW_SHIFTED_TYPE(Template, 25, Type); SHOW_SHIFTED_TYPE(Template, 24, Type); \ - SHOW_SHIFTED_TYPE(Template, 23, Type); SHOW_SHIFTED_TYPE(Template, 22, Type); \ - SHOW_SHIFTED_TYPE(Template, 21, Type); SHOW_SHIFTED_TYPE(Template, 20, Type); \ - SHOW_SHIFTED_TYPE(Template, 19, Type); SHOW_SHIFTED_TYPE(Template, 18, Type); \ - SHOW_SHIFTED_TYPE(Template, 17, Type); SHOW_SHIFTED_TYPE(Template, 16, Type); \ - SHOW_SHIFTED_TYPE(Template, 15, Type); SHOW_SHIFTED_TYPE(Template, 14, Type); \ - SHOW_SHIFTED_TYPE(Template, 13, Type); SHOW_SHIFTED_TYPE(Template, 12, Type); \ - SHOW_SHIFTED_TYPE(Template, 11, Type); SHOW_SHIFTED_TYPE(Template, 10, Type); \ - SHOW_SHIFTED_TYPE(Template, 9, Type); SHOW_SHIFTED_TYPE(Template, 8, Type); \ - SHOW_SHIFTED_TYPE(Template, 7, Type); SHOW_SHIFTED_TYPE(Template, 6, Type); \ - SHOW_SHIFTED_TYPE(Template, 5, Type); SHOW_SHIFTED_TYPE(Template, 4, Type); \ - SHOW_SHIFTED_TYPE(Template, 3, Type); SHOW_SHIFTED_TYPE(Template, 2, Type); \ - SHOW_SHIFTED_TYPE(Template, 1, Type); SHOW_SHIFTED_TYPE(Template, 0, Type) - -#define SHOW_POS_SHIFTED_TYPE(Template, Number, Type) SHOW_TYPE(Template, +(1L << Number), Type) - -#define SHOW_POS_SHIFTED_TYPES(Template, Type) SHOW_POS_SHIFTED_TYPE(Template, 30, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 29, Type); SHOW_POS_SHIFTED_TYPE(Template, 28, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 27, Type); SHOW_POS_SHIFTED_TYPE(Template, 26, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 25, Type); SHOW_POS_SHIFTED_TYPE(Template, 24, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 23, Type); SHOW_POS_SHIFTED_TYPE(Template, 22, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 21, Type); SHOW_POS_SHIFTED_TYPE(Template, 20, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 19, Type); SHOW_POS_SHIFTED_TYPE(Template, 18, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 17, Type); SHOW_POS_SHIFTED_TYPE(Template, 16, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 15, Type); SHOW_POS_SHIFTED_TYPE(Template, 14, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 13, Type); SHOW_POS_SHIFTED_TYPE(Template, 12, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 11, Type); SHOW_POS_SHIFTED_TYPE(Template, 10, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 9, Type); SHOW_POS_SHIFTED_TYPE(Template, 8, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 7, Type); SHOW_POS_SHIFTED_TYPE(Template, 6, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 5, Type); SHOW_POS_SHIFTED_TYPE(Template, 4, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 3, Type); SHOW_POS_SHIFTED_TYPE(Template, 2, Type); \ - SHOW_POS_SHIFTED_TYPE(Template, 1, Type); SHOW_POS_SHIFTED_TYPE(Template, 0, Type) - -#define SHOW_NEG_SHIFTED_TYPE(Template, Number, Type) SHOW_TYPE(Template, -(1L << Number), Type) - -#define SHOW_NEG_SHIFTED_TYPES(Template, Type) SHOW_NEG_SHIFTED_TYPE(Template, 30, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 29, Type); SHOW_NEG_SHIFTED_TYPE(Template, 28, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 27, Type); SHOW_NEG_SHIFTED_TYPE(Template, 26, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 25, Type); SHOW_NEG_SHIFTED_TYPE(Template, 24, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 23, Type); SHOW_NEG_SHIFTED_TYPE(Template, 22, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 21, Type); SHOW_NEG_SHIFTED_TYPE(Template, 20, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 19, Type); SHOW_NEG_SHIFTED_TYPE(Template, 18, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 17, Type); SHOW_NEG_SHIFTED_TYPE(Template, 16, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 15, Type); SHOW_NEG_SHIFTED_TYPE(Template, 14, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 13, Type); SHOW_NEG_SHIFTED_TYPE(Template, 12, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 11, Type); SHOW_NEG_SHIFTED_TYPE(Template, 10, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 9, Type); SHOW_NEG_SHIFTED_TYPE(Template, 8, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 7, Type); SHOW_NEG_SHIFTED_TYPE(Template, 6, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 5, Type); SHOW_NEG_SHIFTED_TYPE(Template, 4, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 3, Type); SHOW_NEG_SHIFTED_TYPE(Template, 2, Type); \ - SHOW_NEG_SHIFTED_TYPE(Template, 1, Type); SHOW_NEG_SHIFTED_TYPE(Template, 0, Type) - - -// Test if a constant can fit within a certain type -#define PRIVATE_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK_EQUAL( Template < Number > :: Type ( Value ) , Value ) - -#if ULONG_MAX > 0xFFFFFFFFL -#define PRIVATE_FIT_TESTS(Template, Type, ValType, InitVal) do { ValType v = InitVal ; \ - PRIVATE_FIT_TEST(Template, 64, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 63, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 62, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 61, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 60, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 59, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 58, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 57, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 56, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 55, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 54, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 53, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 52, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 51, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 50, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 49, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 48, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 47, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 46, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 45, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 44, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 43, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 42, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 41, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 40, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 39, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 38, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 37, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 36, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 35, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 34, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 33, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 32, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 31, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 30, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 29, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 28, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 27, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 26, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 25, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 24, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 23, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 22, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 21, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 20, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 19, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 18, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 17, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 16, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 15, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 14, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 13, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 12, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 11, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 10, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 9, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 8, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 7, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 6, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 5, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 4, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 3, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 2, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 1, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 0, Type, v); } while ( false ) -#else -#define PRIVATE_FIT_TESTS(Template, Type, ValType, InitVal) do { ValType v = InitVal ; \ - PRIVATE_FIT_TEST(Template, 32, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 31, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 30, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 29, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 28, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 27, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 26, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 25, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 24, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 23, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 22, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 21, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 20, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 19, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 18, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 17, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 16, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 15, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 14, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 13, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 12, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 11, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 10, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 9, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 8, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 7, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 6, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 5, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 4, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 3, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 2, Type, v); v >>= 1; \ - PRIVATE_FIT_TEST(Template, 1, Type, v); v >>= 1; PRIVATE_FIT_TEST(Template, 0, Type, v); } while ( false ) +// List the built-in integral types, excluding the ones that are strong-typedefs +// of a lower type. +typedef boost::mpl::vector< + unsigned char +#if USHRT_MAX > UCHAR_MAX + , unsigned short #endif +#if UINT_MAX > USHRT_MAX + , unsigned int +#endif +#if ULONG_MAX > UINT_MAX + , unsigned long +#endif +> distinct_unsigned_types; -#define PRIVATE_SHIFTED_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK_EQUAL( Template < (ULONG_MAX >> Number) > :: Type ( Value ) , Value ) +typedef boost::mpl::transform< + distinct_unsigned_types, + boost::make_signed< boost::mpl::_1 > +>::type distinct_signed_types; -#define PRIVATE_SHIFTED_FIT_TESTS(Template, Type, ValType, InitVal) do { ValType v = InitVal ; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 0, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 1, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 2, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 3, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 4, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 5, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 6, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 7, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 8, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 9, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 10, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 11, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 12, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 13, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 14, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 15, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 16, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 17, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 18, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 19, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 20, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 21, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 22, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 23, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 24, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 25, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 26, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 27, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 28, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 29, Type, v); v >>= 1; \ - PRIVATE_SHIFTED_FIT_TEST(Template, 30, Type, v); v >>= 1; PRIVATE_SHIFTED_FIT_TEST(Template, 31, Type, v); } while ( false ) +// List the digit counts for each integral type +class dibc_helper +{ + template < typename T > + struct type_to_digit_count + : boost::mpl::integral_c< int, std::numeric_limits::digits > + {}; -#define PRIVATE_POS_SHIFTED_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK_EQUAL( Template < (LONG_MAX >> Number) > :: Type ( Value ) , Value ) +public: + typedef boost::mpl::transform< + distinct_unsigned_types, + type_to_digit_count< boost::mpl::_1 > + >::type type; +}; -#define PRIVATE_POS_FIT_TESTS(Template, Type, ValType, InitVal) do { ValType v = InitVal ; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 0, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 1, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 2, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 3, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 4, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 5, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 6, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 7, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 8, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 9, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 10, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 11, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 12, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 13, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 14, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 15, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 16, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 17, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 18, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 19, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 20, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 21, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 22, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 23, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 24, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 25, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 26, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 27, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 28, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 29, Type, v); v >>= 1; \ - PRIVATE_POS_SHIFTED_FIT_TEST(Template, 30, Type, v); v >>= 1; PRIVATE_POS_SHIFTED_FIT_TEST(Template, 31, Type, v); } while ( false ) +typedef dibc_helper::type distinct_integral_bit_counts; -#define PRIVATE_NEG_SHIFTED_FIT_TEST(Template, Number, Type, Value) BOOST_CHECK_EQUAL( Template < (LONG_MIN >> Number) > :: Type ( Value ) , Value ) +// Make list of bit counts between each offical point, plus CHAR_BIT/2 +typedef boost::mpl::transform_view< + boost::mpl::zip_view< + boost::mpl::vector< + boost::mpl::push_front< + boost::mpl::pop_back< distinct_integral_bit_counts >::type, + boost::mpl::integral_c< int, 0 > + >::type, + distinct_integral_bit_counts + > + >, + boost::mpl::unpack_args< + boost::mpl::divides< + boost::mpl::plus< boost::mpl::_1, boost::mpl::_2 >, + boost::mpl::integral_c< int, 2 > + > + > +> median_bit_counts; -#define PRIVATE_NEG_FIT_TESTS(Template, Type, ValType, InitVal) do { ValType v = InitVal ; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 0, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 1, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 2, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 3, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 4, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 5, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 6, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 7, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 8, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 9, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 10, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 11, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 12, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 13, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 14, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 15, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 16, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 17, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 18, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 19, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 20, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 21, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 22, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 23, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 24, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 25, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 26, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 27, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 28, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 29, Type, v); v >>= 1; \ - PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 30, Type, v); v >>= 1; PRIVATE_NEG_SHIFTED_FIT_TEST(Template, 31, Type, v); } while ( false ) +// Maximum number of bits allowed +int const intmax_bits = boost::mpl::back::type::value; + // should be std::numeric_limits::digits + 1 +int const uintmax_bits = intmax_bits; + // should be std::numeric_limits::digits + +// Make master lists including an outlier beyond all valid bit counts +typedef boost::mpl::sort< + boost::mpl::copy< + boost::mpl::joint_view< + distinct_integral_bit_counts, + median_bit_counts + >, + boost::mpl::front_inserter< + boost::mpl::vector< + boost::mpl::integral_c + > + > + >::type +>::type bits_list; + +// Remove the outlier when all bits counts must be valid +typedef boost::mpl::pop_back::type valid_bits_list; + +// Replace the maximum bit count with one less, so left-shifting by a stored +// value doesn't give an invalid result +typedef boost::mpl::push_back< + boost::mpl::pop_back< valid_bits_list >::type, + boost::mpl::integral_c< int, uintmax_bits - 1 > +>::type valid_to_increase_ubits_list; + +// Do it again for signed types since they have one-less bit to use for the +// 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 > +>::type valid_to_increase_sbits_list; + +} // unnamed namespace // Check if given types can support given size parameters BOOST_AUTO_TEST_SUITE( show_type_tests ) -// Check size parameters given by bit length -BOOST_AUTO_TEST_CASE( show_bit_length_type_test ) +// Check the specialization type status of given bit lengths +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_lengths_test, T, valid_bits_list ) { - SHOW_TYPES( boost::int_t, least ); - SHOW_TYPES( boost::int_t, fast ); - SHOW_TYPES( boost::uint_t, least ); - SHOW_TYPES( boost::uint_t, fast ); + // This test is supposed to replace the following printouts given in + // puesdo-code by: + // Routine: Template, Type + // for N := 32 downto 0 + // cout << "Type '" << Template << "<" N << ">::" << Type << "' is '" + // << typeid(Template::Type).name << ".'\n" + // end for + // end Routine + // with Template = {int_t, uint_t}; Type = {least, fast} + // 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. The only interesting part is if the bit + // count is too large, and we can't check that yet. +#ifndef BOOST_NO_USING_TEMPLATE + using std::numeric_limits; + using boost::int_t; + using boost::uint_t; +#else + using namespace std; + using namespace boost; +#endif + + BOOST_MPL_ASSERT_RELATION( numeric_limits::least>::digits, >=, T::value - 1 ); + BOOST_MPL_ASSERT_RELATION( numeric_limits::fast>::digits, >=, T::value - 1 ); + BOOST_MPL_ASSERT_RELATION( numeric_limits::least>::digits, >=, T::value ); + BOOST_MPL_ASSERT_RELATION( numeric_limits::fast>::digits, >=, T::value ); } -// Check size parameters given by maximum or minimum (i.e. extreme) value -BOOST_AUTO_TEST_CASE( show_extreme_type_test ) +// Check size comparisons of given value support, unsigned +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_unsigned_values_test, T, + valid_to_increase_ubits_list ) { - SHOW_POS_SHIFTED_TYPES( boost::int_max_value_t, least ); - SHOW_POS_SHIFTED_TYPES( boost::int_max_value_t, fast ); + // This test is supposed to replace the following printouts given in + // puesdo-code by: + // Routine: Type + // for N := 30 downto 0 + // cout << "Type '" << uint_value_t << "<" (1ul << N) << ">::" << Type + // << "' is '"<< typeid(uint_value_t<(1ul << N)>::Type).name << ".'\n" + // end for + // end Routine + // with Type = {least, fast} + // 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. The interesting parts are where N is the + // length of a integral type, so 1 << N would have to fit in the next larger + // type. (This is why N can't be more than bitlength(uintmax_t) - 1.) +#ifndef BOOST_NO_USING_TEMPLATE + using boost::is_same; + using boost::uint_value_t; + using boost::uint_t; +#else + using namespace boost; +#endif - SHOW_NEG_SHIFTED_TYPES( boost::int_min_value_t, least ); - SHOW_NEG_SHIFTED_TYPES( boost::int_min_value_t, fast ); + unsigned long const one = 1u; + int const count = T::value; - SHOW_SHIFTED_TYPES( boost::uint_value_t, least ); - SHOW_SHIFTED_TYPES( boost::uint_value_t, fast ); + BOOST_MPL_ASSERT( (is_same::least, typename uint_t::least>::value) ); + BOOST_MPL_ASSERT( (is_same::least, typename uint_t::least>::value) ); + BOOST_MPL_ASSERT( (is_same::least, + typename uint_t::least>::value) ); +} + +// Check size comparisons of given value support, signed +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_signed_values_test, T, + valid_to_increase_sbits_list ) +{ + // This test is supposed to replace the following printouts given in + // puesdo-code by: + // Routine: Type + // for N := 30 downto 0 + // cout << "Type '" << int_max_value_t << "<" +(1ul << N) << ">::" << + // Type << "' is '" << typeid(int_max_value_t<+(1ul << N)>::Type).name + // << ".'\n" + // cout << "Type '" << int_min_value_t << "<" -(1ul << N) << ">::" << + // Type << "' is '" << typeid(int_min_value_t<-(1ul << N)>::Type).name + // << ".'\n" + // end for + // end Routine + // with Type = {least, fast} + // 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. The interesting parts are where N is the + // length of a integral type, so 1 << N would have to fit in the next larger + // type. (This is why N can't be more than bitlength(intmax_t) - 1. Note + // that bitlength(intmax_t) + 1 == bitlength(uintmax_t).) +#ifndef BOOST_NO_USING_TEMPLATE + using boost::is_same; + using boost::int_max_value_t; + using boost::int_t; + using boost::int_min_value_t; +#else + using namespace boost; +#endif + + long const one = 1; + int const count = T::value; + + BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); + BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); + + BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); + BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); + + BOOST_MPL_ASSERT( (is_same::least, + typename int_t::least>::value) ); + BOOST_MPL_ASSERT( (is_same::least, + typename int_t::least>::value) ); } BOOST_AUTO_TEST_SUITE_END() @@ -278,41 +308,99 @@ BOOST_AUTO_TEST_SUITE_END() // Check if given constants can fit in given types BOOST_AUTO_TEST_SUITE( fit_type_tests ) -// Check against large initial value -BOOST_AUTO_TEST_CASE( show_bit_length_type_test ) +// Check if large value can fit its minimum required size, by size +BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T, + valid_bits_list ) { + // This test is supposed to replace the following checks given in + // puesdo-code by: + // Routine: Template, Type + // for ( N = 32, V = Template:Max ; N >= 0 ; --N, V >>= 1 ) + // Confirm( static_cast::Type>(V) == V ); + // end for + // end Routine + // with Template = {int_t, uint_t}; Type = {least, fast}; + // Template:Max = { LONG_MAX for int_t, ULONG_MAX for uint_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. #ifndef BOOST_NO_USING_TEMPLATE - using boost::int_t; using boost::uint_t; + using boost::int_t; #else using namespace boost; #endif - PRIVATE_FIT_TESTS( int_t, least, long, LONG_MAX ); - PRIVATE_FIT_TESTS( int_t, fast, long, LONG_MAX ); - PRIVATE_FIT_TESTS( uint_t, least, unsigned long, ULONG_MAX ); - PRIVATE_FIT_TESTS( uint_t, fast, unsigned long, ULONG_MAX ); + int const count = T::value, shift = uintmax_bits - count; + unsigned long const value_u = ULONG_MAX >> shift; + long const value_s = LONG_MAX >> shift; + + BOOST_CHECK_EQUAL( typename uint_t::least(value_u), value_u ); + BOOST_CHECK_EQUAL( typename uint_t::least(value_u >> 1), value_u + >> 1 ); + BOOST_CHECK_EQUAL( typename uint_t::fast(value_u), value_u ); + BOOST_CHECK_EQUAL( typename uint_t::fast(value_u >> 1), value_u + >> 1 ); + + BOOST_CHECK_EQUAL( typename int_t::least(value_s), value_s ); + BOOST_CHECK_EQUAL( typename int_t::least(value_s >> 1), value_s + >> 1 ); + BOOST_CHECK_EQUAL( typename int_t::fast(value_s), value_s ); + BOOST_CHECK_EQUAL( typename int_t::fast(value_s >> 1), value_s >> + 1 ); } -// Check against (absolutely) large initial value -BOOST_AUTO_TEST_CASE( show_extreme_type_test ) +// Check if large value can fit its minimum required size, by value +BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_values_test, T, + valid_to_increase_ubits_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::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 = { LONG_MIN for int_min_value_t, + // LONG_MAX for int_max_value_t, ULONG_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. #ifndef BOOST_NO_USING_TEMPLATE + using boost::uint_value_t; using boost::int_max_value_t; using boost::int_min_value_t; - using boost::uint_value_t; #else using namespace boost; #endif - PRIVATE_POS_FIT_TESTS( int_max_value_t, least, long, LONG_MAX ); - PRIVATE_POS_FIT_TESTS( int_max_value_t, fast, long, LONG_MAX ); + int const shift = T::value; + unsigned long const max_u = ULONG_MAX >> shift; + long const max_s = LONG_MAX >> shift, min_s = LONG_MIN >> shift; - PRIVATE_NEG_FIT_TESTS( int_min_value_t, least, long, LONG_MIN ); - PRIVATE_NEG_FIT_TESTS( int_min_value_t, fast, long, LONG_MIN ); + BOOST_CHECK_EQUAL( typename uint_value_t::least(max_u), max_u ); + BOOST_CHECK_EQUAL( typename uint_value_t<(max_u >> 1)>::least(max_u >> 1), + max_u >> 1 ); + BOOST_CHECK_EQUAL( typename uint_value_t::fast(max_u), max_u ); + BOOST_CHECK_EQUAL( typename uint_value_t<(max_u >> 1)>::fast(max_u >> 1), + max_u >> 1 ); - PRIVATE_SHIFTED_FIT_TESTS( uint_value_t, least, unsigned long, ULONG_MAX ); - PRIVATE_SHIFTED_FIT_TESTS( uint_value_t, fast, unsigned long, ULONG_MAX ); + BOOST_CHECK_EQUAL( typename int_max_value_t::least(max_s), max_s ); + BOOST_CHECK_EQUAL( typename int_max_value_t<(max_s >> 1)>::least(max_s >> + 1), max_s >> 1 ); + BOOST_CHECK_EQUAL( typename int_max_value_t::fast(max_s), max_s ); + BOOST_CHECK_EQUAL( typename int_max_value_t<(max_s >> 1)>::fast(max_s >> 1), + max_s >> 1 ); + + BOOST_CHECK_EQUAL( typename int_min_value_t::least(min_s), min_s ); + BOOST_CHECK_EQUAL( typename int_min_value_t<(min_s >> 1)>::least(min_s >> + 1), min_s >> 1 ); + BOOST_CHECK_EQUAL( typename int_min_value_t::fast(min_s), min_s ); + BOOST_CHECK_EQUAL( typename int_min_value_t<(min_s >> 1)>::fast(min_s >> 1), + min_s >> 1 ); } BOOST_AUTO_TEST_SUITE_END() From 2f91e69629c287b08b2cc5d4ecc86d28016186c5 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Sun, 13 Jul 2008 23:30:18 +0000 Subject: [PATCH 09/23] Re-did implementation [SVN r47408] --- include/boost/integer.hpp | 148 ++++++++++++++++++++++++++------------ 1 file changed, 102 insertions(+), 46 deletions(-) diff --git a/include/boost/integer.hpp b/include/boost/integer.hpp index dc57dff..256fa27 100644 --- a/include/boost/integer.hpp +++ b/include/boost/integer.hpp @@ -7,6 +7,7 @@ // See http://www.boost.org/libs/integer for documentation. // Revision History +// 13 Jul 08 Redid implmentation. (Daryle Walker) // 22 Sep 01 Added value-based integer templates. (Daryle Walker) // 01 Apr 01 Modified to use new header. (John Maddock) // 30 Jul 00 Add typename syntax fix (Jens Maurer) @@ -17,33 +18,105 @@ #include // self include +#include // for BOOST_STATIC_CONSTANT #include // for boost::integer_traits #include // for std::numeric_limits namespace boost { - // Helper templates ------------------------------------------------------// + // integer template mapping a type to its processor-optimized analog -----// // fast integers from least integers // int_fast_t<> works correctly for unsigned too, in spite of the name. template< typename LeastInt > struct int_fast_t { typedef LeastInt fast; }; // imps may specialize - // convert category to type - template< int Category > struct int_least_helper {}; // default is empty +namespace detail +{ - // specializatons: 1=long, 2=int, 3=short, 4=signed char, - // 6=unsigned long, 7=unsigned int, 8=unsigned short, 9=unsigned char - // no specializations for 0 and 5: requests for a type > long are in error - template<> struct int_least_helper<1> { typedef long least; }; - template<> struct int_least_helper<2> { typedef int least; }; - template<> struct int_least_helper<3> { typedef short least; }; - template<> struct int_least_helper<4> { typedef signed char least; }; - template<> struct int_least_helper<6> { typedef unsigned long least; }; - template<> struct int_least_helper<7> { typedef unsigned int least; }; - template<> struct int_least_helper<8> { typedef unsigned short least; }; - template<> struct int_least_helper<9> { typedef unsigned char least; }; + // Helper templates ------------------------------------------------------// + + // convert integer category to type ; default is empty + template< int Rank, typename Signedness > struct int_least_helper {}; + + // specializatons: 1=(unsigned) long, 2=unsigned/int, 3=(unsigned) short, + // 4=(un)signed char + // no specializations for 0: requests for a type > (unsigned) long are in + // error + template<> struct int_least_helper<1, signed> { typedef long least; }; + template<> struct int_least_helper<1, unsigned> + { typedef unsigned long least; }; + template<> struct int_least_helper<2, signed> { typedef int least; }; + template<> struct int_least_helper<2, unsigned> + { typedef unsigned int least; }; + template<> struct int_least_helper<3, signed> { typedef short least; }; + template<> struct int_least_helper<3, unsigned> + { typedef unsigned short least; }; + template<> struct int_least_helper<4, signed> { typedef signed char least; }; + template<> struct int_least_helper<4, unsigned> + { typedef unsigned char least; }; + + // category bounds + enum + { + lowest_integral_rank = 1, + highest_integral_rank = 4 + }; + + // map a bit count to a category + template < int BitsIncludingSign > + struct int_rank_helper + { + BOOST_STATIC_CONSTANT( int, rank = + (BitsIncludingSign - 1 <= std::numeric_limits< long >::digits) + + (BitsIncludingSign - 1 <= std::numeric_limits< int >::digits) + + (BitsIncludingSign - 1 <= std::numeric_limits< short >::digits) + + (BitsIncludingSign - 1 <= std::numeric_limits< signed char >::digits) ); + }; + + template < int Bits > + struct uint_rank_helper + { + BOOST_STATIC_CONSTANT( int, rank = + (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) ); + }; + + // map an extreme value to a category + template < long MaxValue > + struct int_max_rank_helper + { + BOOST_STATIC_CONSTANT( int, rank = + (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) ); + }; + + template < long MinValue > + struct int_min_rank_helper + { + BOOST_STATIC_CONSTANT( int, rank = + (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) ); + }; + + template < unsigned long Value > + struct uint_max_rank_helper + { + BOOST_STATIC_CONSTANT( int, rank = + (Value <= integer_traits< unsigned long >::const_max) + + (Value <= integer_traits< unsigned int >::const_max) + + (Value <= integer_traits< unsigned short >::const_max) + + (Value <= integer_traits< unsigned char >::const_max) ); + }; + +} // namespace detail // integer templates specifying number of bits ---------------------------// @@ -51,13 +124,10 @@ namespace boost template< int Bits > // bits (including sign) required struct int_t { - typedef typename int_least_helper + typedef typename detail::int_least_helper < - (Bits-1 <= std::numeric_limits::digits) + - (Bits-1 <= std::numeric_limits::digits) + - (Bits-1 <= std::numeric_limits::digits) + - (Bits-1 <= std::numeric_limits::digits) - >::least least; + detail::int_rank_helper::rank, + signed>::least least; typedef typename int_fast_t::fast fast; }; @@ -65,14 +135,10 @@ namespace boost template< int Bits > // bits required struct uint_t { - typedef typename int_least_helper + typedef typename detail::int_least_helper < - 5 + - (Bits <= std::numeric_limits::digits) + - (Bits <= std::numeric_limits::digits) + - (Bits <= std::numeric_limits::digits) + - (Bits <= std::numeric_limits::digits) - >::least least; + detail::uint_rank_helper::rank, + unsigned>::least least; typedef typename int_fast_t::fast fast; // int_fast_t<> works correctly for unsigned too, in spite of the name. }; @@ -83,26 +149,20 @@ namespace boost template< long MaxValue > // maximum value to require support struct int_max_value_t { - typedef typename int_least_helper + typedef typename detail::int_least_helper < - (MaxValue <= integer_traits::const_max) + - (MaxValue <= integer_traits::const_max) + - (MaxValue <= integer_traits::const_max) + - (MaxValue <= integer_traits::const_max) - >::least least; + detail::int_max_rank_helper::rank, + signed>::least least; typedef typename int_fast_t::fast fast; }; template< long MinValue > // minimum value to require support struct int_min_value_t { - typedef typename int_least_helper + typedef typename detail::int_least_helper < - (MinValue >= integer_traits::const_min) + - (MinValue >= integer_traits::const_min) + - (MinValue >= integer_traits::const_min) + - (MinValue >= integer_traits::const_min) - >::least least; + detail::int_min_rank_helper::rank, + signed>::least least; typedef typename int_fast_t::fast fast; }; @@ -110,14 +170,10 @@ namespace boost template< unsigned long Value > // maximum value to require support struct uint_value_t { - typedef typename int_least_helper + typedef typename detail::int_least_helper < - 5 + - (Value <= integer_traits::const_max) + - (Value <= integer_traits::const_max) + - (Value <= integer_traits::const_max) + - (Value <= integer_traits::const_max) - >::least least; + detail::uint_max_rank_helper::rank, + unsigned>::least least; typedef typename int_fast_t::fast fast; }; From 10e5587b9e2ae1417cbd831f937d194cf39f4b47 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Mon, 14 Jul 2008 04:25:31 +0000 Subject: [PATCH 10/23] Improved/added testing for the processor-optimized integer template [SVN r47413] --- test/integer_test.cpp | 45 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/test/integer_test.cpp b/test/integer_test.cpp index d296011..6772e56 100644 --- a/test/integer_test.cpp +++ b/test/integer_test.cpp @@ -8,6 +8,7 @@ // See http://www.boost.org/libs/integer for documentation. // Revision History +// 14 Jul 08 Improved testing of fast-integer template. (Daryle Walker) // 13 Jul 08 Modernized tests w/ MPL instead of giant macros (Daryle Walker) // 07 Jul 08 Changed tests to use the unit-test system (Daryle Walker) // 04 Oct 01 Added tests for new templates; rewrote code (Daryle Walker) @@ -49,6 +50,11 @@ #include // for std::type_info +// Control what the "fast" specialization of "short" is +#ifndef CONTROL_FAST_SHORT +#define CONTROL_FAST_SHORT long +#endif + // Control if the names of the types for each version // of the integer templates will be printed. #ifndef CONTROL_SHOW_TYPES @@ -57,13 +63,15 @@ // If specializations have not already been done, then we can confirm -// the effects of the "fast" types by making a specialization. +// the effects of the "fast" types by making a specialization. If there +// is a specialization for "short," make sure that CONTROL_FAST_SHORT +// is set to a type distinct from "short" and the default implementation. namespace boost { template < > struct int_fast_t< short > { - typedef long fast; + typedef CONTROL_FAST_SHORT fast; }; } @@ -177,6 +185,34 @@ typedef boost::mpl::push_back< } // unnamed namespace +// Check the processor-optimzed type system +BOOST_AUTO_TEST_SUITE( optimized_type_tests ) + +// Check the optimzed type override of a given type +BOOST_AUTO_TEST_CASE( fast_type_test ) +{ +#ifndef BOOST_NO_USING_TEMPLATE + using std::numeric_limits; +#else + using namespace std; +#endif + + typedef short least_type; + typedef boost::int_fast_t::fast fast_type; + typedef numeric_limits least_limits; + typedef numeric_limits fast_limits; + + BOOST_MPL_ASSERT_RELATION( (boost::is_same::value), + ==, false ); + BOOST_MPL_ASSERT_RELATION( fast_limits::is_specialized, ==, true ); + BOOST_MPL_ASSERT_RELATION( fast_limits::is_signed && + fast_limits::is_bounded, ==, true ); + BOOST_MPL_ASSERT_RELATION( fast_limits::radix, ==, 2 ); + BOOST_MPL_ASSERT_RELATION( fast_limits::digits, >=, least_limits::digits ); +} + +BOOST_AUTO_TEST_SUITE_END() + // Check if given types can support given size parameters BOOST_AUTO_TEST_SUITE( show_type_tests ) @@ -404,3 +440,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_values_test, T, } BOOST_AUTO_TEST_SUITE_END() + +// Verification of bugs and their fixes +BOOST_AUTO_TEST_SUITE( bug_fix_tests ) + +BOOST_AUTO_TEST_SUITE_END() From 053be71261effcd8b0e9cf7be0d3e704f76a88a3 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Mon, 14 Jul 2008 06:28:54 +0000 Subject: [PATCH 11/23] Added extended-integer support, which fixes #653 (the main part; the secondary part is split off as #1225) [SVN r47414] --- include/boost/integer.hpp | 98 +++++++++++++++++++++++++++-------- include/boost/integer_fwd.hpp | 18 +++++-- integer.htm | 19 ++++--- test/integer_test.cpp | 57 ++++++++++++-------- 4 files changed, 135 insertions(+), 57 deletions(-) diff --git a/include/boost/integer.hpp b/include/boost/integer.hpp index 256fa27..cb285f8 100644 --- a/include/boost/integer.hpp +++ b/include/boost/integer.hpp @@ -7,6 +7,7 @@ // See http://www.boost.org/libs/integer for documentation. // Revision History +// 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) // 01 Apr 01 Modified to use new header. (John Maddock) @@ -18,7 +19,8 @@ #include // self include -#include // for BOOST_STATIC_CONSTANT +#include // for BOOST_STATIC_CONSTANT, etc. +#include // for boost::uintmax_t, intmax_t #include // for boost::integer_traits #include // for std::numeric_limits @@ -40,45 +42,74 @@ namespace detail // convert integer category to type ; default is empty template< int Rank, typename Signedness > struct int_least_helper {}; - // specializatons: 1=(unsigned) long, 2=unsigned/int, 3=(unsigned) short, - // 4=(un)signed char - // no specializations for 0: requests for a type > (unsigned) long are in - // error - template<> struct int_least_helper<1, signed> { typedef long least; }; + // specializatons: 1=(unsigned) __int64/long long, 2=(unsigned) long, + // 3=unsigned/int, 4=(unsigned) short, 5=(un)signed char + // no specializations for 0: requests for a type > (unsigned) (long) long are + // in error +#ifdef BOOST_HAS_LONG_LONG + template<> struct int_least_helper<1, signed> + { typedef long_long_type least; }; template<> struct int_least_helper<1, unsigned> - { typedef unsigned long least; }; - template<> struct int_least_helper<2, signed> { typedef int least; }; + { typedef ulong_long_type least; }; +#elif defined(BOOST_HAS_MS_INT64) + template<> struct int_least_helper<1, signed> { typedef __int64 least; }; + template<> struct int_least_helper<1, unsigned> + { typedef unsigned __int64 least; }; +#endif + template<> struct int_least_helper<2, signed> { typedef long least; }; template<> struct int_least_helper<2, unsigned> - { typedef unsigned int least; }; - template<> struct int_least_helper<3, signed> { typedef short least; }; + { typedef unsigned long least; }; + template<> struct int_least_helper<3, signed> { typedef int least; }; template<> struct int_least_helper<3, unsigned> - { typedef unsigned short least; }; - template<> struct int_least_helper<4, signed> { typedef signed char least; }; + { typedef unsigned int least; }; + template<> struct int_least_helper<4, signed> { typedef short least; }; template<> struct int_least_helper<4, unsigned> + { typedef unsigned short least; }; + template<> struct int_least_helper<5, signed> { typedef signed char least; }; + template<> struct int_least_helper<5, unsigned> { typedef unsigned char least; }; // category bounds enum { +#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) lowest_integral_rank = 1, - highest_integral_rank = 4 +#else + lowest_integral_rank = 2, +#endif + highest_integral_rank = 5 }; // map a bit count to a category template < int BitsIncludingSign > struct int_rank_helper { + BOOST_STATIC_CONSTANT( int, mantissa = BitsIncludingSign - 1 ); BOOST_STATIC_CONSTANT( int, rank = - (BitsIncludingSign - 1 <= std::numeric_limits< long >::digits) + - (BitsIncludingSign - 1 <= std::numeric_limits< int >::digits) + - (BitsIncludingSign - 1 <= std::numeric_limits< short >::digits) + - (BitsIncludingSign - 1 <= std::numeric_limits< signed char >::digits) ); +#ifdef BOOST_HAS_LONG_LONG + (mantissa <= std::numeric_limits< long_long_type >::digits) + +#elif defined(BOOST_HAS_MS_INT64) + (mantissa <= std::numeric_limits< __int64 >::digits) + +#else + 1 + +#endif + (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) ); }; template < int Bits > struct uint_rank_helper { BOOST_STATIC_CONSTANT( int, rank = +#ifdef BOOST_HAS_LONG_LONG + (Bits <= std::numeric_limits< ulong_long_type >::digits) + +#elif defined(BOOST_HAS_MS_INT64) + (Bits <= std::numeric_limits< unsigned __int64 >::digits) + +#else + 1 + +#endif (Bits <= std::numeric_limits< unsigned long >::digits) + (Bits <= std::numeric_limits< unsigned int >::digits) + (Bits <= std::numeric_limits< unsigned short >::digits) + @@ -86,30 +117,51 @@ namespace detail }; // map an extreme value to a category - template < long MaxValue > + template < intmax_t MaxValue > struct int_max_rank_helper { BOOST_STATIC_CONSTANT( int, rank = +#ifdef BOOST_HAS_LONG_LONG + (MaxValue <= integer_traits< long_long_type >::const_max) + +#elif defined(BOOST_HAS_MS_INT64) + (MaxValue <= integer_traits< __int64 >::const_max) + +#else + 1 + +#endif (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) ); }; - template < long MinValue > + template < intmax_t MinValue > struct int_min_rank_helper { BOOST_STATIC_CONSTANT( int, rank = +#ifdef BOOST_HAS_LONG_LONG + (MinValue >= integer_traits< long_long_type >::const_min) + +#elif defined(BOOST_HAS_MS_INT64) + (MinValue >= integer_traits< __int64 >::const_min) + +#else + 1 + +#endif (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) ); }; - template < unsigned long Value > + template < uintmax_t Value > struct uint_max_rank_helper { BOOST_STATIC_CONSTANT( int, rank = +#ifdef BOOST_HAS_LONG_LONG + (Value <= integer_traits< ulong_long_type >::const_max) + +#elif defined(BOOST_HAS_MS_INT64) + (Value <= integer_traits< unsigned __int64 >::const_max) + +#else + 1 + +#endif (Value <= integer_traits< unsigned long >::const_max) + (Value <= integer_traits< unsigned int >::const_max) + (Value <= integer_traits< unsigned short >::const_max) + @@ -146,7 +198,7 @@ namespace detail // integer templates specifying extreme value ----------------------------// // signed - template< long MaxValue > // maximum value to require support + template< intmax_t MaxValue > // maximum value to require support struct int_max_value_t { typedef typename detail::int_least_helper @@ -156,7 +208,7 @@ namespace detail typedef typename int_fast_t::fast fast; }; - template< long MinValue > // minimum value to require support + template< intmax_t MinValue > // minimum value to require support struct int_min_value_t { typedef typename detail::int_least_helper @@ -167,7 +219,7 @@ namespace detail }; // unsigned - template< unsigned long Value > // maximum value to require support + template< uintmax_t Value > // maximum value to require support struct uint_value_t { typedef typename detail::int_least_helper diff --git a/include/boost/integer_fwd.hpp b/include/boost/integer_fwd.hpp index 33cfc99..312cd7b 100644 --- a/include/boost/integer_fwd.hpp +++ b/include/boost/integer_fwd.hpp @@ -12,8 +12,9 @@ #include // for UCHAR_MAX, etc. #include // for std::size_t -#include // for BOOST_NO_INTRINSIC_WCHAR_T -#include // for std::numeric_limits +#include // for BOOST_NO_INTRINSIC_WCHAR_T +#include // for boost::uintmax_t, intmax_t +#include // for std::numeric_limits namespace boost @@ -24,6 +25,13 @@ namespace boost // Only has typedefs or using statements, with #conditionals +// ALERT: the forward declarations of items in need items +// from this header. That means that cannot #include this +// forwarding header, to avoid infinite recursion! One day, maybe +// boost::uintmax_t and boost::intmax_t could be segregated into their own +// header file (which can't #include this header), will use +// that header, and could refer to . + // From -----------------------------------------// @@ -85,13 +93,13 @@ template< int Bits > template< int Bits > struct uint_t; -template< long MaxValue > +template< intmax_t MaxValue > struct int_max_value_t; -template< long MinValue > +template< intmax_t MinValue > struct int_min_value_t; -template< unsigned long Value > +template< uintmax_t Value > struct uint_value_t; diff --git a/integer.htm b/integer.htm index 3d3f9c5..11b2f5b 100644 --- a/integer.htm +++ b/integer.htm @@ -21,7 +21,7 @@ is particularly useful for solving generic programming problems.

-

The exact_integral class template provides an MPL-compatible -alternative. This alternative has the form:

+

The sized_integral, exact_integral, +maximum_signed_integral, minimum_signed_integral, and +maximum_unsigned_integral class templates provide MPL-compatible +alternatives. These alternatives generally have the form:

 template< SwitchType SwitchValue, typename Signedness >
@@ -299,6 +341,11 @@ struct name
 	
 
 
+

The exceptions are the extreme-value class templates +(maximum_signed_integral, minimum_signed_integral, and +maximum_unsigned_integral), which do not take a Signedness +template parameter because the meta-functions already inherently have signedness. +

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 Signedness @@ -308,24 +355,66 @@ controls the appropriate emulation.)

Criteria for the MPL-Compatible Class Templates Class Template (all in name-space boost) - Parameter Type + Parameter Type (in name-space boost as needed) Parameter Member ID Classic Equivalent - Template Parameter Mapping (when type is defined) + Template Parameter Mapping (when type is defined) Signed Unsigned + + sized_integral + int + bit_count + int_t + uint_t + The smallest built-in integral type with at least + bit_count bits (including the sign bit when + Signedness is signed). Not present if no + type qualifies. + exact_integral int bit_count int_exact_t uint_exact_t - The smallest built-in integral type with exactly bit_count - bits (including the sign bit when Signedness is - signed). Not present if no type qualifies. + The smallest built-in integral type with exactly + bit_count bits (including the sign bit when + Signedness is signed). Not present if no + type qualifies. + + + maximum_signed_integral + intmax_t + bound + int_max_value_t + The smallest built-in integral type that can perserve the value in + bound. Not present if bound is non-positive. + It is possible for a type to be absent if + a platform supports really-extended integral types (beyond long + long or __int64), support for those types goes + into <boost/cstdint.hpp>, + but said support hadn't yet been added to <boost/integer.hpp> + + + minimum_signed_integral + intmax_t + bound + int_min_value_t + The smallest built-in integral type that can perserve the value in + bound. Not present if bound is non-negative. + + + maximum_unsigned_integral + uintmax_t + bound + uint_value_t + The smallest built-in integral type that can perserve the value in + bound. Should always be present. @@ -406,7 +495,7 @@ exact and value-based sized templates, and the MPL-compatible templates.


-

Revised July 15, 2008

+

Revised July 16, 2008

© Copyright Beman Dawes 1999. Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file // for BOOST_MPL_ASSERT_RELATION, etc. #include // for boost::mpl::back #include // for boost::mpl::copy +#include // for boost::mpl::equal #include // for boost::mpl::front_inserter #include // for boost::mpl::integral_c #include // for boost::mpl::joint_view @@ -221,13 +223,53 @@ std::size_t const integral_type_count = sizeof(integral_bit_lengths) / // Use SFINAE to check if a particular bit-count is supported template < int Bits > bool -print_out_exact_signed( boost::mpl::integral_c const &x, int bits, - typename boost::exact_integral::type *unused = 0 ) +print_out_sized_signed( boost::mpl::integral_c const &x, int bits, + typename boost::sized_integral::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 a sized_integral<" << bits << + ", signed> specialization, with type '" << typeid(typename + boost::sized_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_sized_signed( T const &x, int bits ) +{ + PRIVATE_SHOW_MESSAGE( "There is no sized_integral<" << bits << + ", signed> specialization." ); + return false; +} + +template < int Bits > +bool +print_out_sized_unsigned( boost::mpl::integral_c const &x, int bits, + typename boost::sized_integral::type *unused = 0 ) +{ + PRIVATE_SHOW_MESSAGE( "There is a sized_integral<" << bits << + ", unsigned> specialization, with type '" << typeid(typename + boost::sized_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_sized_unsigned( T const &x, int bits ) +{ + PRIVATE_SHOW_MESSAGE( "There is no sized_integral<" << bits << + ", unsigned> specialization." ); + return false; +} + +template < int Bits > +bool +print_out_exact_signed( boost::mpl::integral_c const &x, int bits, + typename boost::exact_integral::type *unused = 0 ) +{ PRIVATE_SHOW_MESSAGE( "There is an exact_integral<" << bits << ", signed> specialization, with type '" << typeid(typename boost::exact_integral::type).name() << "'." ); @@ -263,6 +305,69 @@ print_out_exact_unsigned( T const &x, int bits ) return false; } +template < boost::intmax_t Value > +bool +print_out_maximum_signed( boost::maximum_signed_integral const &x, + boost::intmax_t value, typename boost::maximum_signed_integral::type + *unused = 0 ) +{ + PRIVATE_SHOW_MESSAGE( "There is a maximum_signed_integral<" << value << + "> specialization, with type '" << typeid(typename + boost::maximum_signed_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_maximum_signed( T const &x, boost::intmax_t value ) +{ + PRIVATE_SHOW_MESSAGE( "There is no maximum_signed_integral<" << value << + "> specialization." ); + return false; +} + +template < boost::intmax_t Value > +bool +print_out_minimum_signed( boost::minimum_signed_integral const &x, + boost::intmax_t value, typename boost::minimum_signed_integral::type + *unused = 0 ) +{ + PRIVATE_SHOW_MESSAGE( "There is a minimum_signed_integral<" << value << + "> specialization, with type '" << typeid(typename + boost::minimum_signed_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_minimum_signed( T const &x, boost::intmax_t value ) +{ + PRIVATE_SHOW_MESSAGE( "There is no minimum_signed_integral<" << value << + "> specialization." ); + return false; +} + +template < boost::uintmax_t Value > +bool +print_out_maximum_unsigned( boost::maximum_unsigned_integral const &x, + boost::uintmax_t value, typename boost::maximum_unsigned_integral::type + *unused = 0 ) +{ + PRIVATE_SHOW_MESSAGE( "There is a maximum_unsigned_integral<" << value << + "> specialization, with type '" << typeid(typename + boost::maximum_unsigned_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_maximum_unsigned( T const &x, boost::uintmax_t value ) +{ + PRIVATE_SHOW_MESSAGE( "There is no maximum_unsigned_integral<" << value << + "> specialization." ); + return false; +} + } // unnamed namespace @@ -303,8 +408,18 @@ BOOST_AUTO_TEST_SUITE_END() // 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, exact or higher -BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_lengths_test, T, valid_bits_list ) +// Check the specialization type status of given bit lengths, minimum +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_lengths_test, T, bits_list ) +{ + BOOST_CHECK_EQUAL( print_out_sized_signed(T(), T::value), T::value <= + intmax_bits ); + BOOST_CHECK_EQUAL( print_out_sized_unsigned(T(), T::value), T::value <= + uintmax_bits ); +} + +// Check the classic specialization type status of given bit lengths, minimum +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_lengths_test, T, + valid_bits_list ) { // This test is supposed to replace the following printouts given in // puesdo-code by: @@ -357,22 +472,23 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_unsigned_values_test, T, // length of a integral type, so 1 << N would have to fit in the next larger // type. (This is why N can't be more than bitlength(uintmax_t) - 1.) #ifndef BOOST_NO_USING_TEMPLATE - using boost::is_same; - using boost::uint_value_t; - using boost::uint_t; + using boost::mpl::equal; + using boost::maximum_unsigned_integral; + using boost::sized_integral; #else + using namespace boost::mpl; using namespace boost; #endif boost::uintmax_t const one = 1u; int const count = T::value; - BOOST_MPL_ASSERT( (is_same::least, typename uint_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, typename uint_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, - typename uint_t::least>::value) ); + BOOST_MPL_ASSERT( (equal< maximum_unsigned_integral<(one << (count - 2))>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< maximum_unsigned_integral<(one << (count - 1))>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< maximum_unsigned_integral<(one << count)>, + sized_integral >) ); } // Check size comparisons of given value support, signed @@ -399,31 +515,32 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_signed_values_test, T, // type. (This is why N can't be more than bitlength(intmax_t) - 1. Note // that bitlength(intmax_t) + 1 == bitlength(uintmax_t).) #ifndef BOOST_NO_USING_TEMPLATE - using boost::is_same; - using boost::int_max_value_t; - using boost::int_t; - using boost::int_min_value_t; + using boost::mpl::equal; + using boost::maximum_signed_integral; + using boost::sized_integral; + using boost::minimum_signed_integral; #else + using namespace boost::mpl; using namespace boost; #endif boost::intmax_t const one = 1; int const count = T::value; - BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); + BOOST_MPL_ASSERT( (equal< maximum_signed_integral<+(one << (count - 2))>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< minimum_signed_integral<-(one << (count - 2))>, + sized_integral >) ); - BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); + BOOST_MPL_ASSERT( (equal< maximum_signed_integral<+(one << (count - 1))>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< minimum_signed_integral<-(one << (count - 1))>, + sized_integral >) ); - BOOST_MPL_ASSERT( (is_same::least, - typename int_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, - typename int_t::least>::value) ); + BOOST_MPL_ASSERT( (equal< maximum_signed_integral<+(one << count)>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< minimum_signed_integral<-(one << count)>, + sized_integral >) ); } // Check the specialization type status of given bit lengths, exact only @@ -462,6 +579,88 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_exact_lengths_test, T, uint_exact_t::exact>::digits, ==, T::value ); } +// Check if MPL-compatible templates give bad returns for out-of-range values +BOOST_AUTO_TEST_CASE( show_not_type_for_parameter_test ) +{ +#ifndef BOOST_NO_USING_TEMPLATE + using boost::sized_integral; + using boost::mpl::integral_c; + using boost::exact_integral; + using boost::maximum_signed_integral; + using boost::minimum_signed_integral; + using boost::maximum_unsigned_integral; +#else + using namespace boost; + using namespace boost::mpl; +#endif + + typedef sized_integral< 3, signed> ssz3_type; + typedef sized_integral< 0, signed> ssz0_type; + typedef sized_integral<-3, signed> ssz3n_type; + + BOOST_CHECK( print_out_sized_signed(integral_c(), + ssz3_type::bit_count) ); + BOOST_CHECK( !print_out_sized_signed(integral_c(), + ssz0_type::bit_count) ); + BOOST_CHECK( !print_out_sized_signed(integral_c(), + ssz3n_type::bit_count) ); + + typedef sized_integral< 3, unsigned> usz3_type; + typedef sized_integral< 0, unsigned> usz0_type; + typedef sized_integral<-3, unsigned> usz3n_type; + + BOOST_CHECK( print_out_sized_unsigned(integral_c(), + usz3_type::bit_count) ); + BOOST_CHECK( print_out_sized_unsigned(integral_c(), + usz0_type::bit_count) ); + BOOST_CHECK( !print_out_sized_unsigned(integral_c(), + usz3n_type::bit_count) ); + + typedef exact_integral< 3, signed> se3_type; + typedef exact_integral< 0, signed> se0_type; + typedef exact_integral<-3, signed> se3n_type; + + BOOST_CHECK( !print_out_exact_signed(integral_c(), + se3_type::bit_count) ); + BOOST_CHECK( !print_out_exact_signed(integral_c(), + se0_type::bit_count) ); + BOOST_CHECK( !print_out_exact_signed(integral_c(), + se3n_type::bit_count) ); + + typedef exact_integral< 3, unsigned> ue3_type; + typedef exact_integral< 0, unsigned> ue0_type; + typedef exact_integral<-3, unsigned> ue3n_type; + + BOOST_CHECK( !print_out_exact_unsigned(integral_c(), + ue3_type::bit_count) ); + BOOST_CHECK( !print_out_exact_unsigned(integral_c(), + ue0_type::bit_count) ); + BOOST_CHECK( !print_out_exact_unsigned(integral_c(), + ue3n_type::bit_count) ); + + typedef maximum_signed_integral< 15> max15_type; + typedef maximum_signed_integral< 0> max0_type; + typedef maximum_signed_integral<-15> max15n_type; + + BOOST_CHECK( print_out_maximum_signed(max15_type(), max15_type::bound) ); + BOOST_CHECK( !print_out_maximum_signed(max0_type(), max0_type::bound) ); + BOOST_CHECK( !print_out_maximum_signed(max15n_type(), max15n_type::bound) ); + + typedef minimum_signed_integral< 15> min15_type; + typedef minimum_signed_integral< 0> min0_type; + typedef minimum_signed_integral<-15> min15n_type; + + BOOST_CHECK( !print_out_minimum_signed(min15_type(), min15_type::bound) ); + BOOST_CHECK( !print_out_minimum_signed(min0_type(), min0_type::bound) ); + BOOST_CHECK( print_out_minimum_signed(min15n_type(), min15n_type::bound) ); + + typedef maximum_unsigned_integral<15> umax15_type; + typedef maximum_unsigned_integral< 0> umax0_type; + + BOOST_CHECK( print_out_maximum_unsigned(umax15_type(), umax15_type::bound) ); + BOOST_CHECK( print_out_maximum_unsigned(umax0_type(), umax0_type::bound) ); +} + BOOST_AUTO_TEST_SUITE_END() // Check if given constants can fit in given types @@ -485,6 +684,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T, // macros. The limit of type-lists is usually less than 32 (not to mention // 64) elements, so we have to take selected values. #ifndef BOOST_NO_USING_TEMPLATE + using boost::sized_integral; using boost::uint_t; using boost::int_t; #else @@ -497,7 +697,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T, boost::intmax_t const value_s = intmax_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION () >> shift; - BOOST_CHECK_EQUAL( typename uint_t::least(value_u), value_u ); + BOOST_CHECK_EQUAL( (typename sized_integral::type(value_u)), + value_u ); BOOST_CHECK_EQUAL( typename uint_t::least(value_u >> 1), value_u >> 1 ); BOOST_CHECK_EQUAL( typename uint_t::fast(value_u), value_u ); @@ -505,8 +706,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T, >> 1 ); BOOST_CHECK_EQUAL( typename int_t::least(value_s), value_s ); - BOOST_CHECK_EQUAL( typename int_t::least(value_s >> 1), value_s - >> 1 ); + BOOST_CHECK_EQUAL( (typename sized_integral::type(value_s + >> 1)), value_s >> 1 ); BOOST_CHECK_EQUAL( typename int_t::fast(value_s), value_s ); BOOST_CHECK_EQUAL( typename int_t::fast(value_s >> 1), value_s >> 1 ); From 203705fea6cf9da3d8dce7b92d56b256721ca293 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Wed, 23 Jul 2008 06:55:23 +0000 Subject: [PATCH 15/23] Moved preprocessor selection from within macro-function calls to surrounding whole macro calls (some compilers suspend preprocessor directives within a macro call) [SVN r47696] --- include/boost/integer.hpp | 50 +++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/include/boost/integer.hpp b/include/boost/integer.hpp index 5b8b6dc..1f7a750 100644 --- a/include/boost/integer.hpp +++ b/include/boost/integer.hpp @@ -103,14 +103,16 @@ namespace detail struct int_rank_helper { BOOST_STATIC_CONSTANT( int, mantissa = BitsIncludingSign - 1 ); - BOOST_STATIC_CONSTANT( int, rank = (BitsIncludingSign > 0) * ( #ifdef BOOST_HAS_LONG_LONG - (mantissa <= std::numeric_limits< long_long_type >::digits) + + BOOST_STATIC_CONSTANT( int, extended_ = (mantissa <= std::numeric_limits< + long_long_type >::digits) ); #elif defined(BOOST_HAS_MS_INT64) - (mantissa <= std::numeric_limits< __int64 >::digits) + + BOOST_STATIC_CONSTANT( int, extended_ = (mantissa <= std::numeric_limits< + __int64 >::digits) ); #else - 1 + + BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif + BOOST_STATIC_CONSTANT( int, rank = (BitsIncludingSign > 0) * (extended_ + (mantissa <= std::numeric_limits< long >::digits) + (mantissa <= std::numeric_limits< int >::digits) + (mantissa <= std::numeric_limits< short >::digits) + @@ -120,14 +122,16 @@ namespace detail template < int Bits > struct uint_rank_helper { - BOOST_STATIC_CONSTANT( int, rank = (Bits >= 0) * ( #ifdef BOOST_HAS_LONG_LONG - (Bits <= std::numeric_limits< ulong_long_type >::digits) + + BOOST_STATIC_CONSTANT( int, extended_ = (Bits <= std::numeric_limits< + ulong_long_type >::digits) ); #elif defined(BOOST_HAS_MS_INT64) - (Bits <= std::numeric_limits< unsigned __int64 >::digits) + + BOOST_STATIC_CONSTANT( int, extended_ = (Bits <= std::numeric_limits< + unsigned __int64 >::digits) ); #else - 1 + + BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif + BOOST_STATIC_CONSTANT( int, rank = (Bits >= 0) * (extended_ + (Bits <= std::numeric_limits< unsigned long >::digits) + (Bits <= std::numeric_limits< unsigned int >::digits) + (Bits <= std::numeric_limits< unsigned short >::digits) + @@ -177,14 +181,16 @@ namespace detail template < intmax_t MaxValue > struct int_max_rank_helper { - BOOST_STATIC_CONSTANT( int, rank = (MaxValue > 0) * ( #ifdef BOOST_HAS_LONG_LONG - (MaxValue <= integer_traits< long_long_type >::const_max) + + BOOST_STATIC_CONSTANT( int, extended_ = (MaxValue <= integer_traits< + long_long_type >::const_max) ); #elif defined(BOOST_HAS_MS_INT64) - (MaxValue <= integer_traits< __int64 >::const_max) + + BOOST_STATIC_CONSTANT( int, extended_ = (MaxValue <= integer_traits< + __int64 >::const_max) ); #else - 1 + + BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif + BOOST_STATIC_CONSTANT( int, rank = (MaxValue > 0) * (extended_ + (MaxValue <= integer_traits< long >::const_max) + (MaxValue <= integer_traits< int >::const_max) + (MaxValue <= integer_traits< short >::const_max) + @@ -194,14 +200,16 @@ namespace detail template < intmax_t MinValue > struct int_min_rank_helper { - BOOST_STATIC_CONSTANT( int, rank = (MinValue < 0) * ( #ifdef BOOST_HAS_LONG_LONG - (MinValue >= integer_traits< long_long_type >::const_min) + + BOOST_STATIC_CONSTANT( int, extended_ = (MinValue >= integer_traits< + long_long_type >::const_min) ); #elif defined(BOOST_HAS_MS_INT64) - (MinValue >= integer_traits< __int64 >::const_min) + + BOOST_STATIC_CONSTANT( int, extended_ = (MinValue >= integer_traits< + __int64 >::const_min) ); #else - 1 + + BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif + BOOST_STATIC_CONSTANT( int, rank = (MinValue < 0) * (extended_ + (MinValue >= integer_traits< long >::const_min) + (MinValue >= integer_traits< int >::const_min) + (MinValue >= integer_traits< short >::const_min) + @@ -211,14 +219,16 @@ namespace detail template < uintmax_t Value > struct uint_max_rank_helper { - BOOST_STATIC_CONSTANT( int, rank = #ifdef BOOST_HAS_LONG_LONG - (Value <= integer_traits< ulong_long_type >::const_max) + + BOOST_STATIC_CONSTANT( int, extended_ = (Value <= integer_traits< + ulong_long_type >::const_max) ); #elif defined(BOOST_HAS_MS_INT64) - (Value <= integer_traits< unsigned __int64 >::const_max) + + BOOST_STATIC_CONSTANT( int, extended_ = (Value <= integer_traits< unsigned + __int64 >::const_max) ); #else - 1 + + BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif + BOOST_STATIC_CONSTANT( int, rank = extended_ + (Value <= integer_traits< unsigned long >::const_max) + (Value <= integer_traits< unsigned int >::const_max) + (Value <= integer_traits< unsigned short >::const_max) + From 2b7ed6ebf73bbf92487bda93e69b2c4c917d1be4 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Wed, 23 Jul 2008 22:40:20 +0000 Subject: [PATCH 16/23] Resolved namespace conflict from unadorned call, which fixes #2134 [SVN r47742] --- include/boost/integer.hpp | 36 ++++++++++++++++++------------------ test/Jamfile.v2 | 1 + test/issue_2134.cpp | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 test/issue_2134.cpp diff --git a/include/boost/integer.hpp b/include/boost/integer.hpp index 1f7a750..7e0b86c 100644 --- a/include/boost/integer.hpp +++ b/include/boost/integer.hpp @@ -182,57 +182,57 @@ namespace detail struct int_max_rank_helper { #ifdef BOOST_HAS_LONG_LONG - BOOST_STATIC_CONSTANT( int, extended_ = (MaxValue <= integer_traits< + BOOST_STATIC_CONSTANT( int, extended_ = (MaxValue <= boost::integer_traits< long_long_type >::const_max) ); #elif defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT( int, extended_ = (MaxValue <= integer_traits< + BOOST_STATIC_CONSTANT( int, extended_ = (MaxValue <= boost::integer_traits< __int64 >::const_max) ); #else BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif BOOST_STATIC_CONSTANT( int, rank = (MaxValue > 0) * (extended_ + - (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 <= boost::integer_traits< long >::const_max) + + (MaxValue <= boost::integer_traits< int >::const_max) + + (MaxValue <= boost::integer_traits< short >::const_max) + + (MaxValue <= boost::integer_traits< signed char >::const_max)) ); }; template < intmax_t MinValue > struct int_min_rank_helper { #ifdef BOOST_HAS_LONG_LONG - BOOST_STATIC_CONSTANT( int, extended_ = (MinValue >= integer_traits< + BOOST_STATIC_CONSTANT( int, extended_ = (MinValue >= boost::integer_traits< long_long_type >::const_min) ); #elif defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT( int, extended_ = (MinValue >= integer_traits< + BOOST_STATIC_CONSTANT( int, extended_ = (MinValue >= boost::integer_traits< __int64 >::const_min) ); #else BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif BOOST_STATIC_CONSTANT( int, rank = (MinValue < 0) * (extended_ + - (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 >= boost::integer_traits< long >::const_min) + + (MinValue >= boost::integer_traits< int >::const_min) + + (MinValue >= boost::integer_traits< short >::const_min) + + (MinValue >= boost::integer_traits< signed char >::const_min)) ); }; template < uintmax_t Value > struct uint_max_rank_helper { #ifdef BOOST_HAS_LONG_LONG - BOOST_STATIC_CONSTANT( int, extended_ = (Value <= integer_traits< + BOOST_STATIC_CONSTANT( int, extended_ = (Value <= boost::integer_traits< ulong_long_type >::const_max) ); #elif defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT( int, extended_ = (Value <= integer_traits< unsigned + BOOST_STATIC_CONSTANT( int, extended_ = (Value <= boost::integer_traits< unsigned __int64 >::const_max) ); #else BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif BOOST_STATIC_CONSTANT( int, rank = extended_ + - (Value <= integer_traits< unsigned long >::const_max) + - (Value <= integer_traits< unsigned int >::const_max) + - (Value <= integer_traits< unsigned short >::const_max) + - (Value <= integer_traits< unsigned char >::const_max) ); + (Value <= boost::integer_traits< unsigned long >::const_max) + + (Value <= boost::integer_traits< unsigned int >::const_max) + + (Value <= boost::integer_traits< unsigned short >::const_max) + + (Value <= boost::integer_traits< unsigned char >::const_max) ); }; // convert rank to type, Boost.MPL-style diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f85e614..a0b5b19 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -16,4 +16,5 @@ test-suite integer /boost/test//boost_test_exec_monitor/static ] [ run static_min_max_test.cpp /boost/test//boost_test_exec_monitor/static ] + [ compile issue_2134.cpp ] ; diff --git a/test/issue_2134.cpp b/test/issue_2134.cpp new file mode 100644 index 0000000..26f8962 --- /dev/null +++ b/test/issue_2134.cpp @@ -0,0 +1,33 @@ +// boost Issue #2134 test program ------------------------------------------// + +// Copyright Daryle Walker 2008. Distributed under the Boost +// Software License, Version 1.0. (See the accompanying file +// LICENSE_1_0.txt or a copy at .) + +// See for documentation. +// See for the issue involved. + +// Revision History +// 23 Jul 2008 Initial version + +// Control if the inclusion error is triggered +#ifndef CONTROL_INCLUDE_TRAITS +#define CONTROL_INCLUDE_TRAITS 1 +#endif + +#if CONTROL_INCLUDE_TRAITS +// This file defines boost::detail::integer_traits. +#include +#endif + +// This is the file with the issue. It has items within the boost::detail +// namespace that referenced an unadorned "integer_traits". This was meant to +// refer to boost::integer_traits. However, +// defines a boost::detail::integer_traits. If that header is #included before +// this one, then b.d.integer_traits (rightfully) took priority, which lead to a +// syntax error. +#include + + +// Main program, minimal (since this is a compile test) +int main() { return 0; } From 4af7660410961279895c8eb8909268b415c74c1d Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Thu, 24 Jul 2008 11:43:02 +0000 Subject: [PATCH 17/23] Encapsulated the mutually exclusive 'long long' and '__int64' type families into a single interface [SVN r47754] --- include/boost/detail/extended_integer.hpp | 177 ++++++++++++++++++++++ include/boost/integer.hpp | 64 +++----- include/boost/integer_fwd.hpp | 8 +- include/boost/integer_traits.hpp | 75 ++------- test/integer_test.cpp | 14 +- 5 files changed, 218 insertions(+), 120 deletions(-) create mode 100644 include/boost/detail/extended_integer.hpp diff --git a/include/boost/detail/extended_integer.hpp b/include/boost/detail/extended_integer.hpp new file mode 100644 index 0000000..c69636c --- /dev/null +++ b/include/boost/detail/extended_integer.hpp @@ -0,0 +1,177 @@ +// Boost detail/extended_integer.hpp header file ----------------------------// + +// (C) Copyright Daryle Walker 2008. Distributed under the Boost Software +// License, Version 1.0. (See the accompanying file LICENSE_1_0.txt or a copy +// at .) + +// Encapsulates the double-long and __int64 type families as a single family, +// as they are mutually exclusive. + +/** \file + \brief Common definition of extended integer types. + + Instead of other Boost headers making separate \#defines for the double-long + and __int64 type families, since they're mutually exclusive, make a single + set of types and macros for the family that exists (if either). + */ + +#ifndef BOOST_DETAIL_EXTENDED_INTEGER_HPP +#define BOOST_DETAIL_EXTENDED_INTEGER_HPP + +#include // for BOOST_HAS_LONG_LONG and BOOST_HAS_MS_INT64 + +#include // for CHAR_BIT, etc. + + +namespace boost +{ +namespace detail +{ + + +// Extended integer type macro and alias definitions -----------------------// + +// (Unsigned) long long family +#ifdef BOOST_HAS_LONG_LONG + +// Existence +#define BOOST_HAS_XINT 1 + +// Extents +#ifdef ULLONG_MAX +#define BOOST_XINT_MAX LLONG_MAX +#define BOOST_XINT_MIN LLONG_MIN +#define BOOST_UXINT_MAX ULLONG_MAX +#elif defined(ULONG_LONG_MAX) +#define BOOST_XINT_MAX LONG_LONG_MAX +#define BOOST_XINT_MIN LONG_LONG_MIN +#define BOOST_UXINT_MAX ULONG_LONG_MAX +#elif defined(ULONGLONG_MAX) +#define BOOST_XINT_MAX LONGLONG_MAX +#define BOOST_XINT_MIN LONGLONG_MIN +#define BOOST_UXINT_MAX ULONGLONG_MAX +#elif defined(_LLONG_MAX) && defined(_C2) +#define BOOST_XINT_MAX _LLONG_MAX +#define BOOST_XINT_MIN (-_LLONG_MAX - _C2) +#define BOOST_UXINT_MAX _ULLONG_MAX +#else // guess +// Sometimes we get the double-long types without the corresponding constants, +// e.g. GCC in "-ansi" mode. In this case, we'll just have to work out the +// values ourselves. (Here we assume a two's complement representation.) +#define BOOST_XINT_MIN (1LL << (sizeof(::boost::long_long_type) * CHAR_BIT - 1)) +#define BOOST_XINT_MAX (~ BOOST_XINT_MIN) +#define BOOST_UXINT_MAX (~ 0uLL) +#endif + +// Types +typedef ::boost:: long_long_type xint_t; +typedef ::boost::ulong_long_type uxint_t; + +// (Unsigned) __int64 family +#elif defined(BOOST_HAS_MS_INT64) + +// Existence +#define BOOST_HAS_XINT 1 + +// Extents +#ifdef _UI64_MAX +#define BOOST_XINT_MAX _I64_MAX +#define BOOST_XINT_MIN _I64_MIN +#define BOOST_UXINT_MAX _UI64_MAX +#else // guess +// The types are exactly 2's-compl. 64-bit, so we'll enter the values directly. +#define BOOST_XINT_MAX 0x7FFFFFFFFFFFFFFFi64 +#define BOOST_XINT_MIN 0x8000000000000000i64 +#define BOOST_UXINT_MAX 0xFFFFFFFFFFFFFFFFui64 +#endif + +// Types +typedef __int64 xint_t; +typedef unsigned __int64 uxint_t; + +// Neither +#else + +// Non-existence +#define BOOST_HAS_XINT 0 + +// Dummy extents +#define BOOST_XINT_MAX LONG_MAX +#define BOOST_XINT_MIN LONG_MIN +#define BOOST_UXINT_MAX ULONG_MAX + +// Dummy types +typedef signed long xint_t; +typedef unsigned long uxint_t; + +#endif // defined(BOOST_HAS_LONG_LONG)/defined(BOOST_HAS_MS_INT64)/else + +/** \def BOOST_HAS_XINT + + \brief Flag for extended integer types. + + Indicates the presence of one of the two common extended integer type + families, either (unsigned) long long or + (unsigned) __int64. \c BOOST_HAS_XINT is \c 1 if + either type family is defined, and \c 0 if neither is. + */ + +/** \def BOOST_XINT_MAX + + \brief Maximum value for the signed extended integer type. + + \pre \c BOOST_HAS_XINT is \c \#defined to be \c 1. + + Macro constant representing the largest value the signed extended integer + type supports. Its composition may be another macro, an expression, or a + literal. Defaulted to \c LONG_MAX if \c BOOST_HAS_XINT is zero. + */ +/** \def BOOST_XINT_MIN + + \brief Minimum value for the signed extended integer type. + + \pre \c BOOST_HAS_XINT is \c \#defined to be \c 1. + + Macro constant representing the smallest value the signed extended integer + type supports. Its composition may be another macro, an expression, or a + literal. Defaulted to \c LONG_MIN if \c BOOST_HAS_XINT is zero. + */ +/** \def BOOST_UXINT_MAX + + \brief Maximum value for the unsigned extended integer type. + + \pre \c BOOST_HAS_XINT is \c \#defined to be \c 1. + + Macro constant representing the largest value the unsigned extended integer + type supports. Its composition may be another macro, an expression, or a + literal. Defaulted to \c ULONG_MAX if \c BOOST_HAS_XINT is zero. (Use + \c 0u for the type's minimum value.) + */ + +/** \typedef signed long boost::detail::xint_t + + \brief Alias for the signed extended integer type. + + \pre \c BOOST_HAS_XINT is \c \#defined to be \c 1. + + Alias representing the signed extended integer type, no matter which type + family it came from. Defaulted to signed long if + \c BOOST_HAS_XINT is zero. + */ +/** \typedef unsigned long ::boost::detail::uxint_t + + \brief Alias for the signed extended integer type. + + \pre \c BOOST_HAS_XINT is \c \#defined to be \c 1. + + Alias representing the unsigned extended integer type, no matter which type + family it came from. Defaulted to unsigned long if + \c BOOST_HAS_XINT is zero. + */ + + +} // namespace detail +} // namespace boost + + +#endif // BOOST_DETAIL_EXTENDED_INTEGER_HPP diff --git a/include/boost/integer.hpp b/include/boost/integer.hpp index 7e0b86c..531b405 100644 --- a/include/boost/integer.hpp +++ b/include/boost/integer.hpp @@ -29,6 +29,8 @@ #include // for std::numeric_limits #include // for boost::enable_if_c +#include // for BOOST_HAS_XINT, etc. + #include // for UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, etc. namespace boost @@ -64,15 +66,9 @@ namespace detail // 3=unsigned/int, 4=(unsigned) short, 5=(un)signed char // no specializations for 0: requests for a type > (unsigned) (long) long are // in error -#ifdef BOOST_HAS_LONG_LONG - template<> struct int_least_helper<1, signed> - { typedef long_long_type least; }; - template<> struct int_least_helper<1, unsigned> - { typedef ulong_long_type least; }; -#elif defined(BOOST_HAS_MS_INT64) - template<> struct int_least_helper<1, signed> { typedef __int64 least; }; - template<> struct int_least_helper<1, unsigned> - { typedef unsigned __int64 least; }; +#if BOOST_HAS_XINT + template<> struct int_least_helper<1, signed> { typedef xint_t least; }; + template<> struct int_least_helper<1, unsigned> { typedef uxint_t least; }; #endif template<> struct int_least_helper<2, signed> { typedef long least; }; template<> struct int_least_helper<2, unsigned> @@ -90,7 +86,7 @@ namespace detail // category bounds enum { -#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) +#if BOOST_HAS_XINT lowest_integral_rank = 1, #else lowest_integral_rank = 2, @@ -103,12 +99,9 @@ namespace detail struct int_rank_helper { BOOST_STATIC_CONSTANT( int, mantissa = BitsIncludingSign - 1 ); -#ifdef BOOST_HAS_LONG_LONG +#if BOOST_HAS_XINT BOOST_STATIC_CONSTANT( int, extended_ = (mantissa <= std::numeric_limits< - long_long_type >::digits) ); -#elif defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT( int, extended_ = (mantissa <= std::numeric_limits< - __int64 >::digits) ); + xint_t >::digits) ); #else BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif @@ -122,12 +115,9 @@ namespace detail template < int Bits > struct uint_rank_helper { -#ifdef BOOST_HAS_LONG_LONG +#if BOOST_HAS_XINT BOOST_STATIC_CONSTANT( int, extended_ = (Bits <= std::numeric_limits< - ulong_long_type >::digits) ); -#elif defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT( int, extended_ = (Bits <= std::numeric_limits< - unsigned __int64 >::digits) ); + uxint_t >::digits) ); #else BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif @@ -152,12 +142,9 @@ namespace detail struct uint_exact_rank_helper::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 ); +#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX) + BOOST_PRIVATE_INT_EXACT_BUILDER( xint_t, 1 ); + BOOST_PRIVATE_UINT_EXACT_BUILDER( uxint_t, 1 ); #endif #if ULONG_MAX > UINT_MAX BOOST_PRIVATE_INT_EXACT_BUILDER( long, 2 ); @@ -181,12 +168,9 @@ namespace detail template < intmax_t MaxValue > struct int_max_rank_helper { -#ifdef BOOST_HAS_LONG_LONG - BOOST_STATIC_CONSTANT( int, extended_ = (MaxValue <= boost::integer_traits< - long_long_type >::const_max) ); -#elif defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT( int, extended_ = (MaxValue <= boost::integer_traits< - __int64 >::const_max) ); +#if BOOST_HAS_XINT + BOOST_STATIC_CONSTANT( int, extended_ = (MaxValue <= + boost::integer_traits< xint_t >::const_max) ); #else BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif @@ -200,12 +184,9 @@ namespace detail template < intmax_t MinValue > struct int_min_rank_helper { -#ifdef BOOST_HAS_LONG_LONG - BOOST_STATIC_CONSTANT( int, extended_ = (MinValue >= boost::integer_traits< - long_long_type >::const_min) ); -#elif defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT( int, extended_ = (MinValue >= boost::integer_traits< - __int64 >::const_min) ); +#if BOOST_HAS_XINT + BOOST_STATIC_CONSTANT( int, extended_ = (MinValue >= + boost::integer_traits< xint_t >::const_min) ); #else BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif @@ -219,12 +200,9 @@ namespace detail template < uintmax_t Value > struct uint_max_rank_helper { -#ifdef BOOST_HAS_LONG_LONG +#if BOOST_HAS_XINT BOOST_STATIC_CONSTANT( int, extended_ = (Value <= boost::integer_traits< - ulong_long_type >::const_max) ); -#elif defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT( int, extended_ = (Value <= boost::integer_traits< unsigned - __int64 >::const_max) ); + uxint_t >::const_max) ); #else BOOST_STATIC_CONSTANT( int, extended_ = 1 ); #endif diff --git a/include/boost/integer_fwd.hpp b/include/boost/integer_fwd.hpp index 1cc1ce1..446ad66 100644 --- a/include/boost/integer_fwd.hpp +++ b/include/boost/integer_fwd.hpp @@ -16,6 +16,8 @@ #include // for boost::uintmax_t, intmax_t #include // for std::numeric_limits +#include // for BOOST_HAS_XINT, etc. + namespace boost { @@ -73,12 +75,12 @@ template < > template < > class integer_traits< unsigned long >; -#ifdef ULLONG_MAX +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && BOOST_HAS_XINT template < > - class integer_traits< ::boost::long_long_type>; + class integer_traits< ::boost::detail::xint_t >; template < > - class integer_traits< ::boost::ulong_long_type >; + class integer_traits< ::boost::detail::uxint_t >; #endif diff --git a/include/boost/integer_traits.hpp b/include/boost/integer_traits.hpp index 96b3526..4cdc817 100644 --- a/include/boost/integer_traits.hpp +++ b/include/boost/integer_traits.hpp @@ -27,6 +27,8 @@ #include #endif +#include // for BOOST_HAS_XINT, etc. + namespace boost { template @@ -155,77 +157,18 @@ class integer_traits public detail::integer_traits_base { }; -#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) -#if defined(ULLONG_MAX) && defined(BOOST_HAS_LONG_LONG) - +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && BOOST_HAS_XINT template<> -class integer_traits< ::boost::long_long_type> - : public std::numeric_limits< ::boost::long_long_type>, - public detail::integer_traits_base< ::boost::long_long_type, LLONG_MIN, LLONG_MAX> +class integer_traits< detail::xint_t > + : public std::numeric_limits< detail::xint_t >, + public detail::integer_traits_base< detail::xint_t, BOOST_XINT_MIN, BOOST_XINT_MAX > { }; template<> -class integer_traits< ::boost::ulong_long_type> - : public std::numeric_limits< ::boost::ulong_long_type>, - public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULLONG_MAX> +class integer_traits< detail::uxint_t > + : public std::numeric_limits< detail::uxint_t >, + public detail::integer_traits_base< detail::uxint_t, 0u, BOOST_UXINT_MAX > { }; - -#elif defined(ULONG_LONG_MAX) && defined(BOOST_HAS_LONG_LONG) - -template<> -class integer_traits< ::boost::long_long_type> : public std::numeric_limits< ::boost::long_long_type>, public detail::integer_traits_base< ::boost::long_long_type, LONG_LONG_MIN, LONG_LONG_MAX>{ }; -template<> -class integer_traits< ::boost::ulong_long_type> - : public std::numeric_limits< ::boost::ulong_long_type>, - public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULONG_LONG_MAX> -{ }; - -#elif defined(ULONGLONG_MAX) && defined(BOOST_HAS_LONG_LONG) - -template<> -class integer_traits< ::boost::long_long_type> - : public std::numeric_limits< ::boost::long_long_type>, - public detail::integer_traits_base< ::boost::long_long_type, LONGLONG_MIN, LONGLONG_MAX> -{ }; - -template<> -class integer_traits< ::boost::ulong_long_type> - : public std::numeric_limits< ::boost::ulong_long_type>, - public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULONGLONG_MAX> -{ }; - -#elif defined(_LLONG_MAX) && defined(_C2) && defined(BOOST_HAS_LONG_LONG) - -template<> -class integer_traits< ::boost::long_long_type> - : public std::numeric_limits< ::boost::long_long_type>, - public detail::integer_traits_base< ::boost::long_long_type, -_LLONG_MAX - _C2, _LLONG_MAX> -{ }; - -template<> -class integer_traits< ::boost::ulong_long_type> - : public std::numeric_limits< ::boost::ulong_long_type>, - public detail::integer_traits_base< ::boost::ulong_long_type, 0, _ULLONG_MAX> -{ }; - -#elif defined(BOOST_HAS_LONG_LONG) -// -// we have long long but no constants, this happens for example with gcc in -ansi mode, -// we'll just have to work out the values for ourselves (assumes 2's compliment representation): -// -template<> -class integer_traits< ::boost::long_long_type> - : public std::numeric_limits< ::boost::long_long_type>, - public detail::integer_traits_base< ::boost::long_long_type, (1LL << (sizeof(::boost::long_long_type) - 1)), ~(1LL << (sizeof(::boost::long_long_type) - 1))> -{ }; - -template<> -class integer_traits< ::boost::ulong_long_type> - : public std::numeric_limits< ::boost::ulong_long_type>, - public detail::integer_traits_base< ::boost::ulong_long_type, 0, ~0uLL> -{ }; - -#endif #endif } // namespace boost diff --git a/test/integer_test.cpp b/test/integer_test.cpp index 4e32cc1..63bb4ff 100644 --- a/test/integer_test.cpp +++ b/test/integer_test.cpp @@ -30,6 +30,8 @@ #include // for boost::integer_traits #include // for std::numeric_limits +#include // for BOOST_HAS_XINT, etc. + #include // for boost::mpl::plus, divides #include // for BOOST_MPL_ASSERT_RELATION, etc. #include // for boost::mpl::back @@ -110,10 +112,8 @@ typedef boost::mpl::vector< #if ULONG_MAX > UINT_MAX , unsigned long #endif -#if defined(BOOST_HAS_LONG_LONG) && ((ULLONG_MAX > ULONG_MAX) || (ULONGLONG_MAX > ULONG_MAX)) - , boost::ulong_long_type -#elif defined(BOOST_HAS_MS_INT64) && (0xFFFFFFFFFFFFFFFFui64 > ULONG_MAX) - , unsigned __int64 +#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX) + , boost::detail::uxint_t #endif > distinct_unsigned_types; @@ -210,10 +210,8 @@ int const integral_bit_lengths[] = { #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 +#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX) + , std::numeric_limits< boost::detail::uxint_t >::digits #endif }; From 2fcbc31b77bfa9704f1f3db7f6add866c14c7002 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Fri, 25 Jul 2008 12:39:06 +0000 Subject: [PATCH 18/23] Tightened up code; number of bit-counts sampled is now comprehensive instead of representative (with a preprocessor switch for the old behavior since the new behavior greatly increases compile times) [SVN r47801] --- test/integer_test.cpp | 618 ++++++++++++++++-------------------------- 1 file changed, 230 insertions(+), 388 deletions(-) diff --git a/test/integer_test.cpp b/test/integer_test.cpp index 63bb4ff..4b34d40 100644 --- a/test/integer_test.cpp +++ b/test/integer_test.cpp @@ -21,16 +21,15 @@ #define BOOST_TEST_MODULE "Integer size-selection tests" -#include // unit testing framework -#include +#include // unit testing framework -#include // for BOOST_NO_USING_TEMPLATE, etc. +#include // for BOOST_NO_SFINAE #include // for boost::uintmax_t, intmax_t #include // for boost::int_t, boost::uint_t, etc. #include // for boost::integer_traits #include // for std::numeric_limits -#include // for BOOST_HAS_XINT, etc. +#include // BOOST_HAS_XINT, BOOST_UXINT_MAX #include // for boost::mpl::plus, divides #include // for BOOST_MPL_ASSERT_RELATION, etc. @@ -38,11 +37,13 @@ #include // for boost::mpl::copy #include // for boost::mpl::equal #include // for boost::mpl::front_inserter +#include // for boost::mpl::int_ #include // for boost::mpl::integral_c #include // for boost::mpl::joint_view #include // for boost::mpl::pop_back #include // for boost::mpl::push_back #include // for boost::mpl::push_front +#include // for boost::mpl::range_c #include // for boost::mpl::sort #include // for boost::mpl::transform #include // for boost::mpl::transform_view @@ -72,6 +73,12 @@ #define CONTROL_SHOW_TYPES 0 #endif +// Control if every potential bit-count is used, or only a selection +// For me, full counts increase compile time from 90 seconds to 20 minutes! +#ifndef CONTROL_FULL_COUNTS +#define CONTROL_FULL_COUNTS 1 +#endif + // If specializations have not already been done, then we can confirm // the effects of the fast types by making a specialization. If there @@ -123,21 +130,16 @@ typedef boost::mpl::transform< >::type distinct_signed_types; // List the digit counts for each integral type -class dibc_helper +template < typename T > +struct digits_of + : boost::mpl::int_< std::numeric_limits::digits > { - template < typename T > - struct type_to_digit_count - : boost::mpl::integral_c< int, std::numeric_limits::digits > - {}; - -public: - typedef boost::mpl::transform< - distinct_unsigned_types, - type_to_digit_count< boost::mpl::_1 > - >::type type; }; -typedef dibc_helper::type distinct_integral_bit_counts; +typedef boost::mpl::transform< + distinct_unsigned_types, + digits_of< boost::mpl::_1 > +>::type distinct_integral_bit_counts; // Make list of bit counts between each offical point, plus CHAR_BIT/2 typedef boost::mpl::transform_view< @@ -166,6 +168,9 @@ int const intmax_bits = intmax_limits::digits + 1; int const uintmax_bits = uintmax_limits::digits; // Make master lists including an outlier beyond all valid bit counts +#if CONTROL_FULL_COUNTS +typedef boost::mpl::range_c bits_list; +#else typedef boost::mpl::sort< boost::mpl::copy< boost::mpl::joint_view< @@ -179,23 +184,46 @@ typedef boost::mpl::sort< > >::type >::type bits_list; +#endif // Remove the outlier when all bits counts must be valid +#if CONTROL_FULL_COUNTS +typedef boost::mpl::range_c valid_bits_list; +#else typedef boost::mpl::pop_back::type valid_bits_list; +#endif + +// Replace the minimum bit count with one more, so right-shifting by a stored +// value doesn't give an invalid result +#if CONTROL_FULL_COUNTS +typedef boost::mpl::range_c + valid_to_decrease_bits_list; +#else +typedef valid_bits_list valid_to_decrease_bits_list; +#endif // Replace the maximum bit count with one less, so left-shifting by a stored // value doesn't give an invalid result +#if CONTROL_FULL_COUNTS +typedef boost::mpl::range_c valid_to_increase_ubits_list; +#else typedef boost::mpl::push_back< boost::mpl::pop_back< valid_bits_list >::type, boost::mpl::integral_c< int, uintmax_bits - 1 > >::type valid_to_increase_ubits_list; +#endif // Do it again for signed types since they have one-less bit to use for the // mantissa (don't want to shift into the sign bit) +#if CONTROL_FULL_COUNTS +typedef boost::mpl::range_c + valid_to_increase_sbits_list; +#else typedef boost::mpl::push_back< boost::mpl::pop_back< valid_bits_list >::type, boost::mpl::integral_c< int, intmax_bits - 3 > >::type valid_to_increase_sbits_list; +#endif // List the digit counts for each integral type, this time as an object, an // array working as a sorted list @@ -218,153 +246,49 @@ int const integral_bit_lengths[] = { 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-typedefs" to reduce two-argument templates to single-argument. +// This way, all the MPL-compatible templates have the same form, for below. template < int Bits > +struct signed_sized_integral : boost::sized_integral {}; + +template < int Bits > +struct unsigned_sized_integral : boost::sized_integral {}; + +template < int Bits > +struct signed_exact_integral : boost::exact_integral {}; + +template < int Bits > +struct unsigned_exact_integral : boost::exact_integral {}; + +// Use SFINAE to check if a particular parameter is supported +#ifndef BOOST_NO_SFINAE +template < typename ValueT, template class Tmpl, ValueT Value > bool -print_out_sized_signed( boost::mpl::integral_c const &x, int bits, - typename boost::sized_integral::type *unused = 0 ) +print_out_template( Tmpl const &, ValueT setting, char const + *template_pre_name, char const *template_post_name, typename Tmpl::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 a sized_integral<" << bits << - ", signed> specialization, with type '" << typeid(typename - boost::sized_integral::type).name() << "'." ); + PRIVATE_SHOW_MESSAGE( "This is " << template_pre_name << setting + << template_post_name << " specialization, with type '" << typeid(typename + Tmpl::type).name() << "'." ); return true; } -template < typename T > +template < typename ValueT, typename T > bool -print_out_sized_signed( T const &x, int bits ) +print_out_template( T const &, ValueT setting, char const *template_pre_name, + char const *template_post_name ) { - PRIVATE_SHOW_MESSAGE( "There is no sized_integral<" << bits << - ", signed> specialization." ); - return false; -} - -template < int Bits > -bool -print_out_sized_unsigned( boost::mpl::integral_c const &x, int bits, - typename boost::sized_integral::type *unused = 0 ) -{ - PRIVATE_SHOW_MESSAGE( "There is a sized_integral<" << bits << - ", unsigned> specialization, with type '" << typeid(typename - boost::sized_integral::type).name() << "'." ); - return true; -} - -template < typename T > -bool -print_out_sized_unsigned( T const &x, int bits ) -{ - PRIVATE_SHOW_MESSAGE( "There is no sized_integral<" << bits << - ", unsigned> specialization." ); - return false; -} - -template < int Bits > -bool -print_out_exact_signed( boost::mpl::integral_c const &x, int bits, - typename boost::exact_integral::type *unused = 0 ) -{ - PRIVATE_SHOW_MESSAGE( "There is an exact_integral<" << bits << - ", signed> specialization, with type '" << typeid(typename - boost::exact_integral::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 const &x, int bits, - typename boost::exact_integral::type *unused = 0 ) -{ - PRIVATE_SHOW_MESSAGE( "There is an exact_integral<" << bits << - ", unsigned> specialization, with type '" << typeid(typename - boost::exact_integral::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; -} - -template < boost::intmax_t Value > -bool -print_out_maximum_signed( boost::maximum_signed_integral const &x, - boost::intmax_t value, typename boost::maximum_signed_integral::type - *unused = 0 ) -{ - PRIVATE_SHOW_MESSAGE( "There is a maximum_signed_integral<" << value << - "> specialization, with type '" << typeid(typename - boost::maximum_signed_integral::type).name() << "'." ); - return true; -} - -template < typename T > -bool -print_out_maximum_signed( T const &x, boost::intmax_t value ) -{ - PRIVATE_SHOW_MESSAGE( "There is no maximum_signed_integral<" << value << - "> specialization." ); - return false; -} - -template < boost::intmax_t Value > -bool -print_out_minimum_signed( boost::minimum_signed_integral const &x, - boost::intmax_t value, typename boost::minimum_signed_integral::type - *unused = 0 ) -{ - PRIVATE_SHOW_MESSAGE( "There is a minimum_signed_integral<" << value << - "> specialization, with type '" << typeid(typename - boost::minimum_signed_integral::type).name() << "'." ); - return true; -} - -template < typename T > -bool -print_out_minimum_signed( T const &x, boost::intmax_t value ) -{ - PRIVATE_SHOW_MESSAGE( "There is no minimum_signed_integral<" << value << - "> specialization." ); - return false; -} - -template < boost::uintmax_t Value > -bool -print_out_maximum_unsigned( boost::maximum_unsigned_integral const &x, - boost::uintmax_t value, typename boost::maximum_unsigned_integral::type - *unused = 0 ) -{ - PRIVATE_SHOW_MESSAGE( "There is a maximum_unsigned_integral<" << value << - "> specialization, with type '" << typeid(typename - boost::maximum_unsigned_integral::type).name() << "'." ); - return true; -} - -template < typename T > -bool -print_out_maximum_unsigned( T const &x, boost::uintmax_t value ) -{ - PRIVATE_SHOW_MESSAGE( "There is no maximum_unsigned_integral<" << value << - "> specialization." ); + PRIVATE_SHOW_MESSAGE( "Looking for " << template_pre_name << setting + << template_post_name << " specialization? It doesn't exist." ); return false; } +#else +#error "These tests cannot work without Substitution-Failure-Is-Not-An-Error" +#endif } // unnamed namespace @@ -375,25 +299,17 @@ BOOST_AUTO_TEST_SUITE( optimized_type_tests ) // Check the optimzed type override of a given type BOOST_AUTO_TEST_CASE( fast_type_test ) { -#ifndef BOOST_NO_USING_TEMPLATE - using std::numeric_limits; - using boost::is_same; -#else - using namespace std; - using namespace boost; -#endif - typedef short least_type; typedef boost::int_fast_t::fast fast_type; - typedef numeric_limits least_limits; - typedef numeric_limits fast_limits; + typedef std::numeric_limits least_limits; + typedef std::numeric_limits fast_limits; typedef boost::fast_integral::type real_fast_type; - BOOST_MPL_ASSERT_RELATION( (is_same::value), ==, - false ); - BOOST_MPL_ASSERT_RELATION( (is_same::value), ==, - true ); + BOOST_MPL_ASSERT_RELATION( (boost::is_same::value), + ==, false ); + BOOST_MPL_ASSERT_RELATION( (boost::is_same::value), ==, true ); BOOST_MPL_ASSERT_RELATION( fast_limits::is_specialized, ==, true ); BOOST_MPL_ASSERT_RELATION( fast_limits::is_signed && fast_limits::is_bounded, ==, true ); @@ -409,14 +325,16 @@ BOOST_AUTO_TEST_SUITE( show_type_tests ) // Check the specialization type status of given bit lengths, minimum BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_lengths_test, T, bits_list ) { - BOOST_CHECK_EQUAL( print_out_sized_signed(T(), T::value), T::value <= - intmax_bits ); - BOOST_CHECK_EQUAL( print_out_sized_unsigned(T(), T::value), T::value <= - uintmax_bits ); + BOOST_CHECK_EQUAL( print_out_template(signed_sized_integral(), + T::value, "a sized_integral<", ", signed>"), T::value && (T::value <= + intmax_bits) ); + BOOST_CHECK_EQUAL( print_out_template(unsigned_sized_integral(), + T::value, "a sized_integral<", ", unsigned>"), T::value <= uintmax_bits ); } -// Check the classic specialization type status of given bit lengths, minimum -BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_lengths_test, T, +// Check the classic specialization type status of given bit lengths, minimum, +// unsigned +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_lengths_unsigned_test, T, valid_bits_list ) { // This test is supposed to replace the following printouts given in @@ -432,23 +350,21 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_lengths_test, T, // of type-lists is usually less than 32 (not to mention 64) elements, so we // have to take selected values. The only interesting part is if the bit // count is too large, and we can't check that yet. -#ifndef BOOST_NO_USING_TEMPLATE - using std::numeric_limits; - using boost::int_t; - using boost::uint_t; -#else - using namespace std; - using namespace boost; -#endif + BOOST_MPL_ASSERT_RELATION( std::numeric_limits::least>::digits, >=, T::value ); + BOOST_MPL_ASSERT_RELATION( std::numeric_limits::fast>::digits, >=, T::value ); +} - BOOST_MPL_ASSERT_RELATION( numeric_limits::least>::digits, >=, T::value - 1 ); - BOOST_MPL_ASSERT_RELATION( numeric_limits::fast>::digits, >=, T::value - 1 ); - BOOST_MPL_ASSERT_RELATION( numeric_limits::least>::digits, >=, T::value ); - BOOST_MPL_ASSERT_RELATION( numeric_limits::fast>::digits, >=, T::value ); +// Check the classic specialization type status of given bit lengths, minimum, +// signed +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_lengths_signed_test, T, + valid_to_decrease_bits_list ) +{ + BOOST_MPL_ASSERT_RELATION( std::numeric_limits::least>::digits, >=, T::value - 1 ); + BOOST_MPL_ASSERT_RELATION( std::numeric_limits::fast>::digits, >=, T::value - 1 ); } // Check size comparisons of given value support, unsigned @@ -469,24 +385,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_unsigned_values_test, T, // have to take selected values. The interesting parts are where N is the // length of a integral type, so 1 << N would have to fit in the next larger // type. (This is why N can't be more than bitlength(uintmax_t) - 1.) -#ifndef BOOST_NO_USING_TEMPLATE - using boost::mpl::equal; - using boost::maximum_unsigned_integral; - using boost::sized_integral; -#else - using namespace boost::mpl; - using namespace boost; -#endif - boost::uintmax_t const one = 1u; - int const count = T::value; - BOOST_MPL_ASSERT( (equal< maximum_unsigned_integral<(one << (count - 2))>, - sized_integral >) ); - BOOST_MPL_ASSERT( (equal< maximum_unsigned_integral<(one << (count - 1))>, - sized_integral >) ); - BOOST_MPL_ASSERT( (equal< maximum_unsigned_integral<(one << count)>, - sized_integral >) ); + BOOST_MPL_ASSERT( (boost::mpl::equal< boost::maximum_unsigned_integral<(one + << T::value)>, unsigned_sized_integral >) ); } // Check size comparisons of given value support, signed @@ -512,151 +414,124 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_signed_values_test, T, // length of a integral type, so 1 << N would have to fit in the next larger // type. (This is why N can't be more than bitlength(intmax_t) - 1. Note // that bitlength(intmax_t) + 1 == bitlength(uintmax_t).) -#ifndef BOOST_NO_USING_TEMPLATE - using boost::mpl::equal; - using boost::maximum_signed_integral; - using boost::sized_integral; - using boost::minimum_signed_integral; -#else - using namespace boost::mpl; - using namespace boost; -#endif + static boost::intmax_t const one = 1; - boost::intmax_t const one = 1; - int const count = T::value; - - BOOST_MPL_ASSERT( (equal< maximum_signed_integral<+(one << (count - 2))>, - sized_integral >) ); - BOOST_MPL_ASSERT( (equal< minimum_signed_integral<-(one << (count - 2))>, - sized_integral >) ); - - BOOST_MPL_ASSERT( (equal< maximum_signed_integral<+(one << (count - 1))>, - sized_integral >) ); - BOOST_MPL_ASSERT( (equal< minimum_signed_integral<-(one << (count - 1))>, - sized_integral >) ); - - BOOST_MPL_ASSERT( (equal< maximum_signed_integral<+(one << count)>, - sized_integral >) ); - BOOST_MPL_ASSERT( (equal< minimum_signed_integral<-(one << count)>, - sized_integral >) ); + BOOST_MPL_ASSERT( (boost::mpl::equal< boost::maximum_signed_integral<+(one + << T::value)>, signed_sized_integral >) ); + BOOST_MPL_ASSERT( (boost::mpl::equal< boost::minimum_signed_integral<-(one + << T::value)>, signed_sized_integral >) ); } // 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 + bool const is_exact_length = std::binary_search( integral_bit_lengths, + integral_bit_lengths + integral_type_count, T::value ); - 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) ); + BOOST_CHECK_EQUAL( print_out_template(signed_exact_integral(), + T::value, "an exact_integral<", ", signed>"), is_exact_length ); + BOOST_CHECK_EQUAL( print_out_template(unsigned_exact_integral(), + T::value, "an exact_integral<", ", unsigned>"), is_exact_length ); } // 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::exact>::digits, ==, T::value - 1 ); - BOOST_MPL_ASSERT_RELATION( numeric_limits::exact>::digits, ==, T::value ); + BOOST_MPL_ASSERT_RELATION( std::numeric_limits::exact>::digits, ==, T::value - 1 ); + BOOST_MPL_ASSERT_RELATION( std::numeric_limits::exact>::digits, ==, T::value ); } // Check if MPL-compatible templates give bad returns for out-of-range values BOOST_AUTO_TEST_CASE( show_not_type_for_parameter_test ) { -#ifndef BOOST_NO_USING_TEMPLATE - using boost::sized_integral; - using boost::mpl::integral_c; - using boost::exact_integral; - using boost::maximum_signed_integral; - using boost::minimum_signed_integral; - using boost::maximum_unsigned_integral; -#else - using namespace boost; - using namespace boost::mpl; -#endif + typedef signed_sized_integral< 3> ssz3_type; + typedef signed_sized_integral< 0> ssz0_type; + typedef signed_sized_integral<-3> ssz3n_type; - typedef sized_integral< 3, signed> ssz3_type; - typedef sized_integral< 0, signed> ssz0_type; - typedef sized_integral<-3, signed> ssz3n_type; + BOOST_CHECK( print_out_template(ssz3_type(), ssz3_type::bit_count, + "a sized_integral<", ", signed>") ); + BOOST_CHECK( !print_out_template(ssz0_type(), ssz0_type::bit_count, + "a sized_integral<", ", signed>") ); + BOOST_CHECK( !print_out_template(ssz3n_type(), ssz3n_type::bit_count, + "a sized_integral<", ", signed>") ); - BOOST_CHECK( print_out_sized_signed(integral_c(), - ssz3_type::bit_count) ); - BOOST_CHECK( !print_out_sized_signed(integral_c(), - ssz0_type::bit_count) ); - BOOST_CHECK( !print_out_sized_signed(integral_c(), - ssz3n_type::bit_count) ); + typedef unsigned_sized_integral< 3> usz3_type; + typedef unsigned_sized_integral< 0> usz0_type; + typedef unsigned_sized_integral<-3> usz3n_type; - typedef sized_integral< 3, unsigned> usz3_type; - typedef sized_integral< 0, unsigned> usz0_type; - typedef sized_integral<-3, unsigned> usz3n_type; + BOOST_CHECK( print_out_template(usz3_type(), usz3_type::bit_count, + "a sized_integral<", ", unsigned>") ); + BOOST_CHECK( print_out_template(usz0_type(), usz0_type::bit_count, + "a sized_integral<", ", unsigned>") ); + BOOST_CHECK( !print_out_template(usz3n_type(), usz3n_type::bit_count, + "a sized_integral<", ", unsigned>") ); - BOOST_CHECK( print_out_sized_unsigned(integral_c(), - usz3_type::bit_count) ); - BOOST_CHECK( print_out_sized_unsigned(integral_c(), - usz0_type::bit_count) ); - BOOST_CHECK( !print_out_sized_unsigned(integral_c(), - usz3n_type::bit_count) ); + typedef signed_exact_integral< CHAR_BIT > se8_type; + typedef signed_exact_integral< 3> se3_type; + typedef signed_exact_integral< 0> se0_type; + typedef signed_exact_integral<-3> se3n_type; + typedef signed_exact_integral< - CHAR_BIT > se8n_type; - typedef exact_integral< 3, signed> se3_type; - typedef exact_integral< 0, signed> se0_type; - typedef exact_integral<-3, signed> se3n_type; + BOOST_CHECK( print_out_template(se8_type(), se8_type::bit_count, + "an exact_integral<", ", signed>") ); + BOOST_CHECK( !print_out_template(se3_type(), se3_type::bit_count, + "an exact_integral<", ", signed>") ); + BOOST_CHECK( !print_out_template(se0_type(), se0_type::bit_count, + "an exact_integral<", ", signed>") ); + BOOST_CHECK( !print_out_template(se3n_type(), se3n_type::bit_count, + "an exact_integral<", ", signed>") ); + BOOST_CHECK( !print_out_template(se8n_type(), se8n_type::bit_count, + "an exact_integral<", ", signed>") ); - BOOST_CHECK( !print_out_exact_signed(integral_c(), - se3_type::bit_count) ); - BOOST_CHECK( !print_out_exact_signed(integral_c(), - se0_type::bit_count) ); - BOOST_CHECK( !print_out_exact_signed(integral_c(), - se3n_type::bit_count) ); + typedef unsigned_exact_integral< CHAR_BIT > ue8_type; + typedef unsigned_exact_integral< 3> ue3_type; + typedef unsigned_exact_integral< 0> ue0_type; + typedef unsigned_exact_integral<-3> ue3n_type; + typedef unsigned_exact_integral< - CHAR_BIT > ue8n_type; - typedef exact_integral< 3, unsigned> ue3_type; - typedef exact_integral< 0, unsigned> ue0_type; - typedef exact_integral<-3, unsigned> ue3n_type; + BOOST_CHECK( print_out_template(ue8_type(), ue8_type::bit_count, + "an exact_integral<", ", unsigned>") ); + BOOST_CHECK( !print_out_template(ue3_type(), ue3_type::bit_count, + "an exact_integral<", ", unsigned>") ); + BOOST_CHECK( !print_out_template(ue0_type(), ue0_type::bit_count, + "an exact_integral<", ", unsigned>") ); + BOOST_CHECK( !print_out_template(ue3n_type(), ue3n_type::bit_count, + "an exact_integral<", ", unsigned>") ); + BOOST_CHECK( !print_out_template(ue8n_type(), ue8n_type::bit_count, + "an exact_integral<", ", unsigned>") ); - BOOST_CHECK( !print_out_exact_unsigned(integral_c(), - ue3_type::bit_count) ); - BOOST_CHECK( !print_out_exact_unsigned(integral_c(), - ue0_type::bit_count) ); - BOOST_CHECK( !print_out_exact_unsigned(integral_c(), - ue3n_type::bit_count) ); + typedef boost::maximum_signed_integral< 15> max15_type; + typedef boost::maximum_signed_integral< 0> max0_type; + typedef boost::maximum_signed_integral<-15> max15n_type; - typedef maximum_signed_integral< 15> max15_type; - typedef maximum_signed_integral< 0> max0_type; - typedef maximum_signed_integral<-15> max15n_type; + BOOST_CHECK( print_out_template(max15_type(), max15_type::bound, + "a maximum_signed_integral<", ">") ); + BOOST_CHECK( !print_out_template(max0_type(), max0_type::bound, + "a maximum_signed_integral<", ">") ); + BOOST_CHECK( !print_out_template(max15n_type(), max15n_type::bound, + "a maximum_signed_integral<", ">") ); - BOOST_CHECK( print_out_maximum_signed(max15_type(), max15_type::bound) ); - BOOST_CHECK( !print_out_maximum_signed(max0_type(), max0_type::bound) ); - BOOST_CHECK( !print_out_maximum_signed(max15n_type(), max15n_type::bound) ); + typedef boost::minimum_signed_integral< 15> min15_type; + typedef boost::minimum_signed_integral< 0> min0_type; + typedef boost::minimum_signed_integral<-15> min15n_type; - typedef minimum_signed_integral< 15> min15_type; - typedef minimum_signed_integral< 0> min0_type; - typedef minimum_signed_integral<-15> min15n_type; + BOOST_CHECK( !print_out_template(min15_type(), min15_type::bound, + "a minimum_signed_integral<", ">") ); + BOOST_CHECK( !print_out_template(min0_type(), min0_type::bound, + "a minimum_signed_integral<", ">") ); + BOOST_CHECK( print_out_template(min15n_type(), min15n_type::bound, + "a minimum_signed_integral<", ">") ); - BOOST_CHECK( !print_out_minimum_signed(min15_type(), min15_type::bound) ); - BOOST_CHECK( !print_out_minimum_signed(min0_type(), min0_type::bound) ); - BOOST_CHECK( print_out_minimum_signed(min15n_type(), min15n_type::bound) ); + typedef boost::maximum_unsigned_integral<15> umax15_type; + typedef boost::maximum_unsigned_integral< 0> umax0_type; - typedef maximum_unsigned_integral<15> umax15_type; - typedef maximum_unsigned_integral< 0> umax0_type; - - BOOST_CHECK( print_out_maximum_unsigned(umax15_type(), umax15_type::bound) ); - BOOST_CHECK( print_out_maximum_unsigned(umax0_type(), umax0_type::bound) ); + BOOST_CHECK( print_out_template(umax15_type(), umax15_type::bound, + "a maximum_unsigned_integral<", ">") ); + BOOST_CHECK( print_out_template(umax0_type(), umax0_type::bound, + "a maximum_unsigned_integral<", ">") ); } BOOST_AUTO_TEST_SUITE_END() @@ -666,7 +541,7 @@ BOOST_AUTO_TEST_SUITE( fit_type_tests ) // Check if large value can fit its minimum required size, by size BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T, - valid_bits_list ) + valid_to_decrease_bits_list ) { // This test is supposed to replace the following checks given in // puesdo-code by: @@ -681,58 +556,42 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T, // 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. -#ifndef BOOST_NO_USING_TEMPLATE - using boost::sized_integral; - using boost::uint_t; - using boost::int_t; -#else - using namespace boost; -#endif - - int const count = T::value, shift = uintmax_bits - count; + static int const count = T::value; + int const shift = uintmax_bits - count; boost::uintmax_t const value_u = uintmax_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION () >> shift; boost::intmax_t const value_s = intmax_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION () >> shift; - BOOST_CHECK_EQUAL( (typename sized_integral::type(value_u)), - value_u ); - BOOST_CHECK_EQUAL( typename uint_t::least(value_u >> 1), value_u - >> 1 ); - BOOST_CHECK_EQUAL( typename uint_t::fast(value_u), value_u ); - BOOST_CHECK_EQUAL( typename uint_t::fast(value_u >> 1), value_u - >> 1 ); + BOOST_CHECK_EQUAL( static_cast::type>(value_u), value_u ); + BOOST_CHECK_EQUAL( static_cast::least>(value_u), value_u ); + BOOST_CHECK_EQUAL( static_cast::fast>(value_u), value_u ); - BOOST_CHECK_EQUAL( typename int_t::least(value_s), value_s ); - BOOST_CHECK_EQUAL( (typename sized_integral::type(value_s - >> 1)), value_s >> 1 ); - BOOST_CHECK_EQUAL( typename int_t::fast(value_s), value_s ); - BOOST_CHECK_EQUAL( typename int_t::fast(value_s >> 1), value_s >> - 1 ); + BOOST_CHECK_EQUAL( static_cast::type>(value_s), value_s ); + BOOST_CHECK_EQUAL( static_cast::least>(value_s), value_s ); + BOOST_CHECK_EQUAL( static_cast::fast>(value_s), value_s ); } // 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::type uexact_type; - typedef typename exact_integral::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 ); + typename boost::exact_integral::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 ); + typename boost::exact_integral::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 ); @@ -757,21 +616,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_unsigned_values_test, T, // 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; -#ifndef BOOST_NO_USING_TEMPLATE - using boost::uint_value_t; -#else - using namespace boost; -#endif - uintmax_t const max_u = boost::integer_traits::const_max >> - T::value; + static uintmax_t const maxi = boost::integer_traits::const_max + >> T::value; - BOOST_CHECK_EQUAL( typename uint_value_t::least(max_u), max_u ); - BOOST_CHECK_EQUAL( typename uint_value_t<(max_u >> 1)>::least(max_u >> 1), - max_u >> 1 ); - BOOST_CHECK_EQUAL( typename uint_value_t::fast(max_u), max_u ); - BOOST_CHECK_EQUAL( typename uint_value_t<(max_u >> 1)>::fast(max_u >> 1), - max_u >> 1 ); + BOOST_CHECK_EQUAL( static_cast::least>(maxi), maxi ); + BOOST_CHECK_EQUAL( static_cast::fast>(maxi), maxi ); } // Check if large value can fit its minimum required size, by value, signed @@ -793,31 +645,21 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_signed_values_test, T, // 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::const_max >> shift, - min_s = integer_traits::const_min >> shift; + typedef boost::integer_traits intmax_traits; - BOOST_CHECK_EQUAL( typename int_max_value_t::least(max_s), max_s ); - BOOST_CHECK_EQUAL( typename int_max_value_t<(max_s >> 1)>::least(max_s >> - 1), max_s >> 1 ); - BOOST_CHECK_EQUAL( typename int_max_value_t::fast(max_s), max_s ); - BOOST_CHECK_EQUAL( typename int_max_value_t<(max_s >> 1)>::fast(max_s >> 1), - max_s >> 1 ); + static intmax_t const maxi = intmax_traits::const_max >> T::value, + mini = intmax_traits::const_min >> T::value; - BOOST_CHECK_EQUAL( typename int_min_value_t::least(min_s), min_s ); - BOOST_CHECK_EQUAL( typename int_min_value_t<(min_s >> 1)>::least(min_s >> - 1), min_s >> 1 ); - BOOST_CHECK_EQUAL( typename int_min_value_t::fast(min_s), min_s ); - BOOST_CHECK_EQUAL( typename int_min_value_t<(min_s >> 1)>::fast(min_s >> 1), - min_s >> 1 ); + BOOST_CHECK_EQUAL( static_cast::least>(maxi), maxi ); + BOOST_CHECK_EQUAL( static_cast::fast>(maxi), maxi ); + + BOOST_CHECK_EQUAL( static_cast::least>(mini), mini ); + BOOST_CHECK_EQUAL( static_cast::fast>(mini), mini ); } BOOST_AUTO_TEST_SUITE_END() From 2ae867bcf8c1812ab04ed5b135bdcbba35946bc5 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Sun, 27 Jul 2008 09:00:54 +0000 Subject: [PATCH 19/23] Corrected link to corresponding test files [SVN r47838] --- cstdint.htm | 2 +- integer.htm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cstdint.htm b/cstdint.htm index 9492827..0c2f893 100644 --- a/cstdint.htm +++ b/cstdint.htm @@ -18,7 +18,7 @@ writing portable code that requires certain integer widths. All typedef's are i header <stdint.h>.  The 64-bit types required by the C standard are not required in the boost header, and may not be supplied in all implementations, because long long is not [yet] included in the C++ standard.

-

See cstdint_test.cpp for a test program.

+

See cstdint_test.cpp for a test program.

Exact-width integer types

The typedef int#_t, with # replaced by the width, designates a signed integer type of exactly # bits; int8_t denotes an 8-bit diff --git a/integer.htm b/integer.htm index e563bc1..0130d7a 100644 --- a/integer.htm +++ b/integer.htm @@ -462,7 +462,7 @@ int main()

Demonstration Program

-

The program integer_test.cpp is a +

The program integer_test.cpp is a simplistic demonstration of the results from instantiating various examples of the sized type class templates.

From 188cef05a9986feca195f6926640f9f15314fe06 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Sun, 27 Jul 2008 16:34:38 +0000 Subject: [PATCH 20/23] Changed the Integer-mask test to use the unit-test system [SVN r47841] --- test/Jamfile.v2 | 2 +- test/integer_mask_test.cpp | 139 +++++++++++++------------------------ 2 files changed, 51 insertions(+), 90 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a0b5b19..50fceee 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -11,7 +11,7 @@ test-suite integer [ run integer_traits_test.cpp /boost/test//boost_test_exec_monitor/static ] [ run integer_mask_test.cpp - /boost/test//boost_test_exec_monitor/static ] + /boost/test//boost_unit_test_framework ] [ run static_log2_test.cpp /boost/test//boost_test_exec_monitor/static ] [ run static_min_max_test.cpp diff --git a/test/integer_mask_test.cpp b/test/integer_mask_test.cpp index 6146ddf..4444801 100644 --- a/test/integer_mask_test.cpp +++ b/test/integer_mask_test.cpp @@ -8,104 +8,65 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 27 Jul 2008 Changed tests to use the unit-test system (Daryle Walker) // 23 Sep 2001 Initial version (Daryle Walker) -#define BOOST_INCLUDE_MAIN -#include // for main +#define BOOST_TEST_MODULE "Integer mask tests" +#include // unit testing framework -#include // for boost::exit_success +#include // for boost::uintmax_t #include // for boost::high_bit_mask_t, etc. +#include // for BOOST_MPL_ASSERT_RELATION +#include // for boost::mpl::range_c -#include // for std::cout (std::endl indirectly) +#include // for std::size_t -#define PRIVATE_HIGH_BIT_SLOW_TEST(v) BOOST_CHECK( ::boost::high_bit_mask_t< \ - (v) >::high_bit == (1ul << (v)) ); -#define PRIVATE_HIGH_BIT_FAST_TEST(v) BOOST_CHECK( ::boost::high_bit_mask_t< \ - (v) >::high_bit_fast == (1ul << (v)) ); -#define PRIVATE_HIGH_BIT_TEST(v) do { PRIVATE_HIGH_BIT_SLOW_TEST(v); \ - PRIVATE_HIGH_BIT_FAST_TEST(v); } while (false) - -#define PRIVATE_LOW_BITS_SLOW_TEST(v) BOOST_CHECK( ::boost::low_bits_mask_t< \ - (v) >::sig_bits == ((1ul << (v)) - 1) ); -#define PRIVATE_LOW_BITS_FAST_TEST(v) BOOST_CHECK( ::boost::low_bits_mask_t< \ - (v) >::sig_bits_fast == ((1ul << (v)) - 1) ); -#define PRIVATE_LOW_BITS_TEST(v) do { PRIVATE_LOW_BITS_SLOW_TEST(v); \ - PRIVATE_LOW_BITS_FAST_TEST(v); } while (false) - - -int test_main( int, char*[] ) +// Custom types/templates, helper functions, and objects +namespace { - using std::cout; - using std::endl; - cout << "Doing high_bit_mask_t tests." << endl; - PRIVATE_HIGH_BIT_TEST( 31 ); - PRIVATE_HIGH_BIT_TEST( 30 ); - PRIVATE_HIGH_BIT_TEST( 29 ); - PRIVATE_HIGH_BIT_TEST( 28 ); - PRIVATE_HIGH_BIT_TEST( 27 ); - PRIVATE_HIGH_BIT_TEST( 26 ); - PRIVATE_HIGH_BIT_TEST( 25 ); - PRIVATE_HIGH_BIT_TEST( 24 ); - PRIVATE_HIGH_BIT_TEST( 23 ); - PRIVATE_HIGH_BIT_TEST( 22 ); - PRIVATE_HIGH_BIT_TEST( 21 ); - PRIVATE_HIGH_BIT_TEST( 20 ); - PRIVATE_HIGH_BIT_TEST( 19 ); - PRIVATE_HIGH_BIT_TEST( 18 ); - PRIVATE_HIGH_BIT_TEST( 17 ); - PRIVATE_HIGH_BIT_TEST( 16 ); - PRIVATE_HIGH_BIT_TEST( 15 ); - PRIVATE_HIGH_BIT_TEST( 14 ); - PRIVATE_HIGH_BIT_TEST( 13 ); - PRIVATE_HIGH_BIT_TEST( 12 ); - PRIVATE_HIGH_BIT_TEST( 11 ); - PRIVATE_HIGH_BIT_TEST( 10 ); - PRIVATE_HIGH_BIT_TEST( 9 ); - PRIVATE_HIGH_BIT_TEST( 8 ); - PRIVATE_HIGH_BIT_TEST( 7 ); - PRIVATE_HIGH_BIT_TEST( 6 ); - PRIVATE_HIGH_BIT_TEST( 5 ); - PRIVATE_HIGH_BIT_TEST( 4 ); - PRIVATE_HIGH_BIT_TEST( 3 ); - PRIVATE_HIGH_BIT_TEST( 2 ); - PRIVATE_HIGH_BIT_TEST( 1 ); - PRIVATE_HIGH_BIT_TEST( 0 ); +// A big one +boost::uintmax_t const one = 1u; - cout << "Doing low_bits_mask_t tests." << endl; - PRIVATE_LOW_BITS_TEST( 32 ); // Undefined behavior? Whoops! - PRIVATE_LOW_BITS_TEST( 31 ); - PRIVATE_LOW_BITS_TEST( 30 ); - PRIVATE_LOW_BITS_TEST( 29 ); - PRIVATE_LOW_BITS_TEST( 28 ); - PRIVATE_LOW_BITS_TEST( 27 ); - PRIVATE_LOW_BITS_TEST( 26 ); - PRIVATE_LOW_BITS_TEST( 25 ); - PRIVATE_LOW_BITS_TEST( 24 ); - PRIVATE_LOW_BITS_TEST( 23 ); - PRIVATE_LOW_BITS_TEST( 22 ); - PRIVATE_LOW_BITS_TEST( 21 ); - PRIVATE_LOW_BITS_TEST( 20 ); - PRIVATE_LOW_BITS_TEST( 19 ); - PRIVATE_LOW_BITS_TEST( 18 ); - PRIVATE_LOW_BITS_TEST( 17 ); - PRIVATE_LOW_BITS_TEST( 16 ); - PRIVATE_LOW_BITS_TEST( 15 ); - PRIVATE_LOW_BITS_TEST( 14 ); - PRIVATE_LOW_BITS_TEST( 13 ); - PRIVATE_LOW_BITS_TEST( 12 ); - PRIVATE_LOW_BITS_TEST( 11 ); - PRIVATE_LOW_BITS_TEST( 10 ); - PRIVATE_LOW_BITS_TEST( 9 ); - PRIVATE_LOW_BITS_TEST( 8 ); - PRIVATE_LOW_BITS_TEST( 7 ); - PRIVATE_LOW_BITS_TEST( 6 ); - PRIVATE_LOW_BITS_TEST( 5 ); - PRIVATE_LOW_BITS_TEST( 4 ); - PRIVATE_LOW_BITS_TEST( 3 ); - PRIVATE_LOW_BITS_TEST( 2 ); - PRIVATE_LOW_BITS_TEST( 1 ); +// List the ranges of template parameters tests (ranges are half-open) +typedef boost::mpl::range_c high_bit_offsets; +typedef boost::mpl::range_c low_bit_lengths; - return boost::exit_success; +} // unnamed namespace + + +// Check the various integer-valued bit-masks +BOOST_AUTO_TEST_SUITE( integer_mask_tests ) + +// Check the bit-masks of one offset bit +BOOST_AUTO_TEST_CASE_TEMPLATE( high_bit_mask_test, T, high_bit_offsets ) +{ + BOOST_MPL_ASSERT_RELATION( boost::high_bit_mask_t::high_bit, ==, + (one << T::value) ); + BOOST_MPL_ASSERT_RELATION( boost::high_bit_mask_t::high_bit_fast, + ==, (one << T::value) ); } + +// Check the bit-masks of a block of low-valued bits +BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, low_bit_lengths ) +{ + // One can express (2^x - 1) in two ways + // 1. (1 << x) - 1 + // 2. (1 << (x-1)) | ((1 << (x-1)) - 1) + // Since unsigneds have modulo arithmetic, [1] gives the right answer even + // when x is the number of bits in the register. However, that last case + // gives warnings about the sole bit flowing past the register. Applying + // distributive property backwards gives [2], which works without overflow. + BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t::sig_bits, ==, + (one << ( T::value - 1u )) | (( one << (T::value - 1u) ) - 1u) ); + BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t::sig_bits_fast, + ==, (one << ( T::value - 1u )) | (( one << (T::value - 1u) ) - 1u) ); +} + +BOOST_AUTO_TEST_SUITE_END() + +// Verification of bugs and their fixes +BOOST_AUTO_TEST_SUITE( bug_fix_tests ) + +BOOST_AUTO_TEST_SUITE_END() From f041dc0f0a3f63cc710e8ed78f64e9076b0e4a80 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Sun, 27 Jul 2008 17:08:51 +0000 Subject: [PATCH 21/23] Added extended-integer support [SVN r47842] --- include/boost/integer/integer_mask.hpp | 6 ++++++ include/boost/integer_fwd.hpp | 6 ++++++ test/integer_mask_test.cpp | 10 +++++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/boost/integer/integer_mask.hpp b/include/boost/integer/integer_mask.hpp index 0a092d3..65ee5d5 100644 --- a/include/boost/integer/integer_mask.hpp +++ b/include/boost/integer/integer_mask.hpp @@ -15,6 +15,8 @@ #include // for BOOST_STATIC_CONSTANT #include // for boost::uint_t +#include // for BOOST_HAS_XINT, etc. + #include // for UCHAR_MAX, etc. #include // for std::size_t @@ -84,6 +86,10 @@ BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned int ); BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned long ); #endif +#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX) +BOOST_LOW_BITS_MASK_SPECIALIZE( ::boost::detail::uxint_t ); +#endif + #undef BOOST_LOW_BITS_MASK_SPECIALIZE diff --git a/include/boost/integer_fwd.hpp b/include/boost/integer_fwd.hpp index 446ad66..e15385a 100644 --- a/include/boost/integer_fwd.hpp +++ b/include/boost/integer_fwd.hpp @@ -155,6 +155,12 @@ template < > struct low_bits_mask_t< ::std::numeric_limits::digits >; #endif +#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX) +template < > + struct low_bits_mask_t< ::std::numeric_limits< ::boost::detail::uxint_t + >::digits >; +#endif + // From ------------------------------------// diff --git a/test/integer_mask_test.cpp b/test/integer_mask_test.cpp index 4444801..99a22b0 100644 --- a/test/integer_mask_test.cpp +++ b/test/integer_mask_test.cpp @@ -8,7 +8,8 @@ // See http://www.boost.org for most recent version including documentation. // Revision History -// 27 Jul 2008 Changed tests to use the unit-test system (Daryle Walker) +// 27 Jul 2008 Changed tests to use the unit-test system; added +// extended-integer support. (Daryle Walker) // 23 Sep 2001 Initial version (Daryle Walker) #define BOOST_TEST_MODULE "Integer mask tests" @@ -16,6 +17,7 @@ #include // for boost::uintmax_t #include // for boost::high_bit_mask_t, etc. +#include // for std::numeric_limits #include // for BOOST_MPL_ASSERT_RELATION #include // for boost::mpl::range_c @@ -30,8 +32,10 @@ namespace boost::uintmax_t const one = 1u; // List the ranges of template parameters tests (ranges are half-open) -typedef boost::mpl::range_c high_bit_offsets; -typedef boost::mpl::range_c low_bit_lengths; +int const max_offset = std::numeric_limits::digits; + +typedef boost::mpl::range_c high_bit_offsets; +typedef boost::mpl::range_c low_bit_lengths; } // unnamed namespace From 2fd0675a21a35ee0d1f6aa7c2f7fa6873aa45a5c Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Mon, 28 Jul 2008 14:41:00 +0000 Subject: [PATCH 22/23] Hopefully made compile-time constants suitable for more compilers [SVN r47852] --- test/integer_test.cpp | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/test/integer_test.cpp b/test/integer_test.cpp index 4b34d40..8f5c834 100644 --- a/test/integer_test.cpp +++ b/test/integer_test.cpp @@ -44,6 +44,7 @@ #include // for boost::mpl::push_back #include // for boost::mpl::push_front #include // for boost::mpl::range_c +#include // for boost::mpl::shift_right #include // for boost::mpl::sort #include // for boost::mpl::transform #include // for boost::mpl::transform_view @@ -290,6 +291,19 @@ print_out_template( T const &, ValueT setting, char const *template_pre_name, #error "These tests cannot work without Substitution-Failure-Is-Not-An-Error" #endif +// Get the extreme values for each integral type +template < typename T > +struct minimum_of + : boost::mpl::integral_c< T, boost::integer_traits::const_min > +{ +}; + +template < typename T > +struct maximum_of + : boost::mpl::integral_c< T, boost::integer_traits::const_max > +{ +}; + } // unnamed namespace @@ -617,13 +631,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_unsigned_values_test, T, // 64) elements, so we have to take selected values. using boost::uintmax_t; - static uintmax_t const maxi = boost::integer_traits::const_max - >> T::value; + typedef boost::mpl::shift_right, T> maxi_type; + + uintmax_t const maxi = maxi_type::value; BOOST_CHECK_EQUAL( static_cast::least>(maxi), maxi ); + boost::uint_value_t::least>(maxi), maxi ); BOOST_CHECK_EQUAL( static_cast::fast>(maxi), maxi ); + boost::uint_value_t::fast>(maxi), maxi ); } // Check if large value can fit its minimum required size, by value, signed @@ -646,20 +661,20 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_signed_values_test, T, // 64) elements, so we have to take selected values. using boost::intmax_t; - typedef boost::integer_traits intmax_traits; + typedef boost::mpl::shift_right, T> mini_type; + typedef boost::mpl::shift_right, T> maxi_type; - static intmax_t const maxi = intmax_traits::const_max >> T::value, - mini = intmax_traits::const_min >> T::value; + intmax_t const maxi = maxi_type::value, mini = mini_type::value; BOOST_CHECK_EQUAL( static_cast::least>(maxi), maxi ); + boost::int_max_value_t::least>(maxi), maxi ); BOOST_CHECK_EQUAL( static_cast::fast>(maxi), maxi ); + boost::int_max_value_t::fast>(maxi), maxi ); BOOST_CHECK_EQUAL( static_cast::least>(mini), mini ); + boost::int_min_value_t::least>(mini), mini ); BOOST_CHECK_EQUAL( static_cast::fast>(mini), mini ); + boost::int_min_value_t::fast>(mini), mini ); } BOOST_AUTO_TEST_SUITE_END() From 2d259a4f3e44879d2dccfbc0eef006b532a5bcaf Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Tue, 29 Jul 2008 19:33:20 +0000 Subject: [PATCH 23/23] Added MPL-compatible variants of the integer-mask class templates (and finally make the lowest-bit-group metafunctions work for zero-length bit-groups) [SVN r47869] --- doc/integer_mask.html | 211 ++++++++++++++++++++++--- include/boost/integer/integer_mask.hpp | 207 ++++++++++++++++++------ include/boost/integer_fwd.hpp | 38 ++--- test/integer_mask_test.cpp | 119 ++++++++++++-- 4 files changed, 461 insertions(+), 114 deletions(-) diff --git a/doc/integer_mask.html b/doc/integer_mask.html index 5bc7301..6dba489 100644 --- a/doc/integer_mask.html +++ b/doc/integer_mask.html @@ -8,7 +8,11 @@

boost.png (6897 bytes)Integer Bit Mask Templates

-

The class templates in <boost/integer/integer_mask.hpp> provide bit masks for a certain bit position or a contiguous-bit pack of a certain size. The types of the masking constants come from the integer type selection templates header.

+

The class templates in <boost/integer/integer_mask.hpp> +provide bit masks for a certain bit position or a contiguous-bit pack of a +certain size. The types of the masking constants come from the integer type selection templates header.

Contents

@@ -17,6 +21,7 @@ align="middle" width="277" height="86">Integer Bit Mask Templates
  • Synopsis
  • Single Bit-Mask Class Template
  • Group Bit-Mask Class Template
  • +
  • MPL-Compatible Variants
  • Example
  • Demonstration Program
  • Rationale
  • @@ -26,39 +31,68 @@ align="middle" width="277" height="86">Integer Bit Mask Templates

    Synopsis

    -#include <cstddef>  // for std::size_t
    +#include <boost/integer_fwd.hpp>  // forwarding header
    +#include <boost/integer.hpp>      // for boost::int_fast_t
    +#include <cstddef>                // for std::size_t
     
     namespace boost
     {
     
    -template < std::size_t Bit >
    -struct high_bit_mask_t
    +// MPL-compatible
    +template < int Offset >
    +struct integer_hi_mask
     {
    -    typedef implementation_supplied  least;
    -    typedef implementation_supplied   fast;
    +    static  bool const  is_specialized = implementation_supplied;
    +    static  int const   bit_offset = Offset;
     
    -    static const least  high_bit = implementation_defined;
    -    static const fast   high_bit_fast = implementation_defined;
    +    typedef implementation_supplied  type;
    +    typedef implementation_supplied  value_type;
    +    static  value_type const  value = implementation_supplied;
    +    // There are other (optional) operations....
    +};
    +
    +template < int Length >
    +struct integer_lo_mask
    +{
    +    static  bool const  is_specialized = implementation_supplied;
    +    static  int const   bit_count = Length;
    +
    +    typedef implementation_supplied  type;
    +    typedef implementation_supplied  value_type;
    +    static  value_type const  value = implementation_supplied;
    +    // There are other (optional) operations....
    +};
    +
    +// single
    +template < std::size_t Bit >
    +class high_bit_mask_t
    +{
    +public:
    +    typedef typename integer_hi_mask<Bit>::value_type  least;
    +    typedef int_fast_t<least>::fast                     fast;
    +
    +    static const least  high_bit = integer_hi_mask<Bit>::value;
    +    static const fast   high_bit_fast = high_bit;
     
         static const std::size_t  bit_position = Bit;
     
     };
     
    +// group
     template < std::size_t Bits >
    -struct low_bits_mask_t
    +class low_bits_mask_t
     {
    -    typedef implementation_supplied  least;
    -    typedef implementation_supplied   fast;
    +public:
    +    typedef typename integer_lo_mask<Bits>::value_type  least;
    +    typedef int_fast_t<least>::fast                      fast;
     
    -    static const least  sig_bits = implementation_defined;
    -    static const fast   sig_bits_fast = implementation_defined;
    +    static const least  sig_bits = integer_lo_mask<Bits>::value;
    +    static const fast   sig_bits_fast = sig_bits;
     
         static const std::size_t  bit_count = Bits;
     
     };
     
    -// Specializations for low_bits_mask_t exist for certain bit counts.
    -
     }  // namespace boost
     
    @@ -149,16 +183,149 @@ describes the members of an instantiation of -

    Implementation Note
    -When Bits is the exact size of a built-in unsigned type, -the implementation has to change to prevent undefined behavior. -Therefore, there are specializations of low_bits_mask_t at -those bit counts.

    +

    MPL-Compatible Variants

    + +

    The single and group bit-mask class templates have several drawbacks:

    + +
      +
    • You must know the valid bit-lengths in advance.
    • +
    • Using an inappropriate parameter value results in a compiler + diagnostic.
    • +
    • The type names used are inconsistent with other transformations in + Boost, like in MPL.
    • +
    • The above two facts make use of the regular bit-mask class templates + incompatible with template meta-programming techniques.
    • +
    + +

    The integer_hi_mask and integer_lo_mask class +templates provide MPL-compatible alternatives. These alternatives have the +form:

    + +
    +template< int Size >
    +struct name
    +{
    +    static  bool const  is_specialized = implementation_supplied;
    +    static  int const   switch_id = Size;
    +
    +    typedef implementation_supplied  type;
    +    typedef implementation_supplied  value_type;
    +    static  value_type const  value = implementation_supplied;
    +    // with other operations...
    +};
    +
    + +

    Only some of the members are always present. The presence of other members +and operations is flagged by the (always-present) is_specialized.

    + + + + + + + + + + + + + + + +
    Permanent Members of the MPL-Compatible Masking Class Template + Types
    Class Template MemberMeaning
    is_specializedFlag indicating when a particular template class instantiation is a + valid meta-function (true) or not (false).
    switch_id (Actual name is template-specific.)The value of the main control parameter, accessible even if the + template class instantiation is aliased.
    + +

    The optional members are based from inheriting from a MPL-style Integral +Constant type, but only if is_specialized is true.

    + + + + + + + + + + + + + + + + + + + +
    Optional Members of the MPL-Compatible Masking Types
    Class Template MemberMeaning
    valueThe actual bit mask.
    value_typeThe type of the bit mask value.
    typeThe Integral Constant implementation type, which should be + boost::mpl:: + integral_c< value_type, value + >.
    + +

    The Integral Constant prototype also adds the following operations:

    + + + + + + + + + + + + + + + + + + + +
    Optional Operations of the MPL-Compatible Masking Types
    Operation (with n as a masking type)Meaning
    boost::mpl::next< n >::typeboost::mpl::next< n::type >::type, i.e. + boost::mpl::integral_c< n::value_type, n::value + 1 + >.
    boost::mpl::prior< n >::typeboost::mpl::prior< n::type >::type, i.e. + boost::mpl::integral_c< n::value_type, n::value - 1 + >.
    n::value_type const c = n();c is set to n::value.
    + +

    The specifics for each masking class template are:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Criteria for the MPL-Compatible Masking Types
    + (Everything besides the parameter ID is in name-space + boost except where indicated.)
    Class TemplateParameter Member IDClassic EquivalentValue TypeValueValid Range
    integer_hi_maskbit_offsethigh_bit_mask_tsized_integral < bit_offset + 1, unsigned >2bit_offset0 <= bit_offset < std::numeric_limits< uintmax_t >::digits
    integer_lo_maskbit_countlow_bits_mask_tsized_integral < bit_count, unsigned >2bit_offset - 10 <= bit_count <= std::numeric_limits< uintmax_t >::digits

    Example

    -#include <boost/integer/integer_mask.hpp>
    +#include <boost/integer/integer_mask.hpp>
     
     //...
     
    @@ -200,7 +367,7 @@ href="http://www.boost.org/people/daryle_walker.html">Daryle Walker.


    -

    Revised September 23, 2001

    +

    Revised July 29, 2008

    © Copyright Daryle Walker 2001. Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file // self include -#include // for BOOST_STATIC_CONSTANT -#include // for boost::uint_t +#include // for BOOST_STATIC_CONSTANT +#include // for boost::uintmax_t +#include // for boost::sized_integral +#include // for std::numeric_limits +#include // for boost::mpl::and_ +#include // for boost::mpl::bitor_, shift_left +#include // for boost::mpl::true_ +#include // for boost::mpl::greater_equal, etc. +#include // for boost::mpl::empty_base +#include // for boost::mpl::if_ +#include // for boost::mpl::int_ +#include // for boost::integral_c +#include // for boost::mpl::next, prior +#include // for boost::enable_if -#include // for BOOST_HAS_XINT, etc. - -#include // for UCHAR_MAX, etc. #include // for std::size_t -#include // for std::numeric_limits - namespace boost { +namespace detail +{ + +// Helper templates --------------------------------------------------------// + +template < int Bits > +struct hi_integer_mask_builder1 +{ + typedef boost::mpl::int_ bit_count_type; + + typedef typename boost::mpl::next::type + mask_length_type; + typedef boost::sized_integral + mask_type; + + typedef boost::mpl::integral_c one_type; + typedef boost::mpl::shift_left result_type; +}; + +template < int Bits > +struct hi_integer_mask_builder2 +{ + typedef boost::mpl::int_ bit_count_type; + + typedef boost::mpl::greater_equal< bit_count_type, boost::mpl::int_<0> > + lo_bound_type; + typedef boost::mpl::less< bit_count_type, + boost::mpl::int_::digits> > + hi_bound_type; + typedef boost::mpl::and_ count_valid_type; +}; + +template < int Bits, class Enable = void > +struct hi_integer_mask_builder3 +{ + BOOST_STATIC_CONSTANT( bool, is_specialized = false ); +}; + +template < int Bits > +struct hi_integer_mask_builder3< Bits, typename boost::enable_if::count_valid_type>::type > + : hi_integer_mask_builder1::result_type +{ + BOOST_STATIC_CONSTANT( bool, is_specialized = true ); +}; + +template < int Bits > +struct lo_integer_mask_builder1 +{ + typedef boost::mpl::int_ bit_count_type; + + typedef typename boost::mpl::prior::type + shift_length_type; + typedef boost::sized_integral + mask_type; + + typedef boost::mpl::integral_c one_type; + typedef boost::mpl::shift_left + high_bit_type; + typedef typename boost::mpl::prior::type low_bits_type; + typedef boost::mpl::bitor_ result_type; +}; + +template < > +struct lo_integer_mask_builder1< 0 > +{ + // Let's not deal with negative interim values.... + typedef boost::mpl::integral_c result_type; +}; + +template < int Bits > +struct lo_integer_mask_builder2 +{ + typedef boost::mpl::int_ bit_count_type; + + typedef boost::mpl::greater_equal< bit_count_type, boost::mpl::int_<0> > + lo_bound_type; + typedef boost::mpl::less_equal< bit_count_type, + boost::mpl::int_::digits> > + hi_bound_type; + typedef boost::mpl::and_ count_valid_type; +}; + +template < > +struct lo_integer_mask_builder2< 0 > +{ + typedef boost::mpl::true_ count_valid_type; +}; + +template < int Bits, class Enable = void > +struct lo_integer_mask_builder3 +{ + BOOST_STATIC_CONSTANT( bool, is_specialized = false ); + // No MPL Integral Constant to inherit from +}; + +template < int Bits > +struct lo_integer_mask_builder3< Bits, typename enable_if::count_valid_type>::type > + : lo_integer_mask_builder1::result_type +{ + BOOST_STATIC_CONSTANT( bool, is_specialized = true ); +}; + +} // namespace detail + + +// MPL-compatible integer mask class templates -----------------------------// + +// Displaced single-bit mask, 1 << Offset, 0 <= Offset < BitLengthOf(uintmax_t) +template < int Offset > +struct integer_hi_mask + : detail::hi_integer_mask_builder3 +{ + BOOST_STATIC_CONSTANT( int, bit_offset = Offset ); +}; + +// Lowest bit-group mask, 2**Length - 1, 0 <= Length <= BitLengthOf(uintmax_t) +template < int Length > +struct integer_lo_mask + : detail::lo_integer_mask_builder3 +{ + BOOST_STATIC_CONSTANT( int, bit_count = Length ); +}; // Specified single-bit mask class declaration -----------------------------// // (Lowest bit starts counting at 0.) template < std::size_t Bit > -struct high_bit_mask_t +class high_bit_mask_t { - typedef typename uint_t<(Bit + 1)>::least least; - typedef typename uint_t<(Bit + 1)>::fast fast; + typedef integer_hi_mask impl_type; - BOOST_STATIC_CONSTANT( least, high_bit = (least( 1u ) << Bit) ); - BOOST_STATIC_CONSTANT( fast, high_bit_fast = (fast( 1u ) << Bit) ); +public: + typedef typename impl_type::value_type least; + typedef typename int_fast_t::fast fast; - BOOST_STATIC_CONSTANT( std::size_t, bit_position = Bit ); + BOOST_STATIC_CONSTANT( least, high_bit = impl_type::value ); + BOOST_STATIC_CONSTANT( fast, high_bit_fast = impl_type::value ); + + BOOST_STATIC_CONSTANT( std::size_t, bit_position = impl_type::bit_offset ); }; // boost::high_bit_mask_t // Specified bit-block mask class declaration ------------------------------// // Makes masks for the lowest N bits -// (Specializations are needed when N fills up a type.) template < std::size_t Bits > -struct low_bits_mask_t +class low_bits_mask_t { - typedef typename uint_t::least least; - typedef typename uint_t::fast fast; + typedef integer_lo_mask impl_type; - BOOST_STATIC_CONSTANT( least, sig_bits = (~( ~(least( 0u )) << Bits )) ); - BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); +public: + typedef typename impl_type::value_type least; + typedef typename int_fast_t::fast fast; - BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits ); + BOOST_STATIC_CONSTANT( least, sig_bits = impl_type::value ); + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = impl_type::value ); + + BOOST_STATIC_CONSTANT( std::size_t, bit_count = impl_type::bit_count ); }; // boost::low_bits_mask_t -#define BOOST_LOW_BITS_MASK_SPECIALIZE( Type ) \ - template < > struct low_bits_mask_t< std::numeric_limits::digits > { \ - typedef std::numeric_limits limits_type; \ - typedef uint_t::least least; \ - typedef uint_t::fast fast; \ - BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); \ - BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); \ - BOOST_STATIC_CONSTANT( std::size_t, bit_count = limits_type::digits ); \ - } - -BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned char ); - -#if USHRT_MAX > UCHAR_MAX -BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned short ); -#endif - -#if UINT_MAX > USHRT_MAX -BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned int ); -#endif - -#if ULONG_MAX > UINT_MAX -BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned long ); -#endif - -#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX) -BOOST_LOW_BITS_MASK_SPECIALIZE( ::boost::detail::uxint_t ); -#endif - -#undef BOOST_LOW_BITS_MASK_SPECIALIZE - - } // namespace boost diff --git a/include/boost/integer_fwd.hpp b/include/boost/integer_fwd.hpp index e15385a..3ece2e3 100644 --- a/include/boost/integer_fwd.hpp +++ b/include/boost/integer_fwd.hpp @@ -9,12 +9,10 @@ #ifndef BOOST_INTEGER_FWD_HPP #define BOOST_INTEGER_FWD_HPP -#include // for UCHAR_MAX, etc. #include // for std::size_t -#include // for BOOST_NO_INTRINSIC_WCHAR_T +#include // for BOOST_NO_INTRINSIC_WCHAR_T, etc. #include // for boost::uintmax_t, intmax_t -#include // for std::numeric_limits #include // for BOOST_HAS_XINT, etc. @@ -131,35 +129,17 @@ template< uintmax_t Value > // From -----------------------------------// +template < int Offset > + struct integer_hi_mask; + +template < int Length > + struct integer_lo_mask; + template < std::size_t Bit > - struct high_bit_mask_t; + class high_bit_mask_t; template < std::size_t Bits > - struct low_bits_mask_t; - -template < > - struct low_bits_mask_t< ::std::numeric_limits::digits >; - -#if USHRT_MAX > UCHAR_MAX -template < > - struct low_bits_mask_t< ::std::numeric_limits::digits >; -#endif - -#if UINT_MAX > USHRT_MAX -template < > - struct low_bits_mask_t< ::std::numeric_limits::digits >; -#endif - -#if ULONG_MAX > UINT_MAX -template < > - struct low_bits_mask_t< ::std::numeric_limits::digits >; -#endif - -#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX) -template < > - struct low_bits_mask_t< ::std::numeric_limits< ::boost::detail::uxint_t - >::digits >; -#endif + class low_bits_mask_t; // From ------------------------------------// diff --git a/test/integer_mask_test.cpp b/test/integer_mask_test.cpp index 99a22b0..65b6fc2 100644 --- a/test/integer_mask_test.cpp +++ b/test/integer_mask_test.cpp @@ -8,6 +8,8 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 29 Jul 2008 Added MPL-compatible variants of the integer-mask templates. +// (Daryle Walker) // 27 Jul 2008 Changed tests to use the unit-test system; added // extended-integer support. (Daryle Walker) // 23 Sep 2001 Initial version (Daryle Walker) @@ -18,24 +20,72 @@ #include // for boost::uintmax_t #include // for boost::high_bit_mask_t, etc. #include // for std::numeric_limits -#include // for BOOST_MPL_ASSERT_RELATION +#include // for BOOST_MPL_ASSERT_RELATION,etc. +#include // for boost::mpl::bool_ +#include // for boost::mpl::bitor_, shift_left +#include // for boost::mpl::equal_to +#include // for boost::mpl::int_ +#include // for boost::mpl::integral_c +#include // for boost::mpl::prior #include // for boost::mpl::range_c #include // for std::size_t +#include // for std::hex +#include // for std::cout +#include // for std::endl + + +// Control if events will be printed conventionally, or just logged. +#ifndef CONTROL_SHOW_TYPES +#define CONTROL_SHOW_TYPES 0 +#endif + +// Logging +#if CONTROL_SHOW_TYPES +#define PRIVATE_SHOW_MESSAGE( m ) std::cout << m << std::endl +#else +#define PRIVATE_SHOW_MESSAGE( m ) BOOST_TEST_MESSAGE( m ) +#endif // Custom types/templates, helper functions, and objects namespace { -// A big one -boost::uintmax_t const one = 1u; - // List the ranges of template parameters tests (ranges are half-open) int const max_offset = std::numeric_limits::digits; -typedef boost::mpl::range_c high_bit_offsets; -typedef boost::mpl::range_c low_bit_lengths; +typedef boost::mpl::range_c high_bit_offsets; +typedef boost::mpl::range_c low_bit_lengths; +typedef boost::mpl::range_c special_low_bit_lengths; + +// List a range with out-of-service values +typedef boost::mpl::range_c wild_bit_lengths; + +// Use SFINAE to check if a particular parameter is supported +template < typename ValueT, template class Tmpl, ValueT Value > +bool +print_out_template( Tmpl const &, ValueT setting, char const + *template_name, typename Tmpl::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 " << template_name << "<" << setting << + "> specialization with type '" << typeid(typename + Tmpl::value_type).name() << "' and value '" << std::hex << + Tmpl::value << "'." ); + return true; +} + +template < typename ValueT, typename T > +bool +print_out_template( T const &, ValueT setting, char const *template_name ) +{ + PRIVATE_SHOW_MESSAGE( "There is no " << template_name << "<" << setting << + "> specialization." ); + return false; +} } // unnamed namespace @@ -46,14 +96,18 @@ BOOST_AUTO_TEST_SUITE( integer_mask_tests ) // Check the bit-masks of one offset bit BOOST_AUTO_TEST_CASE_TEMPLATE( high_bit_mask_test, T, high_bit_offsets ) { + typedef boost::mpl::integral_c::least, 1u> one_type; + typedef boost::mpl::shift_left result_type; + BOOST_MPL_ASSERT_RELATION( boost::high_bit_mask_t::high_bit, ==, - (one << T::value) ); + result_type::value ); BOOST_MPL_ASSERT_RELATION( boost::high_bit_mask_t::high_bit_fast, - ==, (one << T::value) ); + ==, result_type::value ); } -// Check the bit-masks of a block of low-valued bits -BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, low_bit_lengths ) +// Check the bit-masks of a block of low-valued bits, non-zero block-lengths +BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, special_low_bit_lengths ) { // One can express (2^x - 1) in two ways // 1. (1 << x) - 1 @@ -62,10 +116,51 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, low_bit_lengths ) // when x is the number of bits in the register. However, that last case // gives warnings about the sole bit flowing past the register. Applying // distributive property backwards gives [2], which works without overflow. + typedef typename boost::mpl::prior::type shift_type; + typedef boost::mpl::integral_c::least, 1u> one_type; + typedef boost::mpl::shift_left high_bit_type; + typedef typename boost::mpl::prior::type low_bits_type; + typedef boost::mpl::bitor_ result_type; + BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t::sig_bits, ==, - (one << ( T::value - 1u )) | (( one << (T::value - 1u) ) - 1u) ); + result_type::value ); BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t::sig_bits_fast, - ==, (one << ( T::value - 1u )) | (( one << (T::value - 1u) ) - 1u) ); + ==, result_type::value ); +} + +// Check the bit-masks of a block of low-valued bits, zero block-length +BOOST_AUTO_TEST_CASE( special_low_bits_mask_test ) +{ + // Just like "low_bits_mask_test" above, except that the shifts are negative + // when the bit-count is zero. That causes a lot of warnings and errors, so + // special-case that bit-count. + BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t<0u>::sig_bits, ==, 0 ); + BOOST_MPL_ASSERT_RELATION(boost::low_bits_mask_t<0u>::sig_bits_fast, ==, 0); +} + +// Check the specialization type status of given bit-offsets/lengths +BOOST_AUTO_TEST_CASE_TEMPLATE( confirm_bounds_test, T, wild_bit_lengths ) +{ + typedef boost::integer_hi_mask hi_type; + typedef boost::mpl::int_ hi_offset_type; + typedef boost::mpl::bool_ special_hi_type; + + BOOST_MPL_ASSERT( (boost::mpl::equal_to< hi_offset_type, T >) ); + BOOST_MPL_ASSERT( (boost::mpl::equal_to< special_hi_type, + boost::mpl::bool_<(T::value >= 0) && (T::value < max_offset)> >) ); + BOOST_CHECK_EQUAL( print_out_template(hi_type(), hi_offset_type::value, + "integer_hi_mask"), special_hi_type::value ); + + typedef boost::integer_lo_mask lo_type; + typedef boost::mpl::int_ lo_length_type; + typedef boost::mpl::bool_ special_lo_type; + + BOOST_MPL_ASSERT( (boost::mpl::equal_to< lo_length_type, T >) ); + BOOST_MPL_ASSERT( (boost::mpl::equal_to< special_lo_type, + boost::mpl::bool_<(T::value >= 0) && (T::value <= max_offset)> >) ); + BOOST_CHECK_EQUAL( print_out_template(lo_type(), lo_length_type::value, + "integer_lo_mask"), special_lo_type::value ); } BOOST_AUTO_TEST_SUITE_END()