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