Hi CousinItt, thanks for your reply.
Interesting enough, the "any position" assumption seems not to hold. Positions above 32 don't work. Here's my test program. Did I something wrong? The document you referred to also mentions this limit for linsert.
Code: Select all
for (int index = -64; index < 64; index++)
{
unsigned long long data = 0;
data = linsert(data, 0xF, index, 4);
unsigned data1 = data >> 32;
printf("%d 0x%08x%08x\n", index, data1, data);
}
The output is this:
Code: Select all
-64 0x0000000000000000
... <all zeroes here>
-1 0x0000000000000000
0 0x000000000000000f
1 0x000000000000001e
2 0x000000000000003c
3 0x0000000000000078
4 0x00000000000000f0
5 0x00000000000001e0
6 0x00000000000003c0
7 0x0000000000000780
8 0x0000000000000f00
9 0x0000000000001e00
10 0x0000000000003c00
11 0x0000000000007800
12 0x000000000000f000
13 0x000000000001e000
14 0x000000000003c000
15 0x0000000000078000
16 0x00000000000f0000
17 0x00000000001e0000
18 0x00000000003c0000
19 0x0000000000780000
20 0x0000000000f00000
21 0x0000000001e00000
22 0x0000000003c00000
23 0x0000000007800000
24 0x000000000f000000
25 0x000000001e000000
26 0x000000003c000000
27 0x0000000078000000
28 0x00000000f0000000
29 0x00000001e0000000
30 0x00000003c0000000
31 0x0000000780000000
32 0x0000000f00000000
33 0x0000000000000000
... <all zeroes here>
63 0x0000000000000000
So, using this behaviour I could both read and write bits by a combination of linsert/lextract without if statements, and it is still faster by a factor of 1.5..2 compared to 2x32 bit value shifting with logical operations, but still much slower than if locations above 32 would be supported.
Code: Select all
static uint64_t data;
unsigned is_bit_set(unsigned bit_index)
{
return lextract(lextract(data, bit_index & 0x20, 32), bit_index & 0x1F, 1);
}
void set_bit(unsigned bit_index, unsigned value)
{
// using the fact that positions <0 and >32 are ignored
data = linsert(linsert(data, value, bit_index, 1),
linsert(data >> 32, value, bit_index - 32, 1),
32, 32);
}