Skip to content

Instantly share code, notes, and snippets.

@Eisenwave
Created May 5, 2020 18:33
Show Gist options
  • Save Eisenwave/7882185ff4d4ea42ea5c45af9fb4fd08 to your computer and use it in GitHub Desktop.
Save Eisenwave/7882185ff4d4ea42ea5c45af9fb4fd08 to your computer and use it in GitHub Desktop.
Functions for interleaving two or three numbers bitwise.
#ifndef UTIL_BITS_HPP
#define UTIL_BITS_HPP
#include <cstddef>
#include <cstdint>
#include <limits>
constexpr uint64_t ileave2(uint32_t x, uint32_t y)
{
constexpr uint64_t MASKS_2[] = {
0x5555'5555'5555'5555,
0x3333'3333'3333'3333,
0x0F0F'0F0F'0F0F'0F0F,
0x00FF'00FF'00FF'00FF,
0x0000'FFFF'0000'FFFF
};
uint64_t result = 0;
uint32_t *nums[] = {&x, &y};
for (size_t i = 0; i < 2; ++i) {
uint64_t n = *nums[i];
for (size_t i = 4; i != std::numeric_limits<size_t>::max(); --i) {
n |= n << (1 << i);
n &= MASKS_2[i];
}
result |= n << (1 - i);
}
return result;
}
static_assert(ileave2(0b1111'1111, 0) == 0b1010'1010'1010'1010);
static_assert(ileave2(0, 0b1'1111'1111) == 0b01'0101'0101'0101'0101);
static_assert(ileave2(0, 0xffff'ffff) == 0x5555'5555'5555'5555);
static_assert(ileave2(0, ileave2(0, 0b11)) == 0b10001);
constexpr uint64_t ileave3(uint32_t x, uint32_t y, uint32_t z)
{
constexpr size_t numInputs = 3;
constexpr uint64_t MASKS_2[] = {
0x9249'2492'4924'9249,
0x30C3'0C30'C30C'30C3,
0xF00F'00F0'0F00'F00F,
0x00FF'0000'FF00'00FF,
0xFFFF'0000'0000'FFFF
};
uint64_t result = 0;
uint32_t *nums[] = {&x, &y, &z};
for (size_t i = 0; i < numInputs; ++i) {
uint64_t n = *nums[i];
for (size_t i = 4; i != std::numeric_limits<size_t>::max(); --i) {
const auto shift = (numInputs - 1) * (1 << i);
n |= n << shift;
n &= MASKS_2[i];
}
result |= n << (numInputs - i - 1);
}
return result;
}
static_assert(ileave3(0, 0, 0b1111) == 0b001001001001);
static_assert(ileave3(0b1111, 0, 0) == 0b100100100100);
#endif // UTIL_BITS_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment