SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
bit_manipulation.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
14 #pragma once
15 
16 #include <meta/meta.hpp>
17 
18 #include <climits>
19 #include <utility>
20 
21 // Find correct header for byte-order conversion functions.
22 #if __has_include(<endian.h>) // unix GLIBC
23  #include <endian.h>
24 #elif __has_include(<sys/endian.h>) // *BSD
25  #include <sys/endian.h>
26 #endif // __has_include(endian.h)
27 
30 #include <seqan3/std/concepts>
31 
32 namespace seqan3::detail
33 {
34 
40 template <typename type_t>
41 constexpr auto sizeof_bits = min_viable_uint_v<CHAR_BIT * sizeof(type_t)>;
42 
52 constexpr bool is_power_of_two(size_t const n)
53 {
54  return n > 0 && (n & (n-1)) == 0;
55 }
56 
68 constexpr size_t next_power_of_two(size_t n)
69 {
70  if (n == 0)
71  return 1;
72 
73  --n;
74  for (size_t shift = 1; !is_power_of_two(n + 1); shift <<= 1)
75  n |= n >> shift;
76 
77  return n + 1;
78 }
79 
89 template <std::UnsignedIntegral unsigned_t>
90 constexpr uint8_t bit_scan_reverse(unsigned_t n)
91 {
92  assert(n > 0); // n == 0 might have undefined behaviour
93 #if defined(__GNUC__)
94  if constexpr (sizeof(unsigned_t) == sizeof(unsigned long long))
95  return sizeof_bits<unsigned long long> - __builtin_clzll(n) - 1;
96  else if constexpr (sizeof(unsigned_t) == sizeof(unsigned long))
97  return sizeof_bits<unsigned long> - __builtin_clzl(n) - 1;
98  else
99  return sizeof_bits<unsigned> - __builtin_clz(n) - 1;
100 #else
101  uint8_t i = 0;
102  for (; n != 0; n >>= 1, ++i);
103  return i - 1;
104 #endif
105 }
106 
119 template <std::Integral type>
120 constexpr type to_little_endian(type const in) noexcept
121 {
122  if constexpr (endian::native == endian::little)
123  {
124  return in;
125  }
126  else if constexpr (endian::native == endian::big)
127  {
128  static_assert(sizeof(type) <= 8,
129  "Can only convert the byte encoding for integral numbers with a size of up to 8 bytes.");
130  static_assert(is_power_of_two(sizeof(type)),
131  "Can only convert the byte encoding for integral numbers whose byte size is a power of two.");
132 
133  if constexpr (sizeof(type) == 2)
134  return htole16(in);
135  else if constexpr (sizeof(type) == 4)
136  return htole32(in);
137  else if constexpr (sizeof(type) == 8)
138  return htole64(in);
139  else
140  return in; // single byte.
141  }
142  else
143  {
144  static_assert(endian::native == endian::little || endian::native == endian::big,
145  "Expected a little-endian or big-endian platform.");
146  }
147 }
148 
149 } // namespace seqan3::detail
Provides metaprogramming utilities for integer types.
Provides seqan3::detail::endian.
The Concepts library.
Definition: aligned_sequence_concept.hpp:35