Merge two bitmask with conflict resolving, with some required distance between any two set bits - c++

I have two integer values:
d_a = 6 and d_b = 3, so-called distance between set bits.
Masks created with appropriate distance look like below:
uint64_t a = 0x1041041041041041; // 0001 0000 0100 0001 0000 0100 0001 0000
// 0100 0001 0000 0100 0001 0000 0100 0001
uint64_t b = 0x9249249249249249; // 1001 0010 0100 1001 0010 0100 1001 0010
// 0100 1001 0010 0100 1001 0010 0100 1001
The goal is to have a target mask, which has bits set with d_b, but simultaneously takes into account bits set in the a mask (e.g. first set bit is shifted).
The second thing is that the distance in the target mask is not constant i.e. number of zeros between set bits in the target mask shall be equal to d_b or increased whenever between them is set bit in a
uint64_t target = 0x4488912224488912; // 0100 0100 1000 1000 1001 0001 0010 0010
// 0010 0100 0100 1000 1000 1001 0001 0010
The picture to visualize the problem:
The blue bar is a, yellow is b.
I would rather use bit manipulation intrinsics than bit-by-bit operations.
edit:
Actually, I have the following code, but I am looking for a solution with a fewer number of instructions.
void set_target_mask(int32_t d_a, int32_t d_b, int32_t n_bits_to_set, uint8_t* target)
{
constexpr int32_t n_bit_byte = std::numeric_limits<uint8_t>::digits;
int32_t null_cnt = -1;
int32_t n_set_bit = 0;
int32_t pos = 0;
while(n_set_bit != n_bits_to_set)
{
int32_t byte_idx = pos / n_bit_byte;
int32_t bit_idx = pos % n_bit_byte;
if(pos % d_a == 0)
{
pos++;
continue;
}
null_cnt++;
if(null_cnt % d_b == 0)
{
target[byte_idx] |= 1 << bit_idx;
n_set_bit++;
}
pos++;
}
}

If target is uint64_t, possible d_a and d_b can be converted into bit masks via look-up table. Like lut[6] == 0x2604D5C99A01041 from your question.
Look up tables can be initialized once per program run during initlalization, or in compile time using macro or constant expressions (constexpr).
To make d_b spread, skipping d_a bits, you can use pdep with inverted d_a:
uint64_t tmp = _pdep_u64(d_b_bits, ~d_a_bits);
Then you can convert n_bits_to_set to contiguous bits mask:
uint64_t n_bits = (1 << n_bits_to_set) - 1;
And spread them using pdep again:
uint64_t tmp = _pdep_u64(n_bits, tmp);
(See Intrinsic Guide about pdep. Note that pdep is slow on AMD before Zen3. It's fast on Intel CPUs and Zen3, but not Bulldozer-family or Zen1/Zen2)

Related

How to check if number of lines in a text file is power of 2?

I'm making a program that would simulate something like a March Madness tournament where 64 teams were to play against each other. I've used fstream to read in the teams from the file. The problem I've having is that I must make sure that there are at least a power-of-2 teams in the file at all times or it wouldn't run properly. How would I implement a function that checks if there is the power of 2 lines?
Check if there is exactly one bit set in the number of teams.
bool powerOfTwo = std::popcount(numberOfTeams) == 1;
A trick with binary numbers is that if n is a power of 2, or 0, then n & (n - 1) is 0. Otherwise it's not.
i.e.
bool isPowerOfTwo(int n) {
return (n & (n - 1)) == 0;
}
This works because:
Powers of 2 have a single 1 bit in binary and the rest of the bits are 0s.
To subtract 1 from a number in binary, you change the last 1 bit and all the bits after it.
If that was the only 1 bit in the entire number, then all the bits that didn't change were 0s. Otherwise they weren't all 0s.
Example:
0000 0000 0010 0000 (32)
& 0000 0000 0001 1111 (31)
= 0000 0000 0000 0000 (0) (so 32 is a power of 2)
0000 0000 0110 0100 (100)
& 0000 0000 0110 0011 (99)
= 0000 0000 0110 0000 (96) (so 100 is not a power of 2)

How can I concatenate 4 bytes to 8 in c++?

How can I concatenate 4 bytes to 8?
Example:
long var1 = 0x01011; //0001 0000 0001 0001
long var2 = 0x03034; //0011 0000 0011 0100
// MAGIC...
long result = 0x10113034; //0001 0000 0001 0001 0011 0000 0011 0100
Use shifts and sum to combine elements. In this case, you combine 2 4-byte ints into one 8-byte long long.
unsigned int a = 0x01020304;
unsigned int b = 0x0a0b0c0e;
unsigned long long c = (((unsigned long long)a) << 32) + b;
// c=0x010203040a0b0c0e
using ul = unsigned long;
long concat(long var1, long var2) {
ul result = (static_cast<ul>(var1)<<16) | static_cast<ul>(var2);
return static_cast<long>(result);
}
This function returns the result you want, I didn't test it extensively but intuitively it should work as sample cases.
The easiest way is probably:
By using binary operators:
unsigned long var1 = 0x1011; //0001 0000 0001 0001
unsigned long var2 = 0x3034; //0011 0000 0011 0100
unsigned long result = (var1 << 16) | var2; //Magic!: 0001 0000 0001 0001 0011 0000 0011 0100
By the way, I believe it's the fastest way of coding/computing it!
Tip: Use unsigned numbers for binary operations because it could give surprising results otherwise!

Casting two bytes to a 12 bit short value?

I have a buffer which consists of data in unsigned char and two bytes form a 12 Bit value.
I found out that my system is little endian. The first byte in the buffer gives me on the console numbers from 0 to 255. The second byte gives always low numbers between 1 and 8 (measured data, so higher values up to 4 bit would be possible too).
I tried to shift them together so that I get an ushort with a correct 12 bit number.
Sadly at the moment I am totally confused about the endianess and what I have to shift how far in which direction.
I tried e.g. this:
ushort value =0;
value= (ushort) firstByte << 8 | (ushort) secondByte << 4;
Sadly the value of value is quite often bigger than 12 bit.
Where is the mistake?
It depends on how the bits are packed within the two bytes exactly, but the solution for the most likely packing would be:
value = firstByte | (secondByte << 8);
This assumes that the second byte contains the 4 most significant bits (bits 8..11), while the first byte contains the 8 least significant bits (bits 0..7).
Note: the above solution assumes that firstByte and secondByte are sensible unsigned types (e.g. uint8_t). If they are not (e.g. if you have used char or some other possibly signed type), then you'll need to add some masking:
value = (firstByte & 0xff) | ((secondByte & 0xf) << 8);
I think the main issue may not be with the values you're shifting alone. If these values are greater than their representative bits, they'll create a large value unless "and'd" out.
picture the following
0000 0000 1001 0010 << 8 | 0000 0000 0000 1101 << 4
1001 0010 0000 0000 | 0000 0000 1101 0000
You should notice the first problem here. The first 4 'lowest' values are not being used, and it's using up 16 bits. you only wanted twelve. This should be modified like so:
(these are new numbers to demonstrate something else)
0000 1101 1001 0010 << 8 | 0000 0000 0000 1101
1101 1001 0010 0000 | (0000 0000 0000 1101 & 0000 0000 0000 1111)
This will create the following value:
1101 1001 0010 1101
here, you should note that the value is still greater than the 12 bits. If your numbers don't extend passed the original 8bit, 4 bit size ignore this. Otherwise, you have to use the 'and' operation on the bits to eliminate the left most 4 bits.
0000 1111 1111 1111 & 0000 1001 0010 1101
These values can be created using either 0bXX macros, the 2^bits - 1 pattern, as well as various other forms.

Shift instructions in Golang

The go spec says:
<< left shift integer << unsigned integer
What if the left side is type of uint8:
var x uint8 = 128
fmt.Println(x << 8) // it got 0, why ?
fmt.Println(int(x)<<8) // it got 32768, sure
Questions:
when x is uint8 type, why no compile error?
why x << 8 got result 0
For C/C++,
unsigned int a = 128;
printf("%d",a << 8); // result is 32768.
Could anyone explain? Thank you.
The left shift operator is going to shift the binary digits in the number to the left X number of places. This has the effect of adding X number of 0's to the right hand side the number A unit8 only holds 8 bits so when you have 128 your variable has
x = 1000 0000 == 128
x << 8
x= 1000 0000 0000 0000 == 32768
Since uint8 only holds 8 bits we tak the rightmost 8 bits which is
x = 0000 0000 == 0
The reason you get the right number with an int is an int has at least 16 bits worth of storage and most likely has 32 bits on your system. That is enough to store the entire result.
Because uint8 is an unsigned 8-bit integer type. That's what "u" stands for.
Because uint8(128) << 8 shifts the value, turning 1000 0000 into 0000 0000.
int(x) makes it 0000 0000 0000 0000 0000 0000 1000 0000 (on 32 bit systems, since int is architecture-dependant) and then the shift comes, making it 0000 0000 0000 0000 1000 0000 0000 0000, or 32768.

Convert bit sequence to uint32_t in c++

User specifies register (LFSR) length with integer as a parameter for a function, for example he enters number 5. I need to initialize this 5-bit length LFSR with all 1 bits (for length 5 it will be 11111) and get a seed mask in a format uint32_t - for 5-length register it will be 0x0001f.
What is the best way to get mask 0x0001f for 5 bit length register when a user enters only length of the register as an integer number 5?
To generate a mask of n bits (where n < 32):
uint32_t mask = (1U << n) - 1U;
Explanation: consider the example where n = 5:
1U << n = 1U << 5 = 0000 0000 0000 0000 0000 0000 0010 0000 = 0x20
then we subtract 1 and get:
0000 0000 0000 0000 0000 0000 0001 1111 = 0x1f
Another option is
std::uint32_t mask = ~(~0U << n);
Also you have to make sure unsigned int isn't less than 32 bits on your system, it may be better to write
std::uint32_t mask = ~(~(std::uint32_t)0 << n);