diff --git a/cstdint.htm b/cstdint.htm index 43b828f..0c2f893 100644 --- a/cstdint.htm +++ b/cstdint.htm @@ -2,7 +2,7 @@ - + Header boost/cstdint.hpp @@ -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 @@ -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/doc/integer_mask.html b/doc/integer_mask.html index 0328bbc..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:

    + + + +

    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>
     
     //...
     
    @@ -196,11 +363,11 @@ 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.


    -

    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 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/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 dc57dff..531b405 100644 --- a/include/boost/integer.hpp +++ b/include/boost/integer.hpp @@ -7,6 +7,12 @@ // See http://www.boost.org/libs/integer for documentation. // Revision History +// 16 Jul 08 Added MPL-compatible variants of the minimum-size and value- +// based integer templates. (Daryle Walker) +// 15 Jul 08 Added exact-integer templates; added MPL-compatible variant of +// processor-optimized integer template. (Daryle Walker) +// 14 Jul 08 Added extended-integer support. (Daryle Walker) +// 13 Jul 08 Redid implmentation. (Daryle Walker) // 22 Sep 01 Added value-based integer templates. (Daryle Walker) // 01 Apr 01 Modified to use new header. (John Maddock) // 30 Jul 00 Add typename syntax fix (Jens Maurer) @@ -17,108 +23,357 @@ #include // self include -#include // for boost::integer_traits -#include // for std::numeric_limits +#include // for BOOST_STATIC_CONSTANT, etc. +#include // for boost::uintmax_t, intmax_t +#include // for boost::integer_traits +#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 { - // Helper templates ------------------------------------------------------// + // integer template mapping a type to its processor-optimized analog -----// + + // Some types can be handled better by the processor than others. This + // template metafunction should map various built-in integral types to + // the processor's perferred type for the given type's value range + template < typename BaseInt > + struct fast_integral + { + typedef BaseInt type; + }; + + // Platform-specific specializations should go here. // 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 + struct int_fast_t { typedef typename fast_integral::type fast; }; - // 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) __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 +#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> + { typedef unsigned long least; }; + template<> struct int_least_helper<3, signed> { typedef int least; }; + template<> struct int_least_helper<3, unsigned> + { 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 BOOST_HAS_XINT + lowest_integral_rank = 1, +#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 ); +#if BOOST_HAS_XINT + BOOST_STATIC_CONSTANT( int, extended_ = (mantissa <= std::numeric_limits< + xint_t >::digits) ); +#else + 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) + + (mantissa <= std::numeric_limits< signed char >::digits)) ); + }; + + template < int Bits > + struct uint_rank_helper + { +#if BOOST_HAS_XINT + BOOST_STATIC_CONSTANT( int, extended_ = (Bits <= std::numeric_limits< + uxint_t >::digits) ); +#else + 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) + + (Bits <= std::numeric_limits< unsigned char >::digits)) ); + }; + + template < int BitsIncludingSign > + struct int_exact_rank_helper { BOOST_STATIC_CONSTANT( int, rank = 0 ); }; + template < int Bits > + struct uint_exact_rank_helper { BOOST_STATIC_CONSTANT( int, rank = 0 ); }; + +#define BOOST_PRIVATE_INT_EXACT_BUILDER(Type, Rank) \ + template < > \ + struct int_exact_rank_helper::digits + 1> \ + { BOOST_STATIC_CONSTANT( int, rank = Rank ); } +#define BOOST_PRIVATE_UINT_EXACT_BUILDER(Type, Rank) \ + template < > \ + struct uint_exact_rank_helper::digits> \ + { BOOST_STATIC_CONSTANT( int, rank = Rank ); } + +#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 ); + BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned long, 2 ); +#endif +#if UINT_MAX > USHRT_MAX + BOOST_PRIVATE_INT_EXACT_BUILDER( int, 3 ); + BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned, 3 ); +#endif +#if USHRT_MAX > UCHAR_MAX + BOOST_PRIVATE_INT_EXACT_BUILDER( short, 4 ); + BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned short, 4 ); +#endif + BOOST_PRIVATE_INT_EXACT_BUILDER( signed char, 5 ); + BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned char, 5 ); + +#undef BOOST_PRIVATE_INT_EXACT_BUILDER +#undef BOOST_PRIVATE_UINT_EXACT_BUILDER + + // map an extreme value to a category + template < intmax_t MaxValue > + struct int_max_rank_helper + { +#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 + BOOST_STATIC_CONSTANT( int, rank = (MaxValue > 0) * (extended_ + + (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 + { +#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 + BOOST_STATIC_CONSTANT( int, rank = (MinValue < 0) * (extended_ + + (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 + { +#if BOOST_HAS_XINT + BOOST_STATIC_CONSTANT( int, extended_ = (Value <= boost::integer_traits< + uxint_t >::const_max) ); +#else + BOOST_STATIC_CONSTANT( int, extended_ = 1 ); +#endif + BOOST_STATIC_CONSTANT( int, rank = extended_ + + (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 + template < int Rank, typename Signedness, class Enable = void > + struct integral_rank_to_type + { + BOOST_STATIC_CONSTANT( bool, is_specialized = false ); + // No "signed" nor "type" here + }; + + template < int Rank > + struct integral_rank_to_type< Rank, signed, typename + enable_if_c<(lowest_integral_rank <= Rank) && (Rank <= + highest_integral_rank)>::type > + { + BOOST_STATIC_CONSTANT( bool, is_specialized = true ); + BOOST_STATIC_CONSTANT( bool, is_signed = true ); + typedef typename int_least_helper< Rank, signed >::least type; + }; + + template < int Rank > + struct integral_rank_to_type< Rank, unsigned, typename + enable_if_c<(lowest_integral_rank <= Rank) && (Rank <= + highest_integral_rank)>::type > + { + BOOST_STATIC_CONSTANT( bool, is_specialized = true ); + BOOST_STATIC_CONSTANT( bool, is_signed = false ); + typedef typename int_least_helper< Rank, unsigned >::least type; + }; + +} // namespace detail + + // MPL-compatible integer-mapping class templates ------------------------// + + // minimum number of bits + template < int Bits, typename Signedness > + struct sized_integral + { + BOOST_STATIC_CONSTANT( bool, is_specialized = false ); + BOOST_STATIC_CONSTANT( int, bit_count = Bits ); + }; + + template < int BitsIncludingSign > + struct sized_integral< BitsIncludingSign, signed > + : detail::integral_rank_to_type< + detail::int_rank_helper::rank, signed > + { + BOOST_STATIC_CONSTANT( int, bit_count = BitsIncludingSign ); + }; + + template < int Bits > + struct sized_integral< Bits, unsigned > + : detail::integral_rank_to_type< + detail::uint_rank_helper::rank, unsigned > + { + BOOST_STATIC_CONSTANT( int, bit_count = Bits ); + }; + + // exact number of bits + template < int Bits, typename Signedness > + struct exact_integral + { + BOOST_STATIC_CONSTANT( bool, is_specialized = false ); + BOOST_STATIC_CONSTANT( int, bit_count = Bits ); + }; + + template < int BitsIncludingSign > + struct exact_integral< BitsIncludingSign, signed > + : detail::integral_rank_to_type< + detail::int_exact_rank_helper::rank, signed > + { + BOOST_STATIC_CONSTANT( int, bit_count = BitsIncludingSign ); + }; + + template < int Bits > + struct exact_integral< Bits, unsigned > + : detail::integral_rank_to_type< + detail::uint_exact_rank_helper::rank, unsigned > + { + BOOST_STATIC_CONSTANT( int, bit_count = Bits ); + }; + + // maximum supported (positive) value, signed + template < intmax_t MaxValue > + struct maximum_signed_integral + : detail::integral_rank_to_type< + detail::int_max_rank_helper::rank, signed > + { + BOOST_STATIC_CONSTANT( intmax_t, bound = MaxValue ); + }; + + // minimum supported (negative) value + template < intmax_t MinValue > + struct minimum_signed_integral + : detail::integral_rank_to_type< + detail::int_min_rank_helper::rank, signed > + { + BOOST_STATIC_CONSTANT( intmax_t, bound = MinValue ); + }; + + // maximum supported (nonnegative) value, unsigned + template < uintmax_t Value > + struct maximum_unsigned_integral + : detail::integral_rank_to_type< + detail::uint_max_rank_helper::rank, unsigned > + { + BOOST_STATIC_CONSTANT( uintmax_t, bound = Value ); + }; // integer templates specifying number of bits ---------------------------// // signed - template< int Bits > // bits (including sign) required + template< int Bits > // minimum bits (including sign) required struct int_t { - typedef typename 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; - typedef typename int_fast_t::fast fast; + typedef typename sized_integral::type least; + typedef typename int_fast_t::fast fast; + }; + + template< int Bits > // exact bits (including sign) desired + struct int_exact_t + { + typedef typename exact_integral::type exact; }; // unsigned - template< int Bits > // bits required + template< int Bits > // minimum bits required struct uint_t { - typedef typename 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; - typedef typename int_fast_t::fast fast; + typedef typename sized_integral::type least; + typedef typename int_fast_t::fast fast; // int_fast_t<> works correctly for unsigned too, in spite of the name. }; + template< int Bits > // exact bits desired + struct uint_exact_t + { + typedef typename exact_integral::type exact; + }; + // 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 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; - typedef typename int_fast_t::fast fast; + typedef typename maximum_signed_integral::type least; + 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 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; - typedef typename int_fast_t::fast fast; + typedef typename minimum_signed_integral::type least; + typedef typename int_fast_t::fast fast; }; // 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 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; - typedef typename int_fast_t::fast fast; + typedef typename maximum_unsigned_integral::type least; + typedef typename int_fast_t::fast fast; }; diff --git a/include/boost/integer/integer_mask.hpp b/include/boost/integer/integer_mask.hpp index 0a092d3..a334d64 100644 --- a/include/boost/integer/integer_mask.hpp +++ b/include/boost/integer/integer_mask.hpp @@ -12,81 +12,192 @@ #include // 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 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 - -#undef BOOST_LOW_BITS_MASK_SPECIALIZE - - } // namespace boost diff --git a/include/boost/integer_fwd.hpp b/include/boost/integer_fwd.hpp index 33cfc99..3ece2e3 100644 --- a/include/boost/integer_fwd.hpp +++ b/include/boost/integer_fwd.hpp @@ -9,11 +9,12 @@ #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 std::numeric_limits +#include // for BOOST_NO_INTRINSIC_WCHAR_T, etc. +#include // for boost::uintmax_t, intmax_t + +#include // for BOOST_HAS_XINT, etc. 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 -----------------------------------------// @@ -65,61 +73,73 @@ 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 // From ------------------------------------------------// +template < typename BaseInt > + struct fast_integral; + template < typename LeastInt > struct int_fast_t; +template < int Bits, typename Signedness > + struct sized_integral; + +template < int Bits, typename Signedness > + struct exact_integral; + +template < intmax_t MaxValue > + struct maximum_signed_integral; + +template < intmax_t MinValue > + struct minimum_signed_integral; + +template < uintmax_t Value > + struct maximum_unsigned_integral; + template< int Bits > struct int_t; +template< int Bits > + struct int_exact_t; + template< int Bits > struct uint_t; -template< long MaxValue > +template< int Bits > + struct uint_exact_t; + +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; // 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 + class low_bits_mask_t; // From ------------------------------------// 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/index.html b/index.html index 7ab3ea0..1f0f83c 100644 --- a/index.html +++ b/index.html @@ -10,8 +10,8 @@ boost.png (6897 bytes) Home Libraries - People - FAQ + People + FAQ More @@ -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.htm b/integer.htm index 4dfd977..0130d7a 100644 --- a/integer.htm +++ b/integer.htm @@ -21,8 +21,9 @@ is particularly useful for solving generic programming problems.

    • Contents
    • Synopsis
    • -
    • Easiest-to-Manipulate Types
    • +
    • Processor-Optimized Types
    • Sized Types
    • +
    • MPL-Compatible Variants
    • Example
    • Demonstration Program
    • Rationale
    • @@ -32,67 +33,145 @@ is particularly useful for solving generic programming problems.

      Synopsis

      -
      namespace boost
      +
      +#include <boost/integer_fwd.hpp>  // forwarding header
      +#include <boost/cstdint.hpp>      // for boost::uintmax_t, intmax_t
      +
      +namespace boost
       {
         //  fast integers from least integers
      +  template< typename BaseInt >
      +  struct fast_integral
      +  {
      +      typedef implementation_supplied  type;
      +  };
      +
         template< typename LeastInt >
         struct int_fast_t
         {
      -      typedef implementation_supplied  fast;
      +      typedef typename fast_integral<LeastInt>::type  fast;
      +  };
      +
      +  //  MPL-compatible
      +  template< int Bits, typename Signedness >
      +  struct sized_integral
      +  {
      +      static  bool const  is_specialized = implementation_supplied;
      +      static  bool const  is_signed = implementation_supplied;
      +      static  int const   bit_count = Bits;
      +
      +      typedef implementation_supplied  type;
      +  };
      +
      +  template< int Bits, typename Signedness >
      +  struct exact_integral
      +  {
      +      static  bool const  is_specialized = implementation_supplied;
      +      static  bool const  is_signed = implementation_supplied;
      +      static  int const   bit_count = Bits;
      +
      +      typedef implementation_supplied  type;
      +  };
      +
      +  template< intmax_t MaxValue >
      +  struct maximum_signed_integral
      +  {
      +      static  bool const      is_specialized = implementation_supplied;
      +      static  bool const      is_signed = true;
      +      static  intmax_t const  bound = MaxValue;
      +
      +      typedef implementation_supplied  type;
      +  };
      +
      +  template< intmax_t MinValue >
      +  struct minimum_signed_integral
      +  {
      +      static  bool const      is_specialized = implementation_supplied;
      +      static  bool const      is_signed = true;
      +      static  intmax_t const  bound = MinValue;
      +
      +      typedef implementation_supplied  type;
      +  };
      +
      +  template< uintmax_t Value >
      +  struct maximum_unsigned_integral
      +  {
      +      static  bool const       is_specialized = implementation_supplied;
      +      static  bool const       is_signed = false;
      +      static  uintmax_t const  bound = Value;
      +
      +      typedef implementation_supplied  type;
         };
       
         //  signed
         template< int Bits >
         struct int_t 
         {
      -      typedef implementation_supplied  least;
      -      typedef int_fast_t<least>::fast  fast;
      +      typedef typename sized_integral<Bits, signed>::type  least;
      +      typedef int_fast_t<least>::fast                      fast;
      +  };
      +
      +  template< int Bits >
      +  struct int_exact_t
      +  {
      +      typedef typename exact_integral<Bits, signed>::type  exact;
         };
       
         //  unsigned
         template< int Bits >
         struct uint_t 
         {
      -      typedef implementation_supplied  least;
      -      typedef int_fast_t<least>::fast  fast;
      +      typedef typename sized_integral<Bits, unsigned>::type  least;
      +      typedef int_fast_t<least>::fast                        fast;
      +  };
      +
      +  template< int Bits >
      +  struct uint_exact_t
      +  {
      +      typedef typename exact_integral<Bits, unsigned>::type  exact;
         };
       
         //  signed
      -  template< long MaxValue >
      +  template< intmax_t MaxValue >
         struct int_max_value_t 
         {
      -      typedef implementation_supplied  least;
      -      typedef int_fast_t<least>::fast  fast;
      +      typedef typename maximum_signed_integral<MaxValue>::type  least;
      +      typedef int_fast_t<least>::fast                           fast;
         };
       
      -  template< long MinValue >
      +  template< intmax_t MinValue >
         struct int_min_value_t 
         {
      -      typedef implementation_supplied  least;
      -      typedef int_fast_t<least>::fast  fast;
      +      typedef typename minimum_signed_integral<MinValue>::type  least;
      +      typedef int_fast_t<least>::fast                           fast;
         };
       
         //  unsigned
      -  template< unsigned long Value >
      +  template< uintmax_t Value >
         struct uint_value_t 
         {
      -      typedef implementation_supplied  least;
      -      typedef int_fast_t<least>::fast  fast;
      +      typedef typename maximum_unsigned_integral<Value>::type  least;
      +      typedef int_fast_t<least>::fast                          fast;
         };
       } // namespace boost
       
      -

      Easiest-to-Manipulate Types

      +

      Processor-Optimized Types

      -

      The int_fast_t class template maps its input type to the +

      The fast_integral class template maps its input type to the next-largest type that the processor can manipulate the easiest, or to itself if the input type is already an easy-to-manipulate type. For instance, processing a bunch of char objects may go faster if they were converted to int objects before processing. -The input type, passed as the only template parameter, must be a -built-in integral type, except bool. Unsigned integral -types can be used, as well as signed integral types, despite the name. -The output type is given as the class member fast.

      +The input type, passed as the only template parameter, can be any built-in +integral type besides bool. The output type is given as the class +member type.

      + +

      The int_fast_t class template is the classic meta-function for +this operation. Despite the name, it works for unsigned integral types just +like it works for the signed integral types. The output type is given as the +class member fast, defined to be the same as the corresponding +result from the fast_integral meta-function.

      Implementation Notes
      By default, the output type is identical to the input type. Eventually, @@ -104,72 +183,286 @@ type.

      Sized Types

      -

      The int_t, uint_t, -int_max_value_t, int_min_value_t, and -uint_value_t class templates find the most appropiate -built-in integral type for the given template parameter. This type is -given by the class member least. The easiest-to-manipulate -version of that type is given by the class member fast. -The following table describes each template's criteria.

      +

      The int_t, int_exact_t, uint_t, +uint_exact_t, int_max_value_t, +int_min_value_t, and uint_value_t class templates find +the most appropriate built-in integral type for the given template parameter. +This type is given by the class member least or exact. +For the non-exact class templates, the easiest-to-manipulate version of that +type is given by the class member fast. The following table +describes each template's criteria.

      - +
      - + - + + boost::intmax_t. - + + + + + + the given number of bits. The parameter must be a + non-negative number. A compile-time error results if the parameter + is larger than the number of bits in a + boost::uintmax_t. - + + + + + - + - +
      Criteria for the Sized Type Class Templates
      Class TemplateClass Template (all in name-space boost) Template Parameter Mapping
      boost::int_tint_t The smallest built-in signed integral type with at least the given number of bits, including the sign bit. The parameter - should be a positive number. A compile-time error results if + must be a positive number. A compile-time error results if the parameter is larger than the number of bits in a - long.
      boost::uint_tint_exact_tThe smallest built-in signed integral type with exactly the + given number of bits, including the sign bit. A compile-time error + results if no qualifying type exists.
      uint_t The smallest built-in unsigned integral type with at least - the given number of bits. The parameter should be a positive - number. A compile-time error results if the parameter is - larger than the number of bits in an unsigned - long.
      boost::int_max_value_tuint_exact_tThe smallest built-in unsigned integral type with exactly the given + number of bits. A compile-time error results if no qualifying type + exists.
      int_max_value_t The smallest built-in signed integral type that supports the - given value as a maximum. The parameter should be a + given value as a maximum. The parameter must be a positive number.
      boost::int_min_value_tint_min_value_t The smallest built-in signed integral type that supports the - given value as a minimum. The parameter should be a + given value as a minimum. The parameter must be a negative number.
      boost::uint_value_tuint_value_t The smallest built-in unsigned integral type that supports the given value as a maximum. The parameter should be a positive number.
      +

      MPL-Compatible Variants

      + +

      The bit-length sized-type class templates have several drawbacks:

      + +
        +
      • You must know the valid bit-lengths in advance.
      • +
      • There is no way to inspect the parameter used after a size-type template + class is aliased.
      • +
      • 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 size-type class templates + incompatible with template meta-programming techniques.
      • +
      + +

      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 >
      +struct name
      +{
      +    static  bool const         is_specialized = implementation_supplied;
      +    static  bool const         is_signed = implementation_supplied;
      +    static  SwitchType const   switch_id = SwitchValue;
      +
      +    typedef implementation_supplied  type;
      +};
      +
      + +

      Each member, if present, is defined by:

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Members in MPL-Compatible Class Templates
      Class Template MemberWhen DefinedMeaning
      is_specializedAlwaysFlag indicating when a particular template class instantiation is a + valid meta-function (true) or not (false).
      is_signedis_specialized == trueFlag indicating whether the signed-variant (true) or + the unsigned-variant (false) of the meta-function is + used. This is controlled by the Signedness template + parameter: + + + + + + + + + + + + + + + + + + +
      Effect of Signedness Setting
      Signedness Typeis_signed
      signedtrue
      unsignedfalse
      anything elsenot defined
      + The type used is a programmer mnemonic; the compiler cannot prevent + someone from using int or signed int + instead of signed, or unsigned int instead + of unsigned.
      switch_id (Actual name is template-specific.)AlwaysThe value of the main control parameter, accessible even if the + template class instantiation is aliased.
      typeis_specialized == trueThe meta-function's result. It appears only if the input parameters + satisfy the template's requirements. Its presence, or lack thereof, + enables "Substitution Failure Is Not An Error" (SFINAE) + techniques, instead of a hard compiler diagnostic.
      + +

      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 +controls the appropriate emulation.)

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Criteria for the MPL-Compatible Class Templates
      Class Template (all in name-space boost)Parameter Type (in name-space boost as needed)Parameter Member IDClassic EquivalentTemplate Parameter Mapping (when type is defined)
      SignedUnsigned
      sized_integralintbit_countint_tuint_tThe 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_integralintbit_countint_exact_tuint_exact_tThe 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_integralintmax_tboundint_max_value_tThe 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_integralintmax_tboundint_min_value_tThe smallest built-in integral type that can perserve the value in + bound. Not present if bound is non-negative.
      maximum_unsigned_integraluintmax_tbounduint_value_tThe smallest built-in integral type that can perserve the value in + bound. Should always be present.
      +

      Example

      -
      #include <boost/integer.hpp>
      +
      +#include <boost/integer.hpp>
      +#include <boost/mpl/int.hpp>
      +#include <iostream>
      +#include <ostream>
      +
      +//...
      +
      +template < int Bits >
      +bool
      +fit_exactly( boost::mpl::int_<Bits> const &x,
      + typename boost::exact_integral<Bits, signed>::type *unused = 0 )
      +{
      +    return true;
      +}
      +
      +template < typename T >
      +bool
      +fit_exactly( T const &x )
      +{
      +    return false;
      +}
       
       //...
       
       int main()
       {
      -    boost::int_t<24>::least my_var;
      +    typedef boost::mpl::int_<24>  twenty_four;
      +
      +    boost::int_t<twenty_four::value>::least my_var;
      +
      +    //...
      +
      +    std::cout << "my_var " << ( fit_exactly(twenty_four()) ? "does" :
      +     "does not" ) << " fit its type exactly." << std::endl;
      +
           //...
       }
       

      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.

      @@ -193,20 +486,20 @@ 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 -value-based sized templates.

      +href="http://www.boost.org/people/daryle_walker.html">Daryle Walker designed the +exact and value-based sized templates, and the MPL-compatible templates.


      -

      Revised May 20, 2001

      +

      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 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 + diff --git a/integer_traits.html b/integer_traits.html index b52b76a..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

      @@ -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

      + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 0000000..50fceee --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,20 @@ +#~ 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 + /boost/test//boost_unit_test_framework ] + [ run integer_traits_test.cpp + /boost/test//boost_test_exec_monitor/static ] + [ run integer_mask_test.cpp + /boost/test//boost_unit_test_framework ] + [ 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 ] + [ compile issue_2134.cpp ] + ; diff --git a/test/cstdint_test.cpp b/test/cstdint_test.cpp new file mode 100644 index 0000000..88422de --- /dev/null +++ b/test/cstdint_test.cpp @@ -0,0 +1,233 @@ +// boost cstdint.hpp test program ------------------------------------------// + +// Copyright Beman Dawes 2000. 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) + + +// See http://www.boost.org/libs/integer for documentation. + +// Revision History +// 11 Sep 01 Adapted to work with macros defined in native stdint.h (John Maddock) +// 12 Nov 00 Adapted to merged +// 23 Sep 00 Added INTXX_C constant macro support + int64_t support (John Maddock). +// 28 Jun 00 Initial version +#define __STDC_CONSTANT_MACROS +#include +#include +#include + +#ifdef NDEBUG +int main() +{ + std::cout << "This test makes no sense with NDEBUG defined.\n"; + return 0; +} +#else + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// +// the following class is designed to verify +// that the various INTXX_C macros can be used +// in integral constant expressions: +// +struct integral_constant_checker +{ + static const boost::int8_t int8 = INT8_C(-127); + static const boost::int_least8_t int_least8 = INT8_C(-127); + static const boost::int_fast8_t int_fast8 = INT8_C(-127); + + static const boost::uint8_t uint8 = UINT8_C(255); + static const boost::uint_least8_t uint_least8 = UINT8_C(255); + static const boost::uint_fast8_t uint_fast8 = UINT8_C(255); + + static const boost::int16_t int16 = INT16_C(-32767); + static const boost::int_least16_t int_least16 = INT16_C(-32767); + static const boost::int_fast16_t int_fast16 = INT16_C(-32767); + + static const boost::uint16_t uint16 = UINT16_C(65535); + static const boost::uint_least16_t uint_least16 = UINT16_C(65535); + static const boost::uint_fast16_t uint_fast16 = UINT16_C(65535); + + static const boost::int32_t int32 = INT32_C(-2147483647); + static const boost::int_least32_t int_least32 = INT32_C(-2147483647); + static const boost::int_fast32_t int_fast32 = INT32_C(-2147483647); + + static const boost::uint32_t uint32 = UINT32_C(4294967295); + static const boost::uint_least32_t uint_least32 = UINT32_C(4294967295); + static const boost::uint_fast32_t uint_fast32 = UINT32_C(4294967295); + + static void check(); +}; + +void integral_constant_checker::check() +{ + assert( int8 == -127 ); + assert( int_least8 == -127 ); + assert( int_fast8 == -127 ); + assert( uint8 == 255u ); + assert( uint_least8 == 255u ); + assert( uint_fast8 == 255u ); + assert( int16 == -32767 ); + assert( int_least16 == -32767 ); + assert( int_fast16 == -32767 ); + assert( uint16 == 65535u ); + assert( uint_least16 == 65535u ); + assert( uint_fast16 == 65535u ); + assert( int32 == -2147483647 ); + assert( int_least32 == -2147483647 ); + assert( int_fast32 == -2147483647 ); + assert( uint32 == 4294967295u ); + assert( uint_least32 == 4294967295u ); + assert( uint_fast32 == 4294967295u ); +} +#endif // BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +// +// the following function simply verifies that the type +// of an integral constant is correctly defined: +// +#ifdef __BORLANDC__ +#pragma option -w-8008 +#pragma option -w-8066 +#endif +template +void integral_constant_type_check(T1, T2) +{ + // + // the types T1 and T2 may not be exactly + // the same type, but they should be the + // same size and signedness. We could use + // numeric_limits to verify this, but + // numeric_limits implementations currently + // vary too much, or are incomplete or missing. + // + T1 t1 = static_cast(-1); // cast suppresses warnings + T2 t2 = static_cast(-1); // ditto +#if defined(BOOST_HAS_STDINT_H) + // if we have a native stdint.h + // then the INTXX_C macros may define + // a type that's wider than required: + assert(sizeof(T1) <= sizeof(T2)); +#else + assert(sizeof(T1) == sizeof(T2)); + assert(t1 == t2); +#endif +#if defined(BOOST_HAS_STDINT_H) + // native headers are permitted to promote small + // unsigned types to type int: + if(sizeof(T1) >= sizeof(int)) + { + if(t1 > 0) + assert(t2 > 0); + else + assert(!(t2 > 0)); + } + else if(t1 < 0) + assert(!(t2 > 0)); +#else + if(t1 > 0) + assert(t2 > 0); + else + assert(!(t2 > 0)); +#endif +} + + +int main() +{ +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + integral_constant_checker::check(); +#endif + // + // verify the types of the integral constants: + // + integral_constant_type_check(boost::int8_t(0), INT8_C(0)); + integral_constant_type_check(boost::uint8_t(0), UINT8_C(0)); + integral_constant_type_check(boost::int16_t(0), INT16_C(0)); + integral_constant_type_check(boost::uint16_t(0), UINT16_C(0)); + integral_constant_type_check(boost::int32_t(0), INT32_C(0)); + integral_constant_type_check(boost::uint32_t(0), UINT32_C(0)); +#ifndef BOOST_NO_INT64_T + integral_constant_type_check(boost::int64_t(0), INT64_C(0)); + integral_constant_type_check(boost::uint64_t(0), UINT64_C(0)); +#endif + // + boost::int8_t int8 = INT8_C(-127); + boost::int_least8_t int_least8 = INT8_C(-127); + boost::int_fast8_t int_fast8 = INT8_C(-127); + + boost::uint8_t uint8 = UINT8_C(255); + boost::uint_least8_t uint_least8 = UINT8_C(255); + boost::uint_fast8_t uint_fast8 = UINT8_C(255); + + boost::int16_t int16 = INT16_C(-32767); + boost::int_least16_t int_least16 = INT16_C(-32767); + boost::int_fast16_t int_fast16 = INT16_C(-32767); + + boost::uint16_t uint16 = UINT16_C(65535); + boost::uint_least16_t uint_least16 = UINT16_C(65535); + boost::uint_fast16_t uint_fast16 = UINT16_C(65535); + + boost::int32_t int32 = INT32_C(-2147483647); + boost::int_least32_t int_least32 = INT32_C(-2147483647); + boost::int_fast32_t int_fast32 = INT32_C(-2147483647); + + boost::uint32_t uint32 = UINT32_C(4294967295); + boost::uint_least32_t uint_least32 = UINT32_C(4294967295); + boost::uint_fast32_t uint_fast32 = UINT32_C(4294967295); + +#ifndef BOOST_NO_INT64_T + boost::int64_t int64 = INT64_C(-9223372036854775807); + boost::int_least64_t int_least64 = INT64_C(-9223372036854775807); + boost::int_fast64_t int_fast64 = INT64_C(-9223372036854775807); + + boost::uint64_t uint64 = UINT64_C(18446744073709551615); + boost::uint_least64_t uint_least64 = UINT64_C(18446744073709551615); + boost::uint_fast64_t uint_fast64 = UINT64_C(18446744073709551615); + + boost::intmax_t intmax = INTMAX_C(-9223372036854775807); + boost::uintmax_t uintmax = UINTMAX_C(18446744073709551615); +#else + boost::intmax_t intmax = INTMAX_C(-2147483647); + boost::uintmax_t uintmax = UINTMAX_C(4294967295); +#endif + + assert( int8 == -127 ); + assert( int_least8 == -127 ); + assert( int_fast8 == -127 ); + assert( uint8 == 255u ); + assert( uint_least8 == 255u ); + assert( uint_fast8 == 255u ); + assert( int16 == -32767 ); + assert( int_least16 == -32767 ); + assert( int_fast16 == -32767 ); + assert( uint16 == 65535u ); + assert( uint_least16 == 65535u ); + assert( uint_fast16 == 65535u ); + assert( int32 == -2147483647 ); + assert( int_least32 == -2147483647 ); + assert( int_fast32 == -2147483647 ); + assert( uint32 == 4294967295u ); + assert( uint_least32 == 4294967295u ); + assert( uint_fast32 == 4294967295u ); + +#ifndef BOOST_NO_INT64_T + assert( int64 == INT64_C(-9223372036854775807) ); + assert( int_least64 == INT64_C(-9223372036854775807) ); + assert( int_fast64 == INT64_C(-9223372036854775807) ); + assert( uint64 == UINT64_C(18446744073709551615) ); + assert( uint_least64 == UINT64_C(18446744073709551615) ); + assert( uint_fast64 == UINT64_C(18446744073709551615) ); + assert( intmax == INT64_C(-9223372036854775807) ); + assert( uintmax == UINT64_C(18446744073709551615) ); +#else + assert( intmax == -2147483647 ); + assert( uintmax == 4294967295u ); +#endif + + + std::cout << "OK\n"; + return 0; +} +#endif diff --git a/test/integer_mask_test.cpp b/test/integer_mask_test.cpp index 6146ddf..65b6fc2 100644 --- a/test/integer_mask_test.cpp +++ b/test/integer_mask_test.cpp @@ -8,104 +8,164 @@ // 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) -#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 std::numeric_limits +#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::cout (std::endl indirectly) +#include // for std::size_t +#include // for std::hex +#include // for std::cout +#include // for std::endl -#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) +// Control if events will be printed conventionally, or just logged. +#ifndef CONTROL_SHOW_TYPES +#define CONTROL_SHOW_TYPES 0 +#endif -#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) +// 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 -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 ); +// List the ranges of template parameters tests (ranges are half-open) +int const max_offset = std::numeric_limits::digits; - 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 ); +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; - return boost::exit_success; +// 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 + + +// 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 ) +{ + 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, ==, + result_type::value ); + BOOST_MPL_ASSERT_RELATION( boost::high_bit_mask_t::high_bit_fast, + ==, result_type::value ); +} + +// 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 + // 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. + 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, ==, + result_type::value ); + BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t::sig_bits_fast, + ==, 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() + +// Verification of bugs and their fixes +BOOST_AUTO_TEST_SUITE( bug_fix_tests ) + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/integer_test.cpp b/test/integer_test.cpp new file mode 100644 index 0000000..8f5c834 --- /dev/null +++ b/test/integer_test.cpp @@ -0,0 +1,685 @@ +// boost integer.hpp test program ------------------------------------------// + +// Copyright Beman Dawes 1999. 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) + +// See http://www.boost.org/libs/integer for documentation. + +// Revision History +// 16 Jul 08 Added MPL-compatible variants of the minimum-size and value- +// based integer templates. (Daryle Walker) +// 15 Jul 08 Added exact-integer templates; added MPL-compatible variant of +// processor-optimized integer template. (Daryle Walker) +// 14 Jul 08 Improved testing of processor-optimized integer template; added +// extended-integer support. (Daryle Walker) +// 13 Jul 08 Modernized tests w/ MPL instead of giant macros (Daryle Walker) +// 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 // 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 // BOOST_HAS_XINT, BOOST_UXINT_MAX + +#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::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::shift_right +#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 std::binary_search +#include // for ULONG_MAX, LONG_MAX, LONG_MIN, etc. +#include // for std::size_t +#include // for std::cout +#include // for std::endl +#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 +#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 +// 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 fast_integral< short > + { + typedef CONTROL_FAST_SHORT type; + }; +} + + +// 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 +{ + +// 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 +#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX) + , boost::detail::uxint_t +#endif +> distinct_unsigned_types; + +typedef boost::mpl::transform< + distinct_unsigned_types, + boost::make_signed< boost::mpl::_1 > +>::type distinct_signed_types; + +// List the digit counts for each integral type +template < typename T > +struct digits_of + : boost::mpl::int_< std::numeric_limits::digits > +{ +}; + +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< + 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; + +// Maximum number of bits allowed +typedef std::numeric_limits intmax_limits; +typedef std::numeric_limits uintmax_limits; + +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< + distinct_integral_bit_counts, + median_bit_counts + >, + boost::mpl::front_inserter< + boost::mpl::vector< + boost::mpl::integral_c + > + > + >::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 +int const integral_bit_lengths[] = { + std::numeric_limits< unsigned char >::digits +#if USHRT_MAX > UCHAR_MAX + , std::numeric_limits< unsigned short >::digits +#endif +#if UINT_MAX > USHRT_MAX + , std::numeric_limits< unsigned int >::digits +#endif +#if ULONG_MAX > UINT_MAX + , std::numeric_limits< unsigned long >::digits +#endif +#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX) + , std::numeric_limits< boost::detail::uxint_t >::digits +#endif +}; + +std::size_t const integral_type_count = sizeof(integral_bit_lengths) / + sizeof(integral_bit_lengths[0]); + +// "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_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( "This is " << template_pre_name << setting + << template_post_name << " specialization, with type '" << typeid(typename + Tmpl::type).name() << "'." ); + return true; +} + +template < typename ValueT, typename T > +bool +print_out_template( T const &, ValueT setting, char const *template_pre_name, + char const *template_post_name ) +{ + 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 + +// 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 + + +// 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 ) +{ + typedef short least_type; + typedef boost::int_fast_t::fast fast_type; + typedef std::numeric_limits least_limits; + typedef std::numeric_limits fast_limits; + + typedef boost::fast_integral::type real_fast_type; + + 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 ); + 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 ) + +// 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_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, +// 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 + // 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. + BOOST_MPL_ASSERT_RELATION( std::numeric_limits::least>::digits, >=, T::value ); + BOOST_MPL_ASSERT_RELATION( std::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 +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_unsigned_values_test, T, + valid_to_increase_ubits_list ) +{ + // 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.) + boost::uintmax_t const one = 1u; + + BOOST_MPL_ASSERT( (boost::mpl::equal< boost::maximum_unsigned_integral<(one + << T::value)>, unsigned_sized_integral >) ); +} + +// 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).) + static boost::intmax_t const one = 1; + + 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 ) +{ + bool const is_exact_length = std::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 ) +{ + 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 ) +{ + typedef signed_sized_integral< 3> ssz3_type; + typedef signed_sized_integral< 0> ssz0_type; + typedef signed_sized_integral<-3> 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>") ); + + typedef unsigned_sized_integral< 3> usz3_type; + typedef unsigned_sized_integral< 0> usz0_type; + typedef unsigned_sized_integral<-3> 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>") ); + + 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; + + 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>") ); + + 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; + + 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>") ); + + typedef boost::maximum_signed_integral< 15> max15_type; + typedef boost::maximum_signed_integral< 0> max0_type; + typedef boost::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<", ">") ); + + typedef boost::minimum_signed_integral< 15> min15_type; + typedef boost::minimum_signed_integral< 0> min0_type; + typedef boost::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<", ">") ); + + typedef boost::maximum_unsigned_integral<15> umax15_type; + typedef boost::maximum_unsigned_integral< 0> umax0_type; + + 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() + +// Check if given constants can fit in given types +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_to_decrease_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 = { intmax_t.Max for int_t, uintmax_t.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. + 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( 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( 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 ) +{ + 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 ); + + 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 ); + BOOST_CHECK_EQUAL( repeated_bits_s, repeated_2bits_s ); +} + +// Check if large value can fit its minimum required size, by value, unsigned +BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_unsigned_values_test, T, + valid_to_increase_ubits_list ) +{ + // This test is supposed to replace the following checks given in + // 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}; Type = {least, fast}; Template:Extreme = + // {uintmax_t.Max for uint_value_t} + // In other words, the selected type doesn't mask out any bits it's not + // supposed to. But now we'll use template meta-programming instead of + // macros. The limit of type-lists is usually less than 32 (not to mention + // 64) elements, so we have to take selected values. + using boost::uintmax_t; + + typedef boost::mpl::shift_right, T> maxi_type; + + uintmax_t const maxi = maxi_type::value; + + 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 +BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_signed_values_test, T, + valid_to_increase_sbits_list ) +{ + // This test is supposed to replace the following checks given in + // puesdo-code by: + // Routine: Template, Type + // for ( N = 0, V = Template:Extreme ; N < 32 ; ++N, V >>= 1 ) + // Confirm( static_cast::Type>(V) == V ); + // end for + // end Routine + // with Template = {int_max_value_t, int_min_value_t}; Type = {least, fast}; + // Template:Extreme = {intmax_t.Min for int_min_value_t, intmax_t.Max + // for int_max_value_t} + // In other words, the selected type doesn't mask out any bits it's not + // supposed to. But now we'll use template meta-programming instead of + // macros. The limit of type-lists is usually less than 32 (not to mention + // 64) elements, so we have to take selected values. + using boost::intmax_t; + + typedef boost::mpl::shift_right, T> mini_type; + typedef boost::mpl::shift_right, T> maxi_type; + + intmax_t const maxi = maxi_type::value, mini = mini_type::value; + + 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() + +// Verification of bugs and their fixes +BOOST_AUTO_TEST_SUITE( bug_fix_tests ) + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/integer_traits_test.cpp b/test/integer_traits_test.cpp new file mode 100644 index 0000000..e3de239 --- /dev/null +++ b/test/integer_traits_test.cpp @@ -0,0 +1,102 @@ +/* boost integer_traits.hpp tests + * + * Copyright Jens Maurer 2000 + * 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) + * + * $Id$ + * + * Revision history + * 2000-02-22 Small improvements by Beman Dawes + * 2000-06-27 Rework for better MSVC and BCC co-operation + */ + +#include +#include +// use int64_t instead of long long for better portability +#include + +#define BOOST_INCLUDE_MAIN +#include + +/* + * General portability note: + * MSVC mis-compiles explicit function template instantiations. + * For example, f() and f() are both compiled to call f(). + * BCC is unable to implicitly convert a "const char *" to a std::string + * when using explicit function template instantiations. + * + * Therefore, avoid explicit function template instantiations. + */ + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) +template inline T make_char_numeric_for_streaming(T x) { return x; } +namespace fix{ +inline int make_char_numeric_for_streaming(char c) { return c; } +inline int make_char_numeric_for_streaming(signed char c) { return c; } +inline int make_char_numeric_for_streaming(unsigned char c) { return c; } +} +using namespace fix; +#else +template inline T make_char_numeric_for_streaming(T x) { return x; } +inline int make_char_numeric_for_streaming(char c) { return c; } +inline int make_char_numeric_for_streaming(signed char c) { return c; } +inline int make_char_numeric_for_streaming(unsigned char c) { return c; } +#endif + +template +void runtest(const char * type, T) +{ + typedef boost::integer_traits traits; + std::cout << "Checking " << type + << "; min is " << make_char_numeric_for_streaming((traits::min)()) + << ", max is " << make_char_numeric_for_streaming((traits::max)()) + << std::endl; + BOOST_CHECK(traits::is_specialized); +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1200) + // MSVC++ 6.0 issues a LNK1179 error (duplicate comdat) when the compiler + // generates different symbol names with a very long common prefix: + // the dummy "&& true" disambiguates between the symbols generated by this + // BOOST_CHECK instantiation and the preceding one. + BOOST_CHECK(traits::is_integer && true); +#else + BOOST_CHECK(traits::is_integer); +#endif + BOOST_CHECK(traits::is_integral == true); + BOOST_CHECK(traits::const_min == (traits::min)()); + BOOST_CHECK(traits::const_max == (traits::max)()); +} + +int test_main(int, char*[]) +{ + runtest("bool", bool()); + runtest("char", char()); + typedef signed char signed_char; + runtest("signed char", signed_char()); + typedef unsigned char unsigned_char; + runtest("unsigned char", unsigned_char()); + runtest("wchar_t", wchar_t()); + runtest("short", short()); + typedef unsigned short unsigned_short; + runtest("unsigned short", unsigned_short()); + runtest("int", int()); + typedef unsigned int unsigned_int; + runtest("unsigned int", unsigned_int()); + runtest("long", long()); + typedef unsigned long unsigned_long; + runtest("unsigned long", unsigned_long()); +#if !defined(BOOST_NO_INT64_T) && (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && !defined(__BORLANDC__) && !defined(__BEOS__) + // + // MS/Borland compilers can't support 64-bit member constants + // BeOS doesn't have specialisations for long long in SGI's header. + runtest("int64_t (possibly long long)", boost::int64_t()); + runtest("uint64_t (possibly unsigned long long)", boost::uint64_t()); +#else + std::cout << "Skipped int64_t and uint64_t" << std::endl; +#endif + // Some compilers don't pay attention to std:3.6.1/5 and issue a + // warning here if "return 0;" is omitted. + return 0; +} + 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; }