]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/safe_numerics/cpp.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / safe_numerics / cpp.hpp
CommitLineData
92f5a8d4
TL
1#ifndef BOOST_NUMERIC_CPP_HPP
2#define BOOST_NUMERIC_CPP_HPP
3
4// Copyright (c) 2012 Robert Ramey
5//
6// Distributed under the Boost Software License, Version 1.0. (See
7// accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9
10// policy which creates results types equal to that of C++ promotions.
11// Using the policy will permit the program to build and run in release
12// mode which is identical to that in debug mode except for the fact
13// that errors aren't trapped.
14
15#include <type_traits> // integral constant, remove_cv, conditional
16#include <limits>
17#include <boost/integer.hpp> // integer type selection
18
19#include "safe_common.hpp"
20#include "checked_result.hpp"
21
22namespace boost {
23namespace safe_numerics {
24
25// in C++ the following rules govern integer arithmetic
26
27// This policy is use to emulate another compiler/machine architecture
28// For example, a Z80 has 8 bit char, 16 bit short, 16 bit int, 32 bit long. So one
29// would use cpp<8, 16, 16, 32, 32> to test programs destined to run on a Z80
30
31// Follow section 5 of the standard.
32template<
33 int CharBits,
34 int ShortBits,
35 int IntBits,
36 int LongBits,
37 int LongLongBits
38>
39struct cpp {
40public:
41 using local_char_type = typename boost::int_t<CharBits>::exact;
42 using local_short_type = typename boost::int_t<ShortBits>::exact;
43 using local_int_type = typename boost::int_t<IntBits>::exact;
44 using local_long_type = typename boost::int_t<LongBits>::exact;
45 using local_long_long_type = typename boost::int_t<LongLongBits>::exact;
46
47 template<class T>
48 using rank =
49 typename std::conditional<
50 std::is_same<local_char_type, typename std::make_signed<T>::type>::value,
51 std::integral_constant<int, 1>,
52 typename std::conditional<
53 std::is_same<local_short_type, typename std::make_signed<T>::type>::value,
54 std::integral_constant<int, 2>,
55 typename std::conditional<
56 std::is_same<local_int_type, typename std::make_signed<T>::type>::value,
57 std::integral_constant<int, 3>,
58 typename std::conditional<
59 std::is_same<local_long_type, typename std::make_signed<T>::type>::value,
60 std::integral_constant<int, 4>,
61 typename std::conditional<
62 std::is_same<local_long_long_type, typename std::make_signed<T>::type>::value,
63 std::integral_constant<int, 5>,
64 std::integral_constant<int, 6> // catch all - never promote integral
65 >::type >::type >::type >::type >::type;
66
67 // section 4.5 integral promotions
68
69 // convert smaller of two types to the size of the larger
70 template<class T, class U>
71 using higher_ranked_type = typename std::conditional<
72 (rank<T>::value < rank<U>::value),
73 U,
74 T
75 >::type;
76
77 template<class T, class U>
78 using copy_sign = typename std::conditional<
79 std::is_signed<U>::value,
80 typename std::make_signed<T>::type,
81 typename std::make_unsigned<T>::type
82 >::type;
83
84 template<class T>
85 using integral_promotion = copy_sign<
86 higher_ranked_type<local_int_type, T>,
87 T
88 >;
89
90 // note presumption that T & U don't have he same sign
91 // if that's not true, these won't work
92 template<class T, class U>
93 using select_signed = typename std::conditional<
94 std::numeric_limits<T>::is_signed,
95 T,
96 U
97 >::type;
98
99 template<class T, class U>
100 using select_unsigned = typename std::conditional<
101 std::numeric_limits<T>::is_signed,
102 U,
103 T
104 >::type;
105
106 // section 5 clause 11 - usual arithmetic conversions
107 template<typename T, typename U>
108 using usual_arithmetic_conversions =
109 // clause 0 - if both operands have the same type
110 typename std::conditional<
111 std::is_same<T, U>::value,
112 // no further conversion is needed
113 T,
114 // clause 1 - otherwise if both operands have the same sign
115 typename std::conditional<
116 std::numeric_limits<T>::is_signed
117 == std::numeric_limits<U>::is_signed,
118 // convert to the higher ranked type
119 higher_ranked_type<T, U>,
120 // clause 2 - otherwise if the rank of he unsigned type exceeds
121 // the rank of the of the signed type
122 typename std::conditional<
123 rank<select_unsigned<T, U>>::value
124 >= rank< select_signed<T, U>>::value,
125 // use unsigned type
126 select_unsigned<T, U>,
127 // clause 3 - otherwise if the type of the signed integer type can
128 // represent all the values of the unsigned type
129 typename std::conditional<
130 std::numeric_limits< select_signed<T, U>>::digits >=
131 std::numeric_limits< select_unsigned<T, U>>::digits,
132 // use signed type
133 select_signed<T, U>,
134 // clause 4 - otherwise use unsigned version of the signed type
135 std::make_signed< select_signed<T, U>>
136 >::type >::type >::type
137 >;
138
139 template<typename T, typename U>
140 using result_type = typename usual_arithmetic_conversions<
141 integral_promotion<typename base_type<T>::type>,
142 integral_promotion<typename base_type<U>::type>
143 >::type;
144public:
145 template<typename T, typename U>
146 struct addition_result {
147 using type = result_type<T, U>;
148 };
149 template<typename T, typename U>
150 struct subtraction_result {
151 using type = result_type<T, U>;
152 };
153 template<typename T, typename U>
154 struct multiplication_result {
155 using type = result_type<T, U>;
156 };
157 template<typename T, typename U>
158 struct division_result {
159 using type = result_type<T, U>;
160 };
161 template<typename T, typename U>
162 struct modulus_result {
163 using type = result_type<T, U>;
164 };
165 // note: comparison_result (<, >, ...) is special.
166 // The return value is always a bool. The type returned here is
167 // the intermediate type applied to make the values comparable.
168 template<typename T, typename U>
169 struct comparison_result {
170 using type = result_type<T, U>;
171 };
172 template<typename T, typename U>
173 struct left_shift_result {
174 using type = result_type<T, U>;
175 };
176 template<typename T, typename U>
177 struct right_shift_result {
178 using type = result_type<T, U>;
179 };
180 template<typename T, typename U>
181 struct bitwise_and_result {
182 using type = result_type<T, U>;
183 };
184 template<typename T, typename U>
185 struct bitwise_or_result {
186 using type = result_type<T, U>;
187 };
188 template<typename T, typename U>
189 struct bitwise_xor_result {
190 using type = result_type<T, U>;
191 };
192};
193
194} // safe_numerics
195} // boost
196
197#endif // BOOST_NUMERIC_cpp_HPP