このアルゴリズムが 32 ビット システムで MSB を LSB に、または LSB を MSB に変換する方法を説明してもらえますか?
unsigned char b = x;
b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
コード内で 16 進数の値が LU または U だけで終わるのを見たことがありますが、これはどういう意味ですか?
ありがとう!
b を 8 ビット値として表示しますabcdefgh
。これらの文字はそれぞれ 1 ビット (0 または 1) でありa
、最上位ビットと最下位ビットがありh
ます。次に、各操作がそれらのビットに対して何をするかを見てください。
b * 0x0802LU = 00000abcdefgh00abcdefgh0
b * 0x0802LU & 0x22110LU = 000000b000f0000a000e0000
b * 0x8020LU = 0abcdefgh00abcdefgh00000
b * 0x8020LU & 0x88440LU = 0000d000h0000c000g000000
((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU))
= 0000d0b0h0f00c0a0g0e0000
したがって、この時点で、ビットがシャッフルされて分散されます。
(....) * 0x10101LU = d0b0h0f00c0a0g0e0000
+ d0b0h0f00c0a0g0e000000000000
+ d0b0h0f00c0a0g0e00000000000000000000
= d0b0f0f0dcbahgfedcbahgfe0c0a0g0e0000
(...) * 0x10101LU >> 16 = d0b0f0f0dcbahgfedcba
b = hgfedcba
乗算は、シフト/加算/加算 (定数に設定された 3 ビット) と同等であり、ビットを最終的な位置に並べます。次に、最終的なシフトと 8 ビットへの削減により、最終的なビット反転結果が得られます。
おそらく、achar
は 8 ビットなのでunsigned char b = x
、x の下位 8 ビットを取ります。
0x22110 のマスクは、ビット 4、8、13、および 17 (最下位ビットは 0 から数えます) を抽出します。したがって、0x0802 による乗算では、それらのビットに何を配置するかのみを気にします。0x802 では、ビット 1 と 11 がオンになっているため、この乗算では 8 ビットのコピーがb
ビット 1 から 8 に配置され、別のコピーがビット 11 から 18 に配置されます。オーバーラップがないため、オーバーラップするビットを追加しても影響はありません。より一般的な乗算で。
この製品から、次のビットを取得します。
b
。(コピーのビット 4 はビット 1 から始まるため、ビット 4–1 = の 3 b
)b
。(8–1 = 7.)b
。(13–11 = 2.)b
。(17–11 = 6.)同様に、0x88440 によるマスクは、ビット 6、10、15、および 19 を抽出します。0x8020 による乗算はb
、ビット 5 から 12 に のコピーを配置し、ビット 15 から 22 に別のコピーを配置します。この積から、これらのビットを取得します。
b
。b
。b
。b
。次に、それらを OR して、以下を生成します。
b
。b
。b
。b
。b
。b
。b
。b
。この結果を と呼びt
ます。
これに 0x10101 を掛け、右に 16 シフトし、 に代入しb
ます。代入は に変換されるunsigned char
ため、下位 8 ビットのみが保持されます。シフト後の下位 8 ビットは、シフト前のビット 24 ~ 31 です。したがって、積のビット 24 から 31 だけを気にします。
乗数 0x10101 には、ビット 0、8、および 16 が設定されています。したがって、結果のビット 24 は、 のビット 24、16、および 8 の合計に、t
他の場所からのキャリーを加えたものです。ただし、キャリーはありませんt
。乗数のビットのように、設定されたビットが 8 離れていないことに注意してください。したがって、製品内の同じビットに直接寄与するものはありません。積の各ビットは、 の最大 1 ビットの結果ですt
。それがどのビットかを把握するだけです。
ビット 24 は、 のビット 8、16、または 24 から取得する必要がありますt
。ビット 8 のみ設定可能で、 からビット 7 ですb
。この方法ですべてのビットを推測します。
t
ではビット 7 ですb
。t
あり、 ではビット 6 ですb
。t
あり、 ではビット 5 ですb
。t
あり、 ではビット 4 ですb
。t
ではビット 3 ですb
。t
あり、これは のビット 2 ですb
。t
ではビット 1 ですb
。t
あり、 ではビット 0 ですb
。したがって、積のビット 24 ~ 31 は のビット 7 ~ 0 でb
あるため、最終的に生成される 8 ビットは のビット 7 ~ 0 ですb
。
2番目の質問に答えるにu
は、16進定数を符号なしとして扱うことを意味し(より長い幅に拡張する必要がある場合)、それを.l
として扱うことを意味しlong
ます。
私はあなたの最初の質問に取り組んでいます。
乗算と 16 進数として見ると、このアルゴリズムが何をしているのかを視覚化するのは困難です。これを 2 進数に変換し、乗算を同等のシフト演算の合計に置き換えると、より明確になります。基本的に、それが行っていることは、バイトの一部をシフトしてマスクすることによって展開し、その後、その部分をその場で再構築する並列半加算器を実装することです。これはたまたま最初の場所と逆になります。
例えば、
b * 0x0802 = b << 11 | b << 1
b にいくつかの値を (バイナリで) 挿入し、それに従ってください。