1 /**
2 * Copyright © 2018 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #pragma once
17
18 #include <boost/multiprecision/cpp_int.hpp>
19 #include <boost/version.hpp>
20 #include <ipmid/utility.hpp>
21
22 #include <bitset>
23 #include <tuple>
24
25 #if BOOST_VERSION < 107900
26 using bitcount_t = unsigned;
27 #else
28 using bitcount_t = std::size_t;
29 #endif
30
31 // unsigned fixed-bit sizes
32 template <bitcount_t N>
33 using fixed_uint_t =
34 boost::multiprecision::number<boost::multiprecision::cpp_int_backend<
35 N, N, boost::multiprecision::unsigned_magnitude,
36 boost::multiprecision::unchecked, void>>;
37 // signed fixed-bit sizes
38 template <bitcount_t N>
39 using fixed_int_t =
40 boost::multiprecision::number<boost::multiprecision::cpp_int_backend<
41 N, N, boost::multiprecision::signed_magnitude,
42 boost::multiprecision::unchecked, void>>;
43
44 using uint1_t = fixed_uint_t<1>;
45 using uint2_t = fixed_uint_t<2>;
46 using uint3_t = fixed_uint_t<3>;
47 using uint4_t = fixed_uint_t<4>;
48 using uint5_t = fixed_uint_t<5>;
49 using uint6_t = fixed_uint_t<6>;
50 using uint7_t = fixed_uint_t<7>;
51 // native uint8_t
52 using uint9_t = fixed_uint_t<9>;
53 using uint10_t = fixed_uint_t<10>;
54 using uint11_t = fixed_uint_t<11>;
55 using uint12_t = fixed_uint_t<12>;
56 using uint13_t = fixed_uint_t<13>;
57 using uint14_t = fixed_uint_t<14>;
58 using uint15_t = fixed_uint_t<15>;
59 // native uint16_t
60 using uint24_t = fixed_uint_t<24>;
61
62 // signed fixed-bit sizes
63 using int2_t = fixed_int_t<2>;
64 using int3_t = fixed_int_t<3>;
65 using int4_t = fixed_int_t<4>;
66 using int5_t = fixed_int_t<5>;
67 using int6_t = fixed_int_t<6>;
68 using int7_t = fixed_int_t<7>;
69 // native int8_t
70 using int9_t = fixed_int_t<9>;
71 using int10_t = fixed_int_t<10>;
72 using int11_t = fixed_int_t<11>;
73 using int12_t = fixed_int_t<12>;
74 using int13_t = fixed_int_t<13>;
75 using int14_t = fixed_int_t<14>;
76 using int15_t = fixed_int_t<15>;
77 // native int16_t
78 using int24_t = fixed_int_t<24>;
79
80 // bool is more efficient than a uint1_t
81 using bit = bool;
82
83 // Mechanism for going from uint7_t, int7_t, or std::bitset<7> to 7 bits
84 // use nrFixedBits<uint7_t> or nrFixedBits<decltype(u7)>
85 namespace types
86 {
87 namespace details
88 {
89
90 template <bitcount_t N>
91 struct Size
92 {
93 static constexpr bitcount_t value = N;
94 };
95
96 template <bitcount_t Bits>
97 constexpr auto getNrBits(const fixed_int_t<Bits>&) -> Size<Bits>;
98 template <bitcount_t Bits>
99 constexpr auto getNrBits(const fixed_uint_t<Bits>&) -> Size<Bits>;
100 template <bitcount_t Bits>
101 constexpr auto getNrBits(const std::bitset<Bits>&) -> Size<Bits>;
102
103 template <typename U>
104 using underlying_t =
105 typename std::conditional_t<std::is_enum_v<U>, std::underlying_type<U>,
106 std::enable_if<true, U>>::type;
107
108 } // namespace details
109
110 /**
111 * @brief mechanism to get N from a type like fixed_int_t<N>
112 *
113 * helper template to extract N from a fixed_(u)int_t variable
114 *
115 * @tparam T - a type of fixed_int_t<N> or fixed_unint_t<N>
116 *
117 * @return size_t - evaluates to a constexpr size_t of N
118 */
119 template <typename T>
120 constexpr auto nrFixedBits =
121 decltype(details::getNrBits(std::declval<T>()))::value;
122
123 /**
124 * @brief Converts a number or enum class to another
125 * @tparam R - The output type
126 * @tparam T - The input type
127 * @param t - An enum or integer value to cast
128 * @return The value in R form
129 */
130 template <typename R, typename T>
enum_cast(T t)131 inline R enum_cast(T t)
132 {
133 auto tu = static_cast<details::underlying_t<T>>(t);
134 auto ru = static_cast<details::underlying_t<R>>(tu);
135 return static_cast<R>(ru);
136 }
137
138 } // namespace types
139