Дано:
- Битовая маска
a
(скажем,std::uint64_t
), которая содержит хотя бы один установленный (1
) бит. - Битовая маска селектора
b
, которая является подмножествомa
(т. е.a & b == b
) и имеет хотя бы один установленный бит.
Я хочу выбрать диапазоны смежных 1-битов в a
, которые перекрываются с битом в b
:
a = 0b1111001110001100;
b = 0b0000001010001000;
//c=0b0000001110001100
// XXXX YYY ZZ
Группа XXXX равна 0 в c
, потому что b & XXXX
ложно. Группа ZZ копируется, поскольку в b
установлен один из битов Z. Группа YYY также установлена в c
по той же причине. Обратите внимание, что b
может иметь несколько установленных битов в одной группе в a
.
Таким образом, для каждой непрерывной группы 1
s в a
установите все эти биты в c
, если b
имеет 1
в любой из этих позиций. Более сложный пример:
std::uint64_t a = 0b1101110110101;
std::uint64_t b = 0b0001010010001;
// desired c == 0b0001110110001
// contiguous groups ^^^ ^^ ^ that overlap with a 1 in b
assert(a & b == b); // b is a subset of a
std::uint64_t c = some_magic_operation(a, b);
assert(c == 0b0001110110001);
Существуют ли какие-либо битовые логические инструкции/внутренние элементы (MMX, SSE, AVX, BMI1/BMI2) или трюки с битовыми манипуляциями, которые позволяют мне эффективно вычислять c
из a
и b
? (т.е. без петель)?
ДОПОЛНИТЕЛЬНЫЙ:
Используя подсказку из ответа Дениса, я могу только представить алгоритм на основе цикла:
std::uint64_t a = 0b0110111001001101;
std::uint64_t b = 0b0100101000001101;
assert(a & b == b); // subset
std::cout << std::bitset< 16 >(a) << std::endl;
std::cout << std::bitset< 16 >(b) << std::endl;
std::uint64_t x = (a + b) & ~a;
std::uint64_t c = 0;
while ((x = (a & (x >> 1)))) { // length of longest 1-series times
c |= x;
}
std::cout << std::bitset< 16 >(c) << std::endl;
pext
/pdep
в качестве строительных блоков. Вам абсолютно необходим вывод в указанном вами формате? Ответ Дениса теряет информацию о том, насколько большой была каждая группа, но имеет 1 в результате для каждой подходящей группы. - person Peter Cordes   schedule 19.05.2016(a+b)&~a
). Если быb
имел только 1 в младшем бите группы, мы могли бы, возможно, сделать( (a+b)&~a ) - b
, чтобы заимствование превратило группы обратно в все 1, остановившись на 1 бите из выражения Дениса. Есть ли шанс, что уb
будет такое дополнительное условие? - person Peter Cordes   schedule 19.05.2016