Zmiana okrężna

Macierze 8-elementowych kołowych przesunięć w lewo i prawo

W matematyce kombinatorycznej przesunięcie kołowe jest operacją polegającą na przestawieniu wpisów w krotce poprzez przesunięcie ostatniego wpisu na pierwszą pozycję, przy jednoczesnym przesunięciu wszystkich pozostałych wpisów na następną pozycję lub wykonanie operacji odwrotnej. Przesunięcie kołowe jest szczególnym rodzajem permutacji cyklicznej , która z kolei jest szczególnym rodzajem permutacji . Formalnie przesunięcie kołowe jest permutacją σ n wpisów w krotce taką, że albo

modulo n dla wszystkich wpisów ja = 1, ..., n

Lub

modulo n , dla wszystkich wpisów ja = 1, ..., n .

Wynik wielokrotnego stosowania przesunięć kołowych do danej krotki jest również nazywany przesunięciami kołowymi krotki.

Na przykład wielokrotne stosowanie przesunięć kołowych do krotki czterokrotnej ( a , b , c , d ) daje kolejno

  • ( re , za , b , do ),
  • ( do , re , za , b ),
  • ( b , do , re , za ),
  • ( a , b , c , d ) (oryginalna czterokrotka),

a następnie sekwencja się powtarza; ta czterokrotna krotka ma zatem cztery różne przesunięcia kołowe. Jednak nie wszystkie n -krotki mają n różnych przesunięć kołowych. Na przykład krotka 4 ( a , b , a , b ) ma tylko 2 różne przesunięcia kołowe. Ogólnie liczba przesunięć kołowych n -krotki może być dowolnym dzielnikiem n , w zależności od wpisów krotki.

W programowaniu komputerowym obrót bitowy , znany również jako przesunięcie kołowe, jest operacją bitową, która przesuwa wszystkie bity swojego operandu. W przeciwieństwie do przesunięcia arytmetycznego , przesunięcie kołowe nie zachowuje bitu znaku liczby ani nie odróżnia wykładnika liczby zmiennoprzecinkowej od jej mantysy . W przeciwieństwie do przesunięcia logicznego wolne pozycje bitów nie są wypełniane zerami, ale bitami przesuniętymi poza sekwencję.

Wdrażanie zmian okrężnych

Przesunięcia kołowe są często używane w kryptografii w celu permutacji sekwencji bitów. Niestety wiele języków programowania, w tym C , nie ma operatorów ani standardowych funkcji dla przesunięć kołowych, mimo że praktycznie wszystkie procesory mają do tego bitowe instrukcje operacji (np. Intel x86 ma ROL i ROR). Jednak niektóre kompilatory mogą zapewniać dostęp do instrukcji procesora za pomocą funkcji wewnętrznych . Ponadto niektóre konstrukcje w standardowym ANSI C mogą być optymalizowane przez kompilator do instrukcji języka asemblera „obracaj” na procesorach, które mają taką instrukcję. Większość kompilatorów C rozpoznaje następujący idiom i kompiluje go do pojedynczej 32-bitowej instrukcji obracania.








 
 

       
             
      
             


       
             
      
             
 /*  * Operacje przesunięcia w C są zdefiniowane tylko dla wartości przesunięcia, które  * nie są ujemne i są mniejsze niż sizeof(value) * CHAR_BIT.  * Maska, używana z bitowym-and (&), zapobiega niezdefiniowanemu zachowaniu  *, gdy liczba przesunięć wynosi 0 lub >= szerokość unsigned int.  */  #include  <stdint.h>  // dla uint32_t, aby uzyskać obrót o szerokości 32 bitów, niezależnie od rozmiaru int.  #include  <limits.h>  // for CHAR_BIT  uint32_t  rotl32  (  wartość  uint32_t  ,  liczba  unsigned  int  )  {  const  unsigned  int  mask  =  CHAR_BIT  *  sizeof  (  wartość  )  -  1  ;  liczba  &=  maska  ;  zwróć  (  wartość  <<  liczba  )  |  (  wartość  >>  (  -  liczba  i  maska  ​​));  }  uint32_t  rotr32  (  wartość  uint32_t  ,  liczba  int  bez  znaku  )  {  const  unsigned  int  mask  =  CHAR_BIT  *  sizeof  (  wartość  )  -1  ;  liczba  &=  maska  ;  return  (  wartość  >>  liczba  )  |  (  wartość  <<  (  -  liczba  i  maska  ​​));  } 

Ta bezpieczna i przyjazna dla kompilatorów implementacja została opracowana przez Johna Regehra i dopracowana przez Petera Cordesa.

Prostsza wersja jest często spotykana, gdy liczba jest ograniczona do zakresu od 1 do 31 bitów:

       
             
 uint32_t  rotl32  (  wartość  uint32_t  ,  liczba  int  bez znaku  )  {  zwracana  wartość  <<  liczba  |  wartość  >>  (  32  -  liczba  );  } 

Ta wersja jest niebezpieczna, ponieważ jeśli liczba wynosi 0 lub 32, prosi o przesunięcie 32-bitowe, co jest niezdefiniowanym zachowaniem w standardzie języka C. Jednak i tak ma tendencję do działania, ponieważ większość mikroprocesorów implementuje wartość >> 32 jako przesunięcie 32-bitowe (wytwarzające 0) lub przesunięcie 0-bitowe (wytwarzające pierwotną wartość ), a każda z nich daje poprawny wynik w tej aplikacji .

Przykład

Gdyby sekwencja bitów 0001 0111 została poddana kołowemu przesunięciu o jedną pozycję bitową... (patrz ilustracje poniżej)

  • w lewo dałoby: 0010 1110
Przesunięcie okrężne w lewo.
  • w prawo dałoby: 1000 1011.
Przesunięcie okrężne w prawo.

Gdyby sekwencja bitów 1001 0110 została poddana następującym operacjom:

przesunięcie kołowe w lewo o 1 pozycję: 0010 1101
przesunięcie kołowe w lewo o 2 pozycje: 0101 1010
przesunięcie kołowe w lewo o 3 pozycje: 1011 0100
przesunięcie kołowe w lewo o 4 pozycje: 0110 1001
przesunięcie kołowe w lewo o 5 pozycji: 1101 0010
przesunięcie kołowe w lewo o 6 pozycji: 1010 0101
przesunięcie kołowe w lewo o 7 pozycji: 0100 1011
przesunięcie kołowe w lewo o 8 pozycji: 1001 0110
przesunięcie kołowe w prawo o 1 pozycję: 0100 1011
przesunięcie kołowe w prawo o 2 pozycje: 1010 0101
przesunięcie okrężne w prawo o 3 pozycje: 1101 0010
przesunięcie kołowe w prawo o 4 pozycje: 0110 1001
przesunięcie kołowe w prawo o 5 pozycji: 1011 0100
przesunięcie kołowe w prawo o 6 pozycji: 0101 1010
przesunięcie kołowe w prawo o 7 pozycji: 0010 1101
przesunięcie kołowe w prawo o 8 pozycji: 1001 0110

Aplikacje

Kody cykliczne to rodzaj kodu blokowego , którego właściwość polega na tym, że przesunięcie kołowe słowa kodowego zawsze daje inne słowo kodowe. Motywuje to następującą ogólną definicję: Dla łańcucha s nad alfabetem Σ niech przesunięcie ( s ) oznacza zbiór przesunięć kołowych s , a dla zbioru L ciągów niech przesunięcie ( L ) oznacza zbiór wszystkich przesunięć kołowych struny w l . Jeśli L jest kodem cyklicznym, to shift ( L ) ⊆ L ; jest to warunek konieczny, aby L był językiem cyklicznym . Przesunięcie operacji ( L ) było badane w teorii języka formalnego . Na przykład, jeśli L jest językiem bezkontekstowym , to shift ( L ) jest znowu bezkontekstowy. Ponadto, jeśli L jest opisane przez wyrażenie regularne o długości n , istnieje wyrażenie regularne o długości O ( n3 ) opisujące przesunięcie ( L ).

Zobacz też