Ćwiczenie nr 4: Kodowanie arytmetyczne, range coder

Podobne dokumenty
Kompresja Kodowanie arytmetyczne. Dariusz Sobczuk

Kodowanie informacji

Kodowanie Huffmana. Platforma programistyczna.net; materiały do laboratorium 2014/15 Marcin Wilczewski

mgr inż. Grzegorz Kraszewski SYSTEMY MULTIMEDIALNE wykład 4, strona 1. GOLOMBA I RICE'A

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Temat: Algorytm kompresji plików metodą Huffmana

/* dołączenie pliku nagłówkowego zawierającego deklaracje symboli dla wykorzystywanego mikrokontrolera */ #include <aduc834.h>

Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Podstawy programowania w języku C++

Kodowanie i kompresja Streszczenie Studia dzienne Wykład 9,

Entropia Kodowanie. Podstawy kompresji. Algorytmy kompresji danych. Sebastian Deorowicz

Języki programowania. Przetwarzanie plików amorficznych Konwencja języka C. Część siódma. Autorzy Tomasz Xięski Roman Simiński

Kody Tunstalla. Kodowanie arytmetyczne

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 12. Karol Tarnowski A-1 p.

Def. Kod jednoznacznie definiowalny Def. Kod przedrostkowy Def. Kod optymalny. Przykłady kodów. Kody optymalne

Przetwarzanie i transmisja danych multimedialnych. Wykład 5 Kodowanie słownikowe. Przemysław Sękalski.

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Założenia i obszar zastosowań. JPEG - algorytm kodowania obrazu. Geneza algorytmu KOMPRESJA OBRAZÓW STATYCZNYCH - ALGORYTM JPEG

Według raportu ISO z 1988 roku algorytm JPEG składa się z następujących kroków: 0.5, = V i, j. /Q i, j

teoria informacji Kanały komunikacyjne, kody korygujące Mariusz Różycki 25 sierpnia 2015

Wykład VI. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

pobieramy pierwszą literę komunikatu i wypełniamy nią (wszystkie pozycje tą samą literą) bufor słownikowy.

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

Definicja. Jeśli. wtedy

Pliki. Informacje ogólne. Obsługa plików w języku C

Kodowanie Shannona-Fano

Algorytmy i struktury danych. Wykład 6 Tablice rozproszone cz. 2

2 Przygotował: mgr inż. Maciej Lasota

teoria informacji Entropia, informacja, kodowanie Mariusz Różycki 24 sierpnia 2015

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

KODY SYMBOLI. Kod Shannona-Fano. Algorytm S-F. Przykład S-F

Zadanie nr 3: Sprawdzanie testu z arytmetyki

while(wyrażenie) instrukcja

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

Tablice deklaracja, reprezentacja wewnętrzna

Zadanie 2: Arytmetyka symboli

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Modulacja i kodowanie. Labolatorium. Kodowanie źródłowe Kod Huffman a

Biblioteka standardowa - operacje wejścia/wyjścia

Tematy projektów Algorytmy Kompresji Danych (2006)

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Technologie Informacyjne

Funkcje zawarte w bibliotece < io.h >

Algorytm selekcji Hoare a. Łukasz Miemus

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Funkcje zawarte w bibliotece < io.h >

Kompresja danych kodowanie Huffmana. Dariusz Sobczuk

Języki programowania obiektowego Nieobiektowe elementy języka C++

3. Opracować program kodowania/dekodowania pliku tekstowego. Algorytm kodowania:

Granica kompresji Kodowanie Shannona Kodowanie Huffmana Kodowanie ciągów Kodowanie arytmetyczne. Kody. Marek Śmieja. Teoria informacji 1 / 35

Tablice, funkcje - wprowadzenie

LZ77 LZ78. Kompresja danych. Tomasz Jurdziński. Wykład 5: kodowanie słownikowe

Pliki. Informacje ogólne. Obsługa plików w języku C

1. Synteza automatów Moore a i Mealy realizujących zadane przekształcenie 2. Transformacja automatu Moore a w automat Mealy i odwrotnie

Kodowanie informacji

Wielomian interpolacyjny Hermite a

Kwantyzacja wektorowa. Kodowanie różnicowe.

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Wydział Elektryczny. Katedra Telekomunikacji i Aparatury Elektronicznej. Konstrukcje i Technologie w Aparaturze Elektronicznej.

E S - uniwersum struktury stosu

Język ludzki kod maszynowy

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013

Język C zajęcia nr 11. Funkcje

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

LABORATORIUM 3 ALGORYTMY OBLICZENIOWE W ELEKTRONICE I TELEKOMUNIKACJI. Wprowadzenie do środowiska Matlab

Sieci Mobilne i Bezprzewodowe laboratorium 2 Modelowanie zdarzeń dyskretnych

Wstęp do Informatyki

OPERACJE WEJŚCIA / WYJŚCIA. wysyła sformatowane dane do standardowego strumienia wyjściowego (stdout)

Aproksymacja funkcji a regresja symboliczna

Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.

Ćwiczenie 3 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

Kodowanie predykcyjne

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Tablice i struktury. czyli złożone typy danych. Programowanie Proceduralne 1

Języki programowania. Przetwarzanie tablic znaków. Część druga. Autorzy Tomasz Xięski Roman Simiński

external Data Representation

Instytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny Technologiczny Politechnika Śląska

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Temat 7. Programowanie mikrokontrolerów z rodziny PIC16 w języku C przy użyciu HI-TECH C for PIC10/12/16

Podstawy programowania

IX. Wskaźniki.(3 godz.)

AKD Metody słownikowe

Ćwiczenie nr 6. Poprawne deklaracje takich zmiennych tekstowych mogą wyglądać tak:

Kompilator języka C na procesor 8051 RC51 implementacja

Matematyczne Podstawy Informatyki

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.

Sun RPC/XDR. Dariusz Wawrzyniak 1

Analiza algorytmów zadania podstawowe

Wstęp Statyczne kody Huffmana Dynamiczne kody Huffmana Praktyka. Kodowanie Huffmana. Dawid Duda. 4 marca 2004

Formatowane (tekstowe) wejście/wyjście. Binarne wejście/wyjście.

Podstawy programowania w języku C++

PMiK Programowanie Mikrokontrolera 8051

7. Pętle for. Przykłady

Wykład 3 Składnia języka C# (cz. 2)

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Algorytmy i złożoności Wykład 5. Haszowanie (hashowanie, mieszanie)

Transkrypt:

Algorytmy Kompresji Danych Laboratorium Ćwiczenie nr 4: Kodowanie arytmetyczne, range coder 1. Zapoznać się z opisem implementacji kodera entropijnego range coder i modelem danych opracowanym dla tego kodera (patrz załącznik 1) oraz z przykładami ich użycia. 2. Implementację algorytmu LZSS (koder i dekoder), opracowaną na poprzednim ćwiczeniu, rozbudować o opcję arytmetycznego kodowania wyjścia z kodera słownikowego (i dekodowania wejścia dla dekodera). Dane wyprowadzane przez algorytm LZSS (tzn. flagę /litera czy ciąg/, literę /gdy nie znaleziono ciągu/, lub offset znalezionego ciągu oraz jego długość) należy kodować nie kodem binarnym stałej długości, a za pomocą range codera. Modelowanie wyjścia algorytmu LZSS można zrealizować w oparciu o kilka adaptacyjnych modeli danych: dla flag model bezpamięciowy lub model kontekstowy (w takim przypadku kontekstem winna być poprzednia flaga), dla liter (gdy nie znaleziono ciągu) model bezpamięciowy, dla offsetów znalezionych ciągów model bezpamięciowy, szczegóły patrz niżej, dla długości znalezionych ciągów model kontekstowy, kontekstem może być log 2 (offset znalezionego ciągu), (funkcja log 2 (int) patrz załącznik 2). Zatem w programie należy użyć czterech modeli oraz jednego kodera. W zależności od tego, co w danym momencie kodujemy, używać będziemy odpowiedniego modelu. Jeżeli np. kodujemy literę, to modelem dla liter wyznaczamy jej prawdopodobieństwo (i wymagane przez koder łączne prawdopodobieństwo wszystkich mniejszych liter) i kodujemy ją koderem arytmetycznym (jedynym, tzn. tym samym, którym w poprzednim kroku kodowaliśmy flagę na podstawie danych otrzymanych z modelu dla flag). Offset znalezionego ciągu, tj. liczba z zakresu [1.. MAX_OFFSET], to alfabet o dużej liczbie symboli (typowo MAX_OFFSET=32768); między innymi ze względu na problem ZFP (patrz instrukcja do ćwiczenia nr. 2) adaptacyjne modelowanie takiego alfabetu mogłoby nie być efektywne. Można jednak podzielić zakres na dwa podzakresy: małych i często występujących offsetów [1.. X] oraz dużych, występujących rzadziej [X + 1.. MAX_OFFSET]. X jest parametrem, którego wartość należy dobrać. Następnie modelowaniu i kodowaniu podlega alfabet X + 1 symboli, z których pierwsze X traktowane będą jako wartości małych offsetów, a ostania (X + 1) to znacznik dużego offsetu. gdy offset jest w zakresie [1.. X] to kodujemy wartość offsetu i tą wartością aktualizujemy model, gdy offset jest w zakresie [X + 1.. MAX_OFFSET] to kodujemy symbol X + 1, jako znacznik dużego offsetu, następnie musimy dodatkowo wyprowadzić, binarnie na log 2 (MAX_OFFSET X) bitach, liczbę: offset X 1; model aktualizujemy symbolem X + 1. Np.: W naszym wariancie LZSS MAX_OFFSET=32768. Przyjmujemy, że małe offsety to te, nie większe od 250 (X=250), więc model danych dla offsetów będzie zawierał 251 symboli. Symbol 251 będzie znacznikiem dużego offsetu a pozostałe symbole będą wartościami małych offsetów. Kodujemy offsety wyznaczone algorytmem LZSS:

gdy LZSS wygeneruje mały offset, czyli offset jest w zakresie [1.. 250], np. 20, to kodujemy koderem arytmetycznym wprost wartość offsetu (liczbę 20) i tą wartością aktualizujemy model, gdy offset jest duży, czyli jest w przedziale [251.. 32768] i np. wynosi 2000, to kodujemy, jako znacznik dużego offsetu symbol 251, a następnie wyprowadzamy liczbę 1749=2000 251 binarnie, na 15 bitach; model aktualizujemy symbolem 251. Uwagi: Do strumienia wyjściowego kodera arytmetycznego nie można wprost wyprowadzać żadnych danych z pominięciem tego kodera. Zatem aby wyprowadzić n-bitową liczbę do strumienia, należy ją zakodować koderem arytmetycznym jako liczbę z przedziału [0.. 2 n 1] o równomiernym rozkładzie prawdopodobieństwa (liczby 8- i 16-bitowe patrz załącznik 1: makra encode_byte i encode_short, liczby n-bitowe załącznik 2). Zakres wartości offsetu można podzielić na kilka (K) przedziałów, z których pierwszy jest [1.. X] i używać alfabetu X + K 1 symboli. X początkowych symboli używamy do kodowania offsetów z pierwszego przedziału, pozostałych symboli jako znaczników pozostałych przedziałów. Dla pozostałych przedziałów konieczne jest zakodowanie, oprócz znacznika przedziału, pozycji offsetu wewnątrz przedziału zakodowanie binarnie na takiej liczbie bitów, jaka wynika z długości przedziału. Pewne wartości nie wystąpią na wyjściu algorytmu LZSS; minimalna długość znalezionego ciągu jest liczbą większą od 1 i jest zależna od parametrów algorytmu (typowo wynosi 3 lub więcej), co można uwzględnić optymalizując koder. 3. Dla jednego z plików z korpusu Calgary (sugerowane użycie pliku wybranego podczas poprzednich zajęć) dobrać parametry: liczbę małych offsetów (X) oraz szybkość adaptacji modeli danych (parametr rescale z funkcji initqsmodel). Zmierzyć współczynnik i czas kompresji; porównać uzyskany współczynnik z wynikiem kodera LZSS bez kodowania arytmetycznego. Dla pozostałych plików z Calgary również zmierzyć współczynniki i porównać je z współczynnikami uzyskanymi dla LZSS bez kodera arytmetycznego na poprzednim laboratorium. Uzyskane wyniki oraz wnioski zawrzeć w krótkim sprawozdaniu.

Załącznik 1: Opis implementacji range coder Implementacja range codera autorstwa Michaela Schindlera (do ściągnięcia ze strony przedmiotu, lub z http://www.compressconsult.com/ ) zawiera między innymi: koder entropijny (range coder): rangecod.h rangecod.c bezpamięciowy model danych: qsmodel.h qsmodel.c przykłady użycia kodera i modeli statyczny (de)kompresor: simple_c.c simple_d.c adaptacyjny (de)kompresor (model bezpamięciowy): comp.c decomp.c adaptacyjny (de)kompresor z modelem I* rzędu: comp1.c decomp1.c Niniejszy załącznik zawiera krótki opis podstawowych elementów kodera i modelu, bardziej szczegółowa dokumentacja zawarta jest w plikach.h odpowiednich modułów i programach przykładowych. Sposób użycia kodera i dekodera czytelnie ilustruje przykład simple_c.c simple_d.c, użycie modelu we współpracy z koderem/dekoderem przykład comp.c decomp.c. Koder entropijny range coder (pliki rangecod.h rangecod.c) struct rangecoder rc; Moduł kodera wymaga zadeklarowania zmiennej stanu i przekazywania jej jako parametru do wszystkich funkcji modułu. void start_encoding(rangecoder *rc, char c, int initlength); inicjalizacja kodera. c jest pierwszym bajtem (nagłówkiem) skompresowanych danych (ze względów implementacyjnych konieczne jest wyprowadzenie jednego bajta, o dowolnej wartości, przed rozpoczęciem wyprowadzania skompresowanych danych). initlength to liczba już wyprowadzonych bajtów, (0 gdy nie reinicjalizujemy kodera). void encode_freq(rangecoder *rc, freq sy_f, freq lt_f, freq tot_f); zakoduj symbol s, sy_f to liczba wystąpień symbolu s, lt_f to łączna liczba wystąpień symboli mniejszych od s, tot_f to łączna liczba wystąpień wszystkich symboli alfabetu. Uwaga: domyślnym strumieniem do wyprowadzania skompresowanych danych jest stdout (a wejściem dla dekompresji stdin), aby kompresować do pliku należy albo przekierować stdin/stdout (za pomocą funkcji freopen() i setmode(), tak jak to pokazano w przykładzie simple_c.c), albo przedefiniować makra zdefiniowane w rangecod.c, za pomocą których odbywa się całe i/o range codera: #define outbyte(cod,x) putchar(x) #define inbyte(cod) getchar() void encode_shift(rangecoder *rc, freq sy_f, freq lt_f, freq shift); szybsza wersja funkcji encode_freq, do zastosowania, gdy łączna liczba wystąpień wszystkich symboli alfabetu jest potęgą dwójki i wynosi 2 shift. #define encode_byte(rc,b)... #define encode_short(rc,s)... zapis bajta b lub liczby shortint s do strumienia skompresowanych danych (na odpowiednio około 8 i około 16 bitach).

Uwaga: do strumienia, do którego zapisuje range coder nie należy nic wyprowadzać z pominięciem kodera, i stąd te makra. uint4 done_encoding(rangecoder *rc ); zakończenie pracy kodera, wyprowadzenie wszystkich jeszcze nie zapisanych danych. Funkcja zwraca liczbę bajtów wyprowadzonych od inicjalizacji kodera. int start_decoding(rangecoder *rc ); inicjalizacja dekodowania, zwraca EOF w razie błędu, lub nagłówek zakodowanych danych (parametr c ze start_encoding). freq decode_culfreq(rangecoder *rc, freq tot_f ); zwróć łączną liczbę wystąpień symboli mniejszych od tego, który właśnie dekodujemy (dokładniej wartość jej równą lub nieistotnie mniejszą). tot_f to łączna liczba wystąpień wszystkich symboli alfabetu. Dekodowanie symbolu odbywa się w dwóch krokach: na podstawie zwróconej liczby i modelu wyznaczamy, jakiemu symbolowi odpowiada ta liczba, po czym należy uaktualnić stan dekodera wywołując poniższą funkcję. void decode_update(rangecoder *rc, freq sy_f, freq lt_f, freq tot_f); aktualizacja dekodera po zdekodowaniu symbolu, parametry jak w funkcji encode_freq. freq decode_culshift( rangecoder *ac, freq shift ); #define decode_update_shift(rc,f1,f2,shift)... szybsze wersje funkcji decode_culfreq() i decode_update() do zastosowania, gdy łączna liczba wystąpień wszystkich symboli alfabetu jest potęgą dwójki i wynosi 2 shift. unsigned char decode_byte(rangecoder *rc); unsigned short decode_short(rangecoder *rc); odczytanie ze srtumienia skompresowanych danych odpowiednio bajta lub liczby shortint, po odczytaniu nie wywołujemy decode_update. void done_decoding( rangecoder *rc ); zakończenie pracy dekodera. Proste przykłady użycia powyższych funkcji można znaleźć w programach simple_c.c i simple_d.c. Model danych dla range codera (pliki qsmodel.h qsmodel.c) struct qsmodel m; model bezpamięciowy (zawiera m. in. tablice liczników wystąpień symboli), jest argumentem funkcji operujących na modelu, aby zbudować model wyższego rzędu należy utworzy kolekcję modeli bezpamięciowych (patrz comp1.c decomp1.c). void initqsmodel(qsmodel *m, int n, int lg_totf, int rescale, int *init, int compress); inicjalizacja modelu m, n to liczba symboli alfabetu,

lg_totf łączna liczba wystąpień wszystkich symboli alfabetu zwracana przez model na użytek kodera arytmetycznego będzie zawsze wynosiła 2 lg_totf (tzn. inne liczniki będą skalowane tak, aby zachować zadaną łączną liczbę wystąpień), wartość lg_totf powinna by mniejsza od 16, np. wynosić 12, rescale określa co ile uaktualnień modelu przeprowadzać okresowe dzielenie wszystkich liczników przez 2 (faktycznie jest to wartość docelowa, na początku kompresji dzielenie liczników wykonywane jest częściej), wartość rescale powinna być mniejsza od 2 lg_totf+1. Od wartości rescale zależy szybkość adaptacji modelu, init to tablica początkowych wartości liczników symboli lub NULL (wtedy inicjalizacja w sposób domyślny, wszystkie symbole na początku mają takie same wartości liczników), compress wartośc 1 gdy model używamy w kompresji, 0 dla dekompresji. void resetqsmodel(qsmodel *m, int *init); reinicjalizacja modelu. void deleteqsmodel(qsmodel *m ); zwolnienie pamięci przydzielonej dla modelu w initqsmodel(). void qsgetfreq(qsmodel *m, int sym, int *sy_f, int *lt_f ); dla symbolu sym wyznacz liczbę wystąpień tego symbolu (sy_f) oraz łączną liczbę wystąpień symboli mniejszych od sym (lt_f). Uwaga: łączna liczba wystąpień wszystkich symboli alfabetu to 2 lg_totf, gdzie lg_totf jest zadane podczas inicjalizacji modelu. int qsgetsym( qsmodel *m, int lt_f); wyznacz symbol znając łączną liczbę wystąpień symboli mniejszych od niego (lt_f). void qsupdate(qsmodel *m, int sym); aktualizacja modelu, zarejestrowanie kolejnego wystąpienia symbolu sym. Uwaga: model jest skonstruowany w taki sposób, że wyznaczona przez niego łączna liczba wystąpień wszystkich symboli alfabetu jest potęgą dwójki już od momentu inicjalizacji modelu, dzięki czemu możemy korzystać z szybszych wersji funkcji kodowania/dekodowania range codera. Jednak, aby powyższy warunek spełnić i dodatkowo, aby model działał szybko, operacja qsupdate() nie zawsze prowadzi do natychmiastowej aktualizacji struktur, na podstawie których wyznaczane są liczby wystąpień symboli. Zamiast tego, nowe wystąpienia są zliczane w dodatkowej tablicy, z której co jakiś czas są hurtem wprowadzane do właściwej tablicy liczników. Zatem faktycznie aktualizacja modelu nastąpi dla każdego symbolu z którym wywołana jest funkcja qsupdate(), jednak dla niektórych symboli z pewnym opóźnieniem. Przykłady użycia powyższych funkcji i wykorzystania ich do modelowania dla kompresji z użyciem range codera można znaleźć w programach comp.c decomp.c (model bezpamięciowy) oraz comp1.c decomp1.c (model kontekstowy I rzędu). * Istnieją różne definicje rzędu modelu; tutaj przyjmujemy, że rząd modelu równy jest liczbie symboli poprzedzających dany (długości kontekstu tego symbolu) branych pod uwagę przy wyznaczaniu prawdopodobieństwa dla tego symbolu. Zatem budując model rzędu k zakładamy, że ciąg symboli generowanych przez źródło jest dyskretnym łańcuchem Markowa rzędu k.

Załącznik 2: Przydatne funkcje Funkcja sufit(log 2 (val)) int ceil_log_2(int val) /* ceil(log_2(val)) */ { int result; assert(val>0); } if (val==1) return 0; result=1; val-=1; while (val>>=1) result++; return result; Zapis/odczyt liczb n-bitowych range coderem Zapis n-bitowej liczby b do strumienia skompresowanych danych, 0 < n 16. void encode_n_bits(rangecoder *rc, int b, int n) { assert(n>0 && n<=16); assert(b>=0 && b<(1<<n)); } encode_shift(rc,(freq)1,(freq)b,(freq)n); Odczyt liczby n-bitowej ze strumienia skompresowanych danych, 0 < n 16. unsigned short decode_n_bits(rangecoder *rc, int n) { unsigned short tmp; assert(n>0 && n<=16); } tmp = decode_culshift(rc,n); decode_update_shift(rc,1,tmp,n); return tmp;