このアルゴリズムが 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 にいくつかの値を (バイナリで) 挿入し、それに従ってください。