2012-02-19 6 views
14

का कार्यान्वयन जीसीसी (4.6+) __builtin_clz का कार्यान्वयन क्या है? क्या यह इंटेल x86_64 (AVX) पर कुछ सीपीयू निर्देशों के अनुरूप है?__builtin_clz

+2

आप इसे की कोशिश की? –

+0

मुझे नहीं पता, लेकिन यदि यह उपलब्ध है, तो 'LZCNT' संभावित उम्मीदवार की तरह दिखता है। (Http://en.wikipedia.org/wiki/SSE4 देखें) – reuben

उत्तर

14

इसे Bit Scan Reverse निर्देश और एक घटाव में अनुवाद करना चाहिए। बीएसआर अग्रणी 1 की सूचकांक देता है, और फिर आप प्रमुख शून्यों की संख्या प्राप्त करने के लिए शब्द आकार से घटा सकते हैं।

संपादित करें: यदि आपका सीपीयू एलजेडसीएनटी (अग्रणी शून्य गणना) का समर्थन करता है, तो शायद यह चाल भी करेगा, लेकिन सभी x86-64 चिप्स में वह निर्देश नहीं है।

2

हां, यह सीपीयू निर्देश बीएसआर (बिट स्कैन रिवर्स) के अनुरूप है।

int a=20; //10100 

//trailing zeroes 
cout<<__builtin_ctz(a)<<endl; //gives 2 
cout<<__builtin_ctz(a<<4)<<endl; //gives 6 

//leading zeroes 
cout<<__builtin_clz(a)<<endl; //gives 27 
cout<<__builtin_clz(a>>4)<<endl; //gives 31 

cout<<__builtin_clz(0)<<endl; //gives 32 
+1

यह गलत है। यह बीएसआर और एक घटाव के अनुरूप है। इसके अलावा, उदाहरण दावे के लिए कुछ भी नहीं जोड़ता है। और यह भी, सवाल स्पष्ट रूप से टैग किया गया है सी और एक विशेष संकलक (जीसीसी) का उल्लेख किया गया है। उदाहरण कोड काम नहीं करेगा। – hroptatyr

11

हाँ, और कोई:

यहाँ है कि आप मदद कर सकते हैं एक नमूना कोड है।

सीएलजेड (गिनती अग्रणी शून्य) और बीएसआर (बिट-स्कैन रिवर्स) संबंधित हैं लेकिन अलग हैं। सीएलजेड बराबर है (टाइप बिट चौड़ाई कम एक) - बीएसआर। सीटीजेड (गिनती पिछला शून्य), जिसे एफएफएस (पहले सेट ढूंढें) के रूप में भी जाना जाता है, बीएसएफ (बिट-स्कैन फॉरवर्ड) के समान है।

ध्यान दें कि शून्य पर काम करते समय ये सभी अपरिभाषित हैं!

आपके प्रश्न के उत्तर में, अधिकांश समय x86 और x86_64 पर, __builtin_clz 31 से घटाए गए बीएसआर ऑपरेशन को उत्पन्न करता है (या जो भी आपकी प्रकार की चौड़ाई है), और __builting_ctz एक बीएसएफ ऑपरेशन उत्पन्न करता है।

यदि आप जानना चाहते हैं कि कौन सी असेंबलर जीसीसी उत्पन्न कर रहा है, तो जानने का सबसे अच्छा तरीका देखना है। एस झंडा जीसीसी उत्पादन कोडांतरक यह दिए गए इनपुट के लिए उत्पन्न हो जाती है:

जीसीसी एस -ओ test.S test.c

पर विचार करें:

unsigned int clz(unsigned int num) { 
    return __builtin_clz(num); 
} 

unsigned int ctz(unsigned int num) { 
    return __builtin_ctz(num); 
} 

पर CLZ जीसीसी के लिए 86 (-O2) उत्पन्न करता है:

bsrl %edi, %eax 
xorl $31, %eax 
ret 

और CTZ के लिए:

012,351,
bsfl %edi, %eax 
ret 

ध्यान दें कि यदि आप वास्तव में बीएसआर, और नहीं CLZ चाहते हैं, आप 31 करने की ज़रूरत है - CLZ (। 32-बिट पूर्णांकों के लिए) यह XOR 31 बताते एक्स XOR के रूप में, 31 == 31 - एक्स (इस पहचान 2 से^y के नंबरों के लिए सही है - 1) तो:

num = __builtin_clz(num)^31; 

पैदावार

bsrl %edi, %eax 
ret