OpenTTD Source: src/core/bitmath_func.hpp Source File

OpenTTD Source 14.0-RC3

bitmath_func.hpp
Go to the documentation of this file.
1 /*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10 #ifndef BITMATH_FUNC_HPP
11 #define BITMATH_FUNC_HPP
12
31 template <typename T>
32 debug_inline constexpr static uint GB(const T x, const uint8_t s, const uint8_t n)
33 {
34 return (x >> s) & (((T)1U << n) - 1);
35 }
36
57 template <typename T, typename U>
58 constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
59 {
60 x &= (T)(~((((T)1U << n) - 1) << s));
61 x |= (T)(d << s);
62 return x;
63 }
64
82 template <typename T, typename U>
83 constexpr T AB(T &x, const uint8_t s, const uint8_t n, const U i)
84 {
85 const T mask = ((((T)1U << n) - 1) << s);
86 x = (T)((x & ~mask) | ((x + (i << s)) & mask));
87 return x;
88 }
89
102 template <typename T>
103 debug_inline constexpr bool HasBit(const T x, const uint8_t y)
104 {
105 return (x & ((T)1U << y)) != 0;
106 }
107
120 template <typename T>
121 constexpr T SetBit(T &x, const uint8_t y)
122 {
123 return x = (T)(x | ((T)1U << y));
124 }
125
136 #define SETBITS(x, y) ((x) |= (y))
137
150 template <typename T>
151 constexpr T ClrBit(T &x, const uint8_t y)
152 {
153 return x = (T)(x & ~((T)1U << y));
154 }
155
166 #define CLRBITS(x, y) ((x) &= ~(y))
167
180 template <typename T>
181 constexpr T ToggleBit(T &x, const uint8_t y)
182 {
183 return x = (T)(x ^ ((T)1U << y));
184 }
185
193 template <typename T>
194 constexpr uint8_t FindFirstBit(T x)
195 {
196 if (x == 0) return 0;
197
198 if constexpr (std::is_enum_v<T>) {
199 return std::countr_zero<std::underlying_type_t<T>>(x);
200 } else {
201 return std::countr_zero(x);
202 }
203 }
204
212 template <typename T>
213 constexpr uint8_t FindLastBit(T x)
214 {
215 if (x == 0) return 0;
216
217 return std::numeric_limits<T>::digits - std::countl_zero(x) - 1;
218 }
219
230 template <typename T>
231 constexpr T KillFirstBit(T value)
232 {
233 return value &= (T)(value - 1);
234 }
235
242 template <typename T>
243 constexpr uint CountBits(T value)
244 {
245 if constexpr (std::is_enum_v<T>) {
246 return std::popcount<std::underlying_type_t<T>>(value);
247 } else {
248 return std::popcount(value);
249 }
250 }
251
258 template <typename T>
259 constexpr bool HasExactlyOneBit(T value)
260 {
261 return value != 0 && (value & (value - 1)) == 0;
262 }
263
270 template <typename T>
271 constexpr bool HasAtMostOneBit(T value)
272 {
273 return (value & (value - 1)) == 0;
274 }
275
281 template <typename Tbitpos = uint, typename Tbitset = uint>
282 struct SetBitIterator {
283 struct Iterator {
284 typedef Tbitpos value_type;
285 typedef value_type *pointer;
286 typedef value_type &reference;
287 typedef size_t difference_type;
288 typedef std::forward_iterator_tag iterator_category;
289
290 explicit Iterator(Tbitset bitset) : bitset(bitset), bitpos(static_cast<Tbitpos>(0))
291 {
292 this->Validate();
293 }
294
295 bool operator==(const Iterator &other) const
296 {
297 return this->bitset == other.bitset;
298 }
299 bool operator!=(const Iterator &other) const { return !(*this == other); }
300 Tbitpos operator*() const { return this->bitpos; }
301 Iterator & operator++() { this->Next(); this->Validate(); return *this; }
302
303 private:
304 Tbitset bitset;
305 Tbitpos bitpos;
306 void Validate()
307 {
308 if (this->bitset != 0) {
309 typename std::make_unsigned<Tbitset>::type unsigned_value = this->bitset;
310 this->bitpos = static_cast<Tbitpos>(FindFirstBit(unsigned_value));
311 }
312 }
313 void Next()
314 {
315 this->bitset = KillFirstBit(this->bitset);
316 }
317 };
318
319 SetBitIterator(Tbitset bitset) : bitset(bitset) {}
320 Iterator begin() { return Iterator(this->bitset); }
321 Iterator end() { return Iterator(static_cast<Tbitset>(0)); }
322 bool empty() { return this->begin() == this->end(); }
323
324 private:
325 Tbitset bitset;
326 };
327
328 #if defined(__APPLE__)
329 /* Make endian swapping use Apple's macros to increase speed
330 * (since it will use hardware swapping if available).
331 * Even though they should return uint16_t and uint32_t, we get
332 * warnings if we don't cast those (why?) */
333 # define BSWAP32(x) (static_cast<uint32_t>(CFSwapInt32(x)))
334 # define BSWAP16(x) (static_cast<uint16_t>(CFSwapInt16(x)))
335 #elif defined(_MSC_VER)
336 /* MSVC has intrinsics for swapping, resulting in faster code */
337 # define BSWAP32(x) (_byteswap_ulong(x))
338 # define BSWAP16(x) (_byteswap_ushort(x))
339 #else
340
345 static inline uint32_t BSWAP32(uint32_t x)
346 {
347 #if !defined(__ICC) && defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && __GNUC_MINOR__ >= 3))
348 /* GCC >= 4.3 provides a builtin, resulting in faster code */
349 return static_cast<uint32_t>(__builtin_bswap32(static_cast<int32_t>(x)));
350 #else
351 return ((x >> 24) & 0xFF) | ((x >> 8) & 0xFF00) | ((x << 8) & 0xFF0000) | ((x << 24) & 0xFF000000);
352 #endif /* defined(__GNUC__) */
353 }
354
360 static inline uint16_t BSWAP16(uint16_t x)
361 {
362 return (x >> 8) | (x << 8);
363 }
364 #endif /* __APPLE__ */
365
366 #endif /* BITMATH_FUNC_HPP */
SetBit
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
Definition: bitmath_func.hpp:121
GB
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
FindLastBit
constexpr uint8_t FindLastBit(T x)
Search the last set bit in a value.
Definition: bitmath_func.hpp:213
HasExactlyOneBit
constexpr bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
Definition: bitmath_func.hpp:259
KillFirstBit
constexpr T KillFirstBit(T value)
Clear the first bit in an integer.
Definition: bitmath_func.hpp:231
BSWAP32
static uint32_t BSWAP32(uint32_t x)
Perform a 32 bits endianness bitswap on x.
Definition: bitmath_func.hpp:345
SetBitIterator
Iterable ensemble of each set bit in a value.
Definition: bitmath_func.hpp:282
AB
constexpr T AB(T &x, const uint8_t s, const uint8_t n, const U i)
Add i to n bits of x starting at bit s.
Definition: bitmath_func.hpp:83
SetBitIterator::Iterator
Definition: bitmath_func.hpp:283
CountBits
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
Definition: bitmath_func.hpp:243
BSWAP16
static uint16_t BSWAP16(uint16_t x)
Perform a 16 bits endianness bitswap on x.
Definition: bitmath_func.hpp:360
HasAtMostOneBit
constexpr bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
Definition: bitmath_func.hpp:271
SB
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
Definition: bitmath_func.hpp:58
ClrBit
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Definition: bitmath_func.hpp:151
ToggleBit
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
Definition: bitmath_func.hpp:181
FindFirstBit
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
Definition: bitmath_func.hpp:194
HasBit
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition: bitmath_func.hpp:103