Sean Anderson opublikował nieco hacków zawierających algorytm Erica Cole'a, aby znaleźć liczby całkowitej bit w operacjach z mnożeniem i wyszukiwaniem.N v O ( lg ( N ) )
Algorytm opiera się na „magicznej” liczbie z sekwencji De Bruijn. Czy ktoś może wyjaśnić podstawowe właściwości matematyczne zastosowanej tu sekwencji?
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];
nt.number-theory
comp-number-theory
Yury Bayda
źródło
źródło
Odpowiedzi:
Po pierwsze, ten algorytm oblicza tylko , a ponieważ kod jest zapisywany, działa tylko dla które mieszczą się w bitowym słowie.v 32⌈log2v⌉ v 32
Sekwencja przesunięć i-or, która pojawia się jako pierwsza, ma funkcję propagacji wiodącego 1-bitu aż do najmniej znaczącego bitu. Liczbowo daje to .2 ⌈ log 2 v ⌉ - 1v 2⌈log2v⌉−1
Interesującą częścią jest trik de Bruijn, który pochodzi z tego artykułu Leisersona, Prokopa i Randalla (najwyraźniej profesorowie MIT spędzają czas robiąc trochę hacków :)). To, co musisz wiedzieć o sekwencjach de Bruijna, to to, że reprezentują one wszystkie możliwe sekwencje o danej długości w sposób możliwie skompresowany. Dokładniej, de sekwencja Brujn na alfabet jest binarny ciąg długości tak, że każdy odcinek ciąg binarny pojawia się tylko raz w ciągłą fragmentu (technologia zawijania jest dostępna). Powodem tego jest to, że jeśli masz liczbę której bitową reprezentacją jest sekwencja de Bruijna (wypełnionas 2 k k X k k 2 i X i i < k{0,1} s 2k k X k zera), a następnie górne bitów jednoznacznie identyfikuje (o ile ).k 2iX i i<k
źródło
Kilka komentarzy (nie do końca odpowiedź). Sklasyfikujmy 32-bitowe liczby całkowite w następujący sposób:do
Typ X: (jako ciąg binarny) jest sekwencją De Bruijna (dla wszystkich obrotów bity [27, 31] są różne). Przykład:do
Typu Y: Bity [27,31] z są różne dla i = 0 , 1 , . . . , 31 . To właśnie Leiserson i in. wykorzystuje. Przykłady:2)ja⋅ c i = 0 , 1 , . . . , 31
Typ: z bitów [27,31] z są różne dla i = 0 , 1 , . . . , 31 . Właśnie tego potrzebujemy w pierwotnym pytaniu. Przykłady:( 2i + 1- 1 ) ⋅ c i = 0 , 1 , . . . , 31
Kilka obserwacji opartych na szybkich eksperymentach (mam nadzieję, że udało mi się to dobrze):
Istnieje 65536 liczb całkowitych typu X.
Istnieje 4096 liczb całkowitych typu X + Y. Są to dokładnie te liczby całkowite typu X, które zaczynają się od sekwencji „0000 ...”
Istnieje 256 liczb całkowitych typu X + Y + Z. Są to dokładnie te liczby całkowite typu X, które zaczynają się od sekwencji „0000011111 ...”
Wszystkie liczby całkowite typu Y są również typu X.
Istnieją jednak 768 liczb całkowitych typu Z, które nie są ani typu X, ani typu Y. Zaczynają się one od „1000011111 ...”, „0111100000 ...” lub „1111100000 ...”
źródło
Ta szczególna stała jest sekwencją De Bruijna z alfabetem binarnym, ale z dodatkową właściwością. Nazwie to „Właściwością Marc Dickinson”, ponieważ oryginalny algorytm mógłby zostać zaimplementowany bez tych specjalnych sekwencji DB. Dołączając 2 dodatkowe operacje, moglibyśmy użyć dowolnej zwykłej sekwencji DB. Operacja: v ^ = (v >> 1); // clr wszystkie bity oprócz MSB ustawionego po kaskadowym lub przesunięciu.
Jeśli liczyłeś na elegancki wzór matematyczny do ich opisania lub twierdzenia, aby je wytworzyć lub coś podobnego, myślę, że wymagałoby to głębokiego wglądu w teorię liczb i ewentualnie inne dziedziny, które są poza moim zakresem umiejętności. Jeśli chcę zgadywać, to założę się, że mogą być wytwarzane przez automaty komórkowe. To nie jest odpowiedź dlaczego? na rygorystycznej podstawie, ale próba intuicyjnego zrozumienia, dlaczego to działa i dlaczego działa poprawnie, abyś mógł z niego korzystać z pewnością.
źródło