見つけるためにデBruijnグラフシーケンスを使用


11

ショーン・アンダーソンは、公開されたビットハッキングいじる見つけるために、エリック・コールのアルゴリズムを含むのビットの整数でのルックアップ乗算として動作を制御します。N V O LG Nをlog2vNvO(lg(N))

このアルゴリズムは、De Bruijnシーケンスの「マジック」番号に依存しています。誰かがここで使用されているシーケンスの基本的な数学特性を説明できますか?

uint32_t v; // find the log base 2 of 32-bit v
int r;      // result goes here

static const int MultiplyDeBruijnBitPosition[32] = 
{
  0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
  8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};

v |= v >> 1; // first round down to one less than a power of 2 
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;

r = MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];

2
このアイデアは、この論文supertech.csail.mit.edu/papers/debruijn.pdfから来ています。サイズのde Brujnシーケンスは、サイズすべてのビット文字列を非常に簡潔に表現する方法です。可能な文字列はそれぞれ、連続したサブシーケンスとして1回だけ現れます。したがって、de Bruijnシーケンスをビットだけシフトし、最後のビットを読み取ると、一意の識別子が得られます。 K N 2 K K N2kkn2kkn
サショニコロフ2013

1
ちなみに、これはのみを計算します。書かれているように、32ビット整数でのみ機能します。log2v
サショニコロフ2013

1
@Sasho答えになりますか?
ユヴァルフィルマス

@SashoNikolovありがとう、質問に天井関数を追加
Yury Bayda

回答:


9

最初に、このアルゴリズムはのみを計算し、コードが記述されているため、ビットワードに適合するでのみ機能することに注意してください。V 32log2vv32

最初に現れるシフトとor-sのシーケンスには、先頭の1ビットを最下位ビットまで伝播する機能があります。数値的には、これによります。2 ログイン2 V - 1v2log2v1

おもしろい部分は、Leiserson、Prokop、Randallのこの論文に由来するde Bruijnのトリックです(明らかにMIT教授はビットハックに時間を費やしています:))。de Bruijnシーケンスについて知っておく必要があるのは、それらが可能な限り圧縮された方法で与えられた長さのすべての可能なシーケンスを表すということです。正確には、アルファベット上のde Brujnシーケンスは、長さバイナリ文字列であり、各長さバイナリ文字列は、連続した部分文字列として1回だけ現れます(ラップアラウンドが許可されます)。これが役立つ理由は、ビット表現がde Bruijnシーケンス(パディング)である数値がある場合2 K K X K K 2 I X 、I 、I < K{0,1}s2kkXk0)、の上位ビットは一意に識別します(限り)。k2iXii<k


3
i2ii2i11

v

5

c

  • c

    11111011100110101100010100100000
    
  • 2ici=0,1,...,31

    00000100011001010011101011011111
    00001111101110011010110001010010
    
  • (2i+11)ci=0,1,...,31

    00000111110001001010110011011101  (07C4ACDD)
    10000111110001001010110011011101
    01111000001110110101001100100011
    11111000001110110101001100100011
    

簡単な実験に基づいたいくつかの観察(これらが正しいことを願っています):

  1. X型の整数は65536個あります。

  2. タイプX + Yの整数は4096個あります。これらは、シーケンス '0000 ...'で始まるタイプXの整数です。

    • 直感:先行ゼロで、回転=シフト?
  3. タイプX + Y + Zの256個の整数があります。これらは、シーケンス '0000011111 ...'で始まるタイプXの整数です。

    • 直感:??
  4. タイプYのすべての整数もタイプXです。

  5. ただし、タイプXでもタイプYでもないタイプZの768個の整数もあります。これらは「1000011111 ...」、「0111100000 ...」、または「1111100000 ...」で始まります。


1
これは、De Bruijnと2 ^ n-1の乗算が機能する理由を扱う唯一の答えです。2^ nは単なるシフトです。誰かが上記の#3の「直感」を拡張できれば、それが大好きです。エリック・コールはどうやってこれを思いついたのですか?試行錯誤?または、2 ^ n-1で乗算するとビットに実際に何が起こるかを理解していますか?
FarmerBob 14年

1
  • この定数はどこから来たのですか?

引用:「2009年12月10日に、Mark Dickinsonは、vを2のべき乗ではなく、次の2のべき乗よりも小さい1に切り上げることを要求することにより、いくつかの操作を削減しました。[graphics.stanford.edu/~seander/bithacks.html]

この特定の定数は、バイナリアルファベットを持つDe Bruijnシーケンスですが、追加のプロパティがあります。これらの特別なDBシーケンスなしで元のアルゴリズムを実装できるため、「Marc Dickinsonプロパティ」と呼びます。2つの追加操作を追加することにより、通常のDBシーケンスを使用できます。操作:v ^ =(v >> 1); //カスケードまたはシフト後に設定されたMSBを除くすべてのビットをclrします。

  • 結果(bruteforce)

シーケンスタイプ| 整数| いいえ、DBSeq。と| 回転なし| ディキンソンプロパティ
B(2、3)| 256 | 16 | 2 | 1
B(2、4)| 64Ki | 256 | 16 | 4
B(2、5)| 04Gi | 64Ki | 02Ki | 256
B(2、6 )| 16Ei | 04Gi | 64Mi | ?

  • 特別なプロパティ

0x7C4ACDD 2k1(mod232)2 K 132k1ここに画像の説明を入力してください2k1

  • ディキンソン特性を持つ辞書的に最小のバイナリde Bruijnシーケンス

    [B(2,3):0x1D] [B(2,4):0x0F2D] [B(2,5):0x7C4ACDD] [B(2,6):まだ検索中]

それらを記述するためのエレガントな数式やそれらを生成するための定理または類似のものを望んでいた場合、これには数論やおそらく私のスキルセットを超えた他の分野に対する深い洞察が必要だと思います。私がどこでワイルドな推測をするかは、セルオートマトンによって生成される可能性があります。これはなぜ答えではないのですか?厳密な基盤に基づいていますが、なぜ機能するのか、なぜ適切に機能するのかを直感的に理解しようとするため、自信を持って使用できます。

PS LUTの構築については説明しませんでしたが、アルゴリズムの動作原理を理解していれば簡単に推測できます。


最後に見つかったもの:B(2,6)0x3f08a4c6acb9dbd-'dickinson property'を持つ64ビットde bruijnシーケンス。私は少なくとも122Kのそのようなシーケンスを見つけました。
FranG
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.