サイズが N 文字のビットマスクがあり、これは静的にわかっています (つまり、コンパイル時に計算できますが、単一の定数ではないため、書き留めることはできません)。 「欲しい」ビット。そして、同じサイズの値がありますが、これは実行時にのみわかります。その値から「必要な」ビットを順番に新しい値の先頭に集めたいと思います。簡単にするために、必要なビット数が <= 32 であると仮定しましょう。
うまくいけば正しい動作をする、完全に最適化されていない参照コード:
template<int N, const char mask[N]>
unsigned gather_bits(const char* val)
{
unsigned result = 0;
char* result_p = (char*)&result;
int pos = 0;
for (int i = 0; i < N * CHAR_BIT; i++)
{
if (mask[i/CHAR_BIT] & (1 << (i % CHAR_BIT)))
{
if (val[i/CHAR_BIT] & (1 << (i % CHAR_BIT)))
{
if (pos < sizeof(unsigned) * CHAR_BIT)
{
result_p[pos/CHAR_BIT] |= 1 << (pos % CHAR_BIT);
}
else
{
abort();
}
}
pos += 1;
}
}
return result;
}
その定式化が実際にコンパイル時にマスクの内容へのアクセスを許可するかどうかはわかりませんが。しかし、いずれにせよ、それは使用可能です。おそらく、constexpr
関数または何かがより良いアイデアになるでしょう. 私はここで必要な C++ の魔法を探しているわけではありません (それは後で調べます)、アルゴリズムだけです。
わかりやすくするために、16 ビット値と虚数バイナリ表記を使用した入力/出力の例:
mask = 0b0011011100100110
val = 0b0101000101110011
--
wanted = 0b__01_001__1__01_ // retain only those bits which are set in the mask
result = 0b0000000001001101 // bring them to the front
^ gathered bits begin here
私の質問は次のとおりです。
これを行う最もパフォーマンスの高い方法は何ですか? (役立つハードウェアの説明はありますか?)
マスクと値の両方が に制限されている場合はどうなるでしょうか?つまり
unsigned
、無制限の char 配列ではなく、1 つの単語でしょうか? それでは、固定された短い一連の命令でそれを行うことができますか?