1 /* boost random/traits.hpp header file
2  *
3  * Copyright John Maddock 2015
4  * Distributed under the Boost Software License, Version 1.0. (See
5  * accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  * See http://www.boost.org for most recent version including documentation.
9  *
10  * These traits classes serve two purposes: they are designed to mostly
11  * work out of the box for multiprecision types (ie number types that are
12  * C++ class types and not integers or floats from type-traits point of view),
13  * they are also a potential point of specialization for user-defined
14  * number types.
15  *
16  * $Id$
17  */
18 
19 #ifndef BOOST_RANDOM_TRAITS_HPP
20 #define BOOST_RANDOM_TRAITS_HPP
21 
22 #include <boost/type_traits/is_signed.hpp>
23 #include <boost/type_traits/is_integral.hpp>
24 #include <boost/type_traits/make_unsigned.hpp>
25 #include <boost/mpl/bool.hpp>
26 #include <limits>
27 
28 namespace boost {
29 namespace random {
30 namespace traits {
31    // \cond show_private
32    template <class T, bool intrinsic>
33    struct make_unsigned_imp
34    {
35       typedef typename boost::make_unsigned<T>::type type;
36    };
37    template <class T>
38    struct make_unsigned_imp<T, false>
39    {
40       BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
41       BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_signed == false);
42       BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer == true);
43       typedef T type;
44    };
45    // \endcond
46    /** \brief Converts the argument type T to an unsigned type.
47    *
48    * This trait has a single member `type` which is the unsigned type corresponding to T.
49    * Note that
50    * if T is signed, then member `type` *should define a type with one more bit precision than T*.  For built-in
51    * types this trait defaults to `boost::make_unsigned<T>::type`.  For user defined types it simply asserts that
52    * the argument type T is an unsigned integer (using std::numeric_limits).
53    * User defined specializations may be provided for other cases.
54    */
55    template <class T>
56    struct make_unsigned
57    // \cond show_private
58       : public make_unsigned_imp < T, boost::is_integral<T>::value >
59       // \endcond
60    {};
61    // \cond show_private
62    template <class T, bool intrinsic>
63    struct make_unsigned_or_unbounded_imp
64    {
65       typedef typename boost::make_unsigned<T>::type type;
66    };
67    template <class T>
68    struct make_unsigned_or_unbounded_imp<T, false>
69    {
70       BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
71       BOOST_STATIC_ASSERT((std::numeric_limits<T>::is_signed == false) || (std::numeric_limits<T>::is_bounded == false));
72       BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer == true);
73       typedef T type;
74    };
75    // \endcond
76    /** \brief Converts the argument type T to either an unsigned type or an unbounded integer type.
77    *
78    * This trait has a single member `type` which is either the unsigned type corresponding to T or an unbounded
79    * integer type.  This trait is used to generate types suitable for the calculation of a range: as a result
80    * if T is signed, then member `type` *should define a type with one more bit precision than T*.  For built-in
81    * types this trait defaults to `boost::make_unsigned<T>::type`.  For user defined types it simply asserts that
82    * the argument type T is either an unbounded integer, or an unsigned one (using std::numeric_limits).
83    * User defined specializations may be provided for other cases.
84    */
85    template <class T>
86    struct make_unsigned_or_unbounded
87       // \cond show_private
88       : public make_unsigned_or_unbounded_imp < T, boost::is_integral<T>::value >
89       // \endcond
90    {};
91    /** \brief Traits class that indicates whether type T is an integer
92    */
93    template <class T>
94    struct is_integral
95       : public mpl::bool_<boost::is_integral<T>::value || (std::numeric_limits<T>::is_integer)>
96    {};
97    /** \brief Traits class that indicates whether type T is a signed integer
98    */
99    template <class T> struct is_signed
100       : public mpl::bool_ < boost::is_signed<T>::value || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed)>
101    {};
102 
103 }
104 }
105 }
106 
107 #endif
108