एक पूर्णांक के को खोजने के लिए de Bruijn अनुक्रम का उपयोग करना


11

शॉन एंडरसन प्रकाशित बिट हैक्स twiddling एरिक कोल एल्गोरिथ्म युक्त खोजने के लिए एक के -बिट पूर्णांक में गुणा और साथ देखने आपरेशनों।लॉग2vएनvहे(एलजी(एन))

एल्गोरिथ्म डी ब्रूजन अनुक्रम से एक "जादू" संख्या पर निर्भर करता है। क्या कोई यहां इस्तेमाल किए गए अनुक्रम के मौलिक गणित गुणों की व्याख्या कर सकता है?

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 से आता है । आकार का एक डी Brujn अनुक्रम आकार के सभी बिट श्रृंखला का प्रतिनिधित्व करने के लिए एक रास्ता है बहुत संक्षेप में: प्रत्येक संभव स्ट्रिंग एक सन्निहित परिणाम को के रूप में ठीक एक बार दिखाई देता है। इसलिए यदि आप बिट्स द्वारा de Bruijn अनुक्रम को स्थानांतरित करते हैं और अंतिम बिट्स को पढ़ते हैं , तो आपके पास लिए एक विशिष्ट पहचानकर्ता है । 2kkn2kkn
साशो निकोलेव

1
वैसे यह केवल गणना करता है ; और जैसा कि लिखा गया है यह केवल 32-बिट पूर्णांक के लिए काम करता है। लॉग2v
सैशो निकोलेव

1
@ साशो जवाब में बदलो?
युवल फिल्मस

@SashoNikolov धन्यवाद, सवाल के लिए एक छत समारोह जोड़ा गया
यूरी बेडा

जवाबों:


9

पहले ध्यान दें कि यह एल्गोरिथ्म केवल गणना करता है , और जैसा कि कोड लिखा गया है, यह केवल बिट शब्द में फिट लिए काम करता है।लॉग2vv32

पहली बार दिखाई देने वाली शिफ्ट्स और or-s के अनुक्रम में के अग्रणी 1-बिट को सभी तरह से कम से कम महत्वपूर्ण बिट तक प्रचारित करने का कार्य है । संख्यात्मक रूप से, यह आपको ।v2लॉग2v-1

दिलचस्प हिस्सा डी ब्रूजन ट्रिक है, जो लीसरसन, प्रोकोप और रान्डेल के इस पत्र से आता है (जाहिर है एमआईटी के प्रोफेसर बिट्स हैक करने में समय बिताते हैं :))। डी ब्रूजन अनुक्रमों के बारे में आपको जो जानने की जरूरत है, वह यह है कि वे किसी दिए गए लंबाई के सभी संभव अनुक्रमों का प्रतिनिधित्व करते हैं जो कि यथासंभव संकुचित है। संक्षेप में, वर्णमाला के ऊपर एक डी Brujn अनुक्रम एक द्विआधारी स्ट्रिंग है लंबाई के ऐसी है कि प्रत्येक लंबाई बाइनरी स्ट्रिंग एक सन्निहित-स्ट्रिंग के रूप में ठीक एक बार दिखाई देता है (लपेट अनुमति दी है)। इसका कारण यह उपयोगी है कि यदि आपके पास एक संख्या जिसका बिट प्रतिनिधित्व एक डी ब्रूजन अनुक्रम ( साथ गद्देदार) है{0,1}रों2एक्सशून्य), तो 2 के शीर्ष बिट्स विशिष्ट रूप से पहचानता (जब तक )।2मैंएक्समैंमैं<


3
ध्यान दें कि आप इस तरह से किसी भी de Bruijn अनुक्रम का उपयोग कर सकते गणना करने के लिए दिए गए 2 मैं । हालांकि, अगर आप डी Bruijn अनुक्रम एक मनमाना उपयोग नहीं कर सकते गणना करने के लिए मैं दिए गए 2 मैं - 1 । यहाँ 0x07C4ACDD = 00000111110001001010110011011101 कुछ अतिरिक्त गुणों के साथ एक डे ब्रूजन अनुक्रम प्रतीत होता है, जिसके लिए अतिरिक्त - 1 इस दृष्टिकोण को बर्बाद नहीं करता है। मैं2मैंमैं2i11
जुका सुओमेला

धन्यवाद @JukkaSuomela, मैं उस बारे में थोड़ा उलझन में था। मुझे लगता है कि आप हमेशा केवल 1 से जोड़ सकते हैं । v
साशो निकोलोव

5

कुछ टिप्पणियाँ (वास्तव में उत्तर नहीं)। 32-बिट पूर्णांक को निम्न प्रकार से वर्गीकृत करते हैं:c

  • टाइप X: (बाइनरी स्ट्रिंग के रूप में) डी ब्रूजन अनुक्रम है (सभी घुमावों के लिए, बिट्स [27,31] अलग हैं)। एक उदाहरण:c

    11111011100110101100010100100000
    
  • टाइप Y: बिट्स [27,31] के के लिए अलग हैं मैं = 0 , 1 , , 31 । यह वही है जो Leiserson et al। का उपयोग करता है। उदाहरण:2ici=0,1,...,31

    00000100011001010011101011011111
    00001111101110011010110001010010
    
  • प्रकार जेड: के टुकड़े [27,31] के लिए अलग हैं मैं = 0 , 1 , , 31 । यह वही है जो हमें मूल प्रश्न में चाहिए। उदाहरण:(2i+11)ci=0,1,..,31

    00000111110001001010110011011101  (07C4ACDD)
    10000111110001001010110011011101
    01111000001110110101001100100011
    11111000001110110101001100100011
    

त्वरित प्रयोगों के आधार पर कुछ अवलोकन (मुझे आशा है कि मुझे ये अधिकार मिले):

  1. प्रकार X के 65536 पूर्णांक हैं।

  2. टाइप X + Y के 4096 पूर्णांक हैं। ये ठीक प्रकार के X के पूर्णांक हैं जो क्रम से शुरू होते हैं '0000 ...'

    • अंतर्ज्ञान: अग्रणी शून्य के साथ, रोटेशन = स्थानांतरण?
  3. टाइप X + Y + Z के 256 पूर्णांक हैं। ये ठीक प्रकार के X के पूर्णांक हैं जो क्रम से शुरू होते हैं '0000011111 ...'

    • सहज बोध: ??
  4. प्रकार Y के सभी पूर्णांक प्रकार X के भी हैं।

  5. हालाँकि, Z के 768 पूर्णांक भी हैं जो न तो टाइप X के हैं और न ही Y के प्रकार। ये '1000011111 ...', '0111100000 ...', या '1111100000 ...' से शुरू होते हैं।


1
यह एकमात्र उत्तर है जो 2 ^ n-1 कार्यों के कारण De Bruijn के गुणन को 2 ^ n के विपरीत बताता है, जो कि केवल एक बदलाव है। मुझे अच्छा लगेगा अगर कोई # 3 के ऊपर "अंतर्ज्ञान" पर विस्तार कर सकता है। एरिक कोल इसके साथ कैसे आया? परीक्षण त्रुटि विधि? या जब आप 2 ^ n-1 से गुणा करते हैं तो वास्तव में बिट्स का क्या होता है, इसकी कुछ समझ?
फ़ार्मबॉस

1
  • यह निरंतर कहाँ से आता है?

उद्धरण: "10 दिसंबर, 2009 को, मार्क डिकिंसन ने 2 के शक्ति के बजाय 2 की अगली शक्ति की तुलना में एक राउंड तक की आवश्यकता होने पर एक जोड़े के संचालन को बंद कर दिया।" [Graphics.stanford.edu/~seander/bithacks.html]

यह कण कण निरंतर द्विआधारी वर्णमाला के साथ लेकिन एक अतिरिक्त संपत्ति के साथ एक डी ब्रूजन अनुक्रम है। मैं इसे 'मार्क डिकिंसन प्रॉपर्टी' कहने जा रहा हूं क्योंकि मूल एल्गोरिथम को इन विशेष डीबी दृश्यों के बिना लागू किया जा सकता है। 2 अतिरिक्त कार्यों को जोड़कर हम किसी भी साधारण डीबी अनुक्रम का उपयोग कर सकते हैं। ऑपरेशन: v ^ = (v >> 1); // सीपीआर को छोड़कर सभी बिट्स को कैस्केडिंग या शिफ्ट के बाद सेट करें।

  • परिणाम (जानवर)

Seq.Type | नहीं नहीं। DBSeq। के साथ | बिना रोटेशन के | साथ डिकिन्सन संपत्ति
बी (2, 3) | 256 | 16 | 2 | 1
बी (2, 4) | 64Ki | 256 | 16 | 4
बी (2, 5) | 04 जी | 64Ki | 02Ki | 256
बी (2, 6) | 16 ईई | 04 जी | 64Mi | ??

  • विशेष संपत्ति

0एक्स7सी4सीडीडी *21(आधुनिक232)321यहाँ छवि विवरण दर्ज करें21

  • डिकिन्सन प्रॉपर्टी के साथ लेक्सिकोग्राफिक रूप से सबसे छोटा बाइनरी डे ब्रूजन अनुक्रम

    [B (2,3): 0x1D] [B (2,4): 0x0F2D] [B (2,5): 0x7C4ACDD] [B (2,6): स्टिल सर्चिंग]

यदि आप उन्हें या कुछ इसी तरह का उत्पादन करने के लिए उन्हें या प्रमेय का वर्णन करने के लिए एक सुरुचिपूर्ण गणितीय सूत्र की उम्मीद कर रहे थे, तो मुझे लगता है कि इसके लिए संख्या सिद्धांत और संभवतः अन्य क्षेत्रों में गहन अंतर्दृष्टि की आवश्यकता होगी जो मेरे कौशल से परे हैं। अगर मैं जहां एक जंगली अनुमान बनाने के लिए मैं शर्त लगा सकता हूं कि वे सेल्युलर ऑटोमेटा द्वारा उत्पादित किए जा सकते हैं। यह एक उत्तर क्यों नहीं है? एक कठोर आधार पर लेकिन यह समझने का प्रयास करें कि यह क्यों काम करता है और यह ठीक से काम क्यों करता है, इसलिए आप इसे आत्मविश्वास के साथ उपयोग कर सकते हैं।

PS मैंने LUT निर्माण को कवर नहीं किया, जो कि एल्गोरिदम के कार्य सिद्धांतों को समझने पर आसानी से घटाया जाता है।


अंत में पाया गया: बी (2,6) 0x3f08a4c6acb9dbd - 'डिकिंसन प्रॉपर्टी' के साथ 64 बिट डे ब्रूजन अनुक्रम। मुझे कम से कम 122K ऐसे सीक्वेंस मिले हैं।
फ्रांज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.