16 #include <meta/meta.hpp>
18 #include <sdsl/bits.hpp>
24 #if __has_include(<endian.h>) // unix GLIBC
26 #elif __has_include(<sys/endian.h>) // *BSD
27 #include <sys/endian.h>
28 #endif // __has_include(endian.h)
34 namespace seqan3::detail
42 template <
typename type_t>
43 constexpr
auto sizeof_bits = min_viable_uint_v<CHAR_BIT *
sizeof(type_t)>;
54 constexpr
bool is_power_of_two(
size_t const n)
56 return n > 0 && (n & (n-1)) == 0;
70 constexpr
size_t next_power_of_two(
size_t n)
76 for (
size_t shift = 1; !is_power_of_two(n + 1); shift <<= 1)
105 template <std::
unsigned_
integral
unsigned_t>
106 constexpr uint8_t popcount(unsigned_t
const n) noexcept
108 #if defined(__GNUC__)
109 if constexpr (
sizeof(unsigned_t) ==
sizeof(
unsigned long long))
110 return __builtin_popcountll(n);
111 else if constexpr (
sizeof(unsigned_t) ==
sizeof(
unsigned long))
112 return __builtin_popcountl(n);
114 return __builtin_popcount(n);
116 return sdsl::bits::cnt(n);
145 template <std::
unsigned_
integral
unsigned_t>
146 constexpr uint8_t count_leading_zeros(unsigned_t
const n) noexcept
149 #if defined(__GNUC__)
150 if constexpr (
sizeof(unsigned_t) ==
sizeof(
unsigned long long))
151 return __builtin_clzll(n);
152 else if constexpr (
sizeof(unsigned_t) ==
sizeof(
unsigned long))
153 return __builtin_clzl(n);
155 return __builtin_clz(n) + sizeof_bits<unsigned_t> - sizeof_bits<unsigned int>;
157 return sizeof_bits<unsigned_t> - sdsl::bits::hi(n) - 1;
186 template <std::
unsigned_
integral
unsigned_t>
187 constexpr uint8_t count_trailing_zeros(unsigned_t
const n) noexcept
190 #if defined(__GNUC__)
191 if constexpr (
sizeof(unsigned_t) ==
sizeof(
unsigned long long))
192 return __builtin_ctzll(n);
193 else if constexpr (
sizeof(unsigned_t) ==
sizeof(
unsigned long))
194 return __builtin_ctzl(n);
196 return __builtin_ctz(n);
198 return sdsl::bits::lo(n);
227 template <std::
unsigned_
integral
unsigned_t>
228 constexpr uint8_t most_significant_bit_set(unsigned_t
const n) noexcept
231 #if defined(__GNUC__)
232 return sizeof_bits<unsigned_t> - count_leading_zeros(n) - 1;
234 return sdsl::bits::hi(n);
250 template <std::
integral type>
251 constexpr type to_little_endian(type
const in) noexcept
253 if constexpr (endian::native == endian::little)
257 else if constexpr (endian::native == endian::big)
259 static_assert(
sizeof(type) <= 8,
260 "Can only convert the byte encoding for integral numbers with a size of up to 8 bytes.");
261 static_assert(is_power_of_two(
sizeof(type)),
262 "Can only convert the byte encoding for integral numbers whose byte size is a power of two.");
264 if constexpr (
sizeof(type) == 2)
266 else if constexpr (sizeof(type) == 4)
268 else if constexpr (sizeof(type) == 8)
275 static_assert(endian::native == endian::little || endian::native == endian::big,
276 "Expected a little-endian or big-endian platform.");