20 #ifndef ANTKEEPER_BIT_MATH_HPP
21 #define ANTKEEPER_BIT_MATH_HPP
44 constexpr
int count(T x) noexcept;
55 constexpr T
crossover(T a, T b,
int i) noexcept;
76 constexpr T
deposit(T x, T mask) noexcept;
104 constexpr T
expand(T x) noexcept;
114 constexpr T
extract(T x, T mask) noexcept;
124 constexpr T
flip(T x,
int i) noexcept;
133 template <
class T,
class U = T>
145 constexpr T
merge(T a, T b, T mask) noexcept;
154 constexpr T
parity(T x) noexcept;
175 std::uint16_t
swap16(std::uint16_t x) noexcept;
178 std::int16_t
swap16(std::int16_t x) noexcept;
181 std::uint32_t
swap32(std::uint32_t x) noexcept;
184 std::int32_t
swap32(std::int32_t x) noexcept;
187 std::uint64_t
swap64(std::uint64_t x) noexcept;
190 std::int64_t
swap64(std::int64_t x) noexcept;
195 x &= T(0x5555555555555555);
197 x = (x ^ (x >> 1)) & T(0x3333333333333333);
198 x = (x ^ (x >> 2)) & T(0x0f0f0f0f0f0f0f0f);
200 if constexpr(
sizeof(T) >= 2)
201 x = (x ^ (x >> 4)) & T(0x00ff00ff00ff00ff);
202 if constexpr(
sizeof(T) >= 4)
203 x = (x ^ (x >> 8)) & T(0x0000ffff0000ffff);
204 if constexpr(
sizeof(T) >= 8)
205 x = (x ^ (x >> 16)) & T(0x00000000ffffffff);
222 T mask = (T(1) << i) - 1;
223 return merge(b, a, mask);
233 merge ^= (mask ^ (mask - 1)) >> 1;
243 return interleave<T>(x, x >> (
sizeof(T) << 2));
249 x &= (1 << (
sizeof(T) << 2)) - 1;
251 if constexpr(
sizeof(T) >= 8)
252 x = (x ^ (x << 16)) & T(0x0000ffff0000ffff);
253 if constexpr(
sizeof(T) >= 4)
254 x = (x ^ (x << 8)) & T(0x00ff00ff00ff00ff);
255 if constexpr(
sizeof(T) >= 2)
256 x = (x ^ (x << 4)) & T(0x0f0f0f0f0f0f0f0f);
258 x = (x ^ (x << 2)) & T(0x3333333333333333);
259 x = (x ^ (x << 1)) & T(0x5555555555555555);
269 for (T i = 1; mask; i <<= 1)
272 result |= mask & -mask;
290 for (T i = 1; mask; i <<= 1)
292 if (x & mask & -mask)
301 inline constexpr T
flip(T x,
int i) noexcept
303 return x ^ (T(1) << i);
306 template <
class T,
class U>
309 return expand<U>(a) | (expand<U>(b) << 1);
313 inline constexpr T
merge(T a, T b, T mask) noexcept
315 return a ^ ((a ^ b) & mask);
321 if constexpr(
sizeof(T) >= 8)
323 if constexpr(
sizeof(T) >= 4)
325 if constexpr(
sizeof(T) >= 2)
330 return (0x6996 >> (x & 0xf)) & 1;
339 return odd | (even << (
sizeof(T) << 2));
345 return ((x & T(0xaaaaaaaaaaaaaaaa)) >> 1) | ((x & T(0x5555555555555555)) << 1);
348 std::uint16_t
swap16(std::uint16_t x) noexcept
350 return (x << 8) | (x >> 8);
353 std::int16_t
swap16(std::int16_t x) noexcept
355 return (x << 8) | ((x >> 8) & 0xFF);
358 std::uint32_t
swap32(std::uint32_t x) noexcept
360 x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
361 return (x << 16) | (x >> 16);
364 std::int32_t
swap32(std::int32_t x) noexcept
366 x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
367 return (x << 16) | ((x >> 16) & 0xFFFF);
370 std::uint64_t
swap64(std::uint64_t x) noexcept
372 x = ((x << 8) & 0xFF00FF00FF00FF00) | ((x >> 8) & 0x00FF00FF00FF00FF);
373 x = ((x << 16) & 0xFFFF0000FFFF0000) | ((x >> 16) & 0x0000FFFF0000FFFF);
374 return (x << 32) | (x >> 32);
377 std::int64_t
swap64(std::int64_t x) noexcept
379 x = ((x << 8) & 0xFF00FF00FF00FF00) | ((x >> 8) & 0x00FF00FF00FF00FF);
380 x = ((x << 16) & 0xFFFF0000FFFF0000) | ((x >> 16) & 0x0000FFFF0000FFFF);
381 return (x << 32) | ((x >> 32) & 0xFFFFFFFF);
constexpr T swap_adjacent(T x) noexcept
Swaps the each odd bit with its following even bit.
constexpr T compress(T x) noexcept
Compresses the even bits of a value into the lower half, then clears the upper half.
std::uint32_t swap32(std::uint32_t x) noexcept
Swaps the byte order of an unsigned 32-bit number.
constexpr T crossover(T a, T b, int i) noexcept
Performs a single-point crossover between two values.
constexpr T merge(T a, T b, T mask) noexcept
Merges the bits of two values using a bit mask.
constexpr T flip(T x, int i) noexcept
Flips a single bit in a value.
constexpr T segregate(T x) noexcept
Segregates the odd and even bits of a value.
constexpr U interleave(T a, T b) noexcept
Returns a value with even bits containing the first value's lower half, and odd bits containing the s...
constexpr T crossover_n(T a, T b, T mask) noexcept
Performs an n-point crossover between two values.
constexpr int difference(T x, T y) noexcept
Returns the number of differing bits between two values, known as Hamming distance.
std::uint16_t swap16(std::uint16_t x) noexcept
Swaps the byte order of an unsigned 16-bit number.
constexpr int count(T x) noexcept
Returns the number of set bits in a value, known as a population count or Hamming weight.
constexpr T desegregate(T x) noexcept
Interleaves bits of the lower and upper halves of a value.
constexpr T parity(T x) noexcept
Returns the parity of a value.
std::uint64_t swap64(std::uint64_t x) noexcept
Swaps the byte order of an unsigned 64-bit number.
constexpr T deposit(T x, T mask) noexcept
Reads bits from the least significant bits of a value and returns them in the positions marked by a m...
constexpr T expand(T x) noexcept
Moves bits from the lower half of a value to occupy all even bits, and clears all odd bits.
constexpr T extract(T x, T mask) noexcept
Reads bits from a value in the positions marked by a mask and returns them in the least significant b...