, и я заинтересован в преобразовании целого без знака, следуя приведенным выше правилам (т.е. 2-битные пары должны быть преобразованы в соответствии с правилами: 00-> 10, 01-> 01 и 10-> 01 ), так что я получаю 32-битное целое без знака int
Конечно, это можно сделать, но требуемая последовательность операций будет отличаться для каждого из 27 различных отображений из {0, 1, 2 } до {0, 1, 2}. Некоторые могут быть очень простыми, например, для трех константных отображений, но другие требуют более сложных выражений.
Не выполнив тщательного анализа, я склонен предположить, что отображения, которые не являются ни постоянными, ни перестановками, такие, которые представлены в примере, вероятно, имеют наибольшую минимальную сложность. Все они имеют общие характеристики c, которые два ключа соответствуют одному значению, в то время как другой ключ соответствует другому. Один из способов - не обязательно лучший - подойти к поиску выражения для такого отображения - это сосредоточиться сначала на достижении общего результата, когда два ключа отображаются на одно значение, а другой - на другое, а затем перейти к преобразованию результирующие значения к желаемым, если необходимо.
Для представленного примера, например,
0 -> 2
1 -> 1
2 -> 1
, можно (на основе ключа) ) используйте ((key & 2) >> 1) | ((key & 1) << 1)
для достижения этих предварительных результатов:
0 -> 0
1 -> 3
2 -> 3
, которые можно преобразовать в желаемый конечный результат, щелкнув бит старшего порядка с помощью операции исключающего или.
Обратите внимание, немного маскировки. Существуют и другие способы, которые можно использовать для сопоставления одного ключа, но в случае нескольких ключей, хранящихся в непрерывных битах одного и того же целого числа, необходимо соблюдать осторожность, чтобы не загрязнить вычисленные сопоставления данными из разных ключей.
В битовой векторной форме с 16 записями это будет
uint32_t keys = /*...*/;
uint32_t values = (((keys & 0xAAAAAAAAu) >> 1) | ((keys & 0x55555555u) << 1))
^ 0xAAAAAAAAu;
. У этого случая на пару меньше операций, чем у выражения в вашем другом ответе, но я не уверен, что это наименьшее возможное количество операций. На самом деле, если вы готовы принять арифметические c операции в дополнение к побитовым, то вы определенно можете сделать это с меньшим количеством операций:
uint32_t keys = /*...*/;
uint32_t values = 0xAAAAAAAAu
- (((keys & 0xAAAAAAAAu) >> 1) | (keys & 0x55555555u));
Конечно, в целом Различные операции не все имеют одинаковую стоимость, но целочисленные сложения и вычитания, а также побитовые И, ИЛИ и XOR имеют одинаковую стоимость в большинстве архитектур (см., например, * 1031). *).