Jaka jest implementacja GCC (4.6+) __builtin_clz
? Czy odpowiada niektórym instrukcjom procesora w Intel x86_64 (AVX)
?Implementacja __builtin_clz
Odpowiedz
Należy przetłumaczyć na instrukcję Bit Scan Reverse i odjąć. BSR podaje indeks wiodącego 1, a następnie można go odjąć od rozmiaru słowa, aby uzyskać liczbę zer wiodących.
Edycja: jeśli twój procesor obsługuje LZCNT (Leading Zero Count), to prawdopodobnie zrobi to samo, ale nie wszystkie układy x86-64 mają tę instrukcję.
Tak, odpowiada instrukcji procesora BSR (skanowanie bitowe do tyłu).
Oto przykładowy kod, który może pomóc:
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
To źle. Odpowiada to bsr i odejmowaniu. Również przykład nie dodaje nic do roszczenia. A także, pytanie jest wyraźnie oznaczone jako C i wymieniono konkretny kompilator (gcc). Przykładowy kod nie działa. – hroptatyr
Tak i nie.
CLZ (zerem wiodącym zliczającym) i BSR (odwrócony bit-skan) są powiązane, ale różne. CLZ jest równy (wpisz bitową szerokość mniejszą) - BSR. CTZ (zliczanie zliczające zera), znane również jako FFS (pierwszy znaleziony zestaw) jest taki sam, jak z BSF (skanowanie w kierunku bitu do przodu).
Należy pamiętać, że wszystkie te parametry są nieokreślone przy zerowej pracy!
W odpowiedzi na twoje pytanie, przez większość czasu na x86 i x86_64, __builtin_clz generuje operację BSR odejmowaną od 31 (lub niezależnie od szerokości twojego typu), a __builting_ctz generuje operację BSF.
Jeśli chcesz wiedzieć, co generuje GIGA asembler, najlepiej wiedzieć, jak to sprawdzić. Flaga -S będzie miał wyświetlamy GCC asembler to wygenerowany dla danego wejścia:
gcc -S -o test.S test.c
Rozważmy:
unsigned int clz(unsigned int num) {
return __builtin_clz(num);
}
unsigned int ctz(unsigned int num) {
return __builtin_ctz(num);
}
On x 86 do CLZ gcc (-O2) generuje:
bsrl %edi, %eax
xorl $31, %eax
ret
i CTZ:
bsfl %edi, %eax
ret
Pamiętaj, że jeśli naprawdę chcesz bsr, a nie clz, musisz zrobić 31 - clz (dla 32-bitowych liczb całkowitych). To wyjaśnia XOR 31, jako x XOR 31 == 31 - x (to tożsamość jest prawdziwe tylko dla liczb od od 2^r - 1) Więc:
num = __builtin_clz(num)^31;
daje
bsrl %edi, %eax
ret
- 1. Implementacja IConvertible.GetTypeCode
- 2. Implementacja ACID
- 3. Implementacja Trie
- 4. Implementacja ToArgb()
- 5. Implementacja UnitOfWork
- 6. Implementacja DDD
- 7. Implementacja safe_ptr
- 8. Implementacja rur
- 9. Implementacja History.js
- 10. Kontekstowa implementacja
- 11. Implementacja parsera
- 12. implementacja sondowania na Linuksie kontra implementacja sondowania na solaris
- 13. Implementacja std :: is_function - dlaczego moja implementacja działa inaczej?
- 14. Implementacja maszyn stanu płynnego
- 15. implementacja ack nad UDP?
- 16. Implementacja SMPP w Pythonie
- 17. Implementacja protokołu Bittorrent
- 18. Implementacja animacji w UIButtonie
- 19. Mysql B + implementacja drzewa
- 20. junitowa implementacja wielu biegaczy
- 21. Implementacja ExpandoObject w Scali
- 22. Implementacja AMQP C++
- 23. Implementacja funkcji Hashing MySQL
- 24. Implementacja hashtable dla C
- 25. implementacja laplacian 3x3
- 26. Implementacja C# timeout
- 27. Domyślna implementacja ListView WłaścicielDod
- 28. Django post_save() implementacja sygnału
- 29. Implementacja Xamarin SQLite PCL
- 30. Implementacja RDSA na szałwinie
Czy spróbować? –
Nie wiem, ale jeśli jest dostępny, "LZCNT" wydaje się być prawdopodobnym kandydatem. (Patrz http://en.wikipedia.org/wiki/SSE4) – reuben