{ Базовые структуры данных для СТАТИЧЕСКОГО арифметического кодирования } {--------------------------------------------------------------------------- (c) Copyright Aleksandrov O.E., 2010 Molecular Physics department, USTU, Ekaterinsburg, K-2, 620002, RUSSIA phone 375-41-46 E-mail: aleks@dpt.ustu.ru ----------------------------------------------------------------------------} Unit AriTypes; INTERFACE USES VeryLongArithmetic { модуль арифметических операций со сверхдлинными беззнаковыми целыми - надож чем-то диапазоны записывать?} ; type { Символ, над которым оперируем } tSymbol=byte; { Номер символа } tSymbolIndex=0..(High(tSymbol)-Low(tSymbol)); { Количество различных символов } tSymbolCount=0..(High(tSymbol)-Low(tSymbol)+1); const { Размер символа в битах } cSizeOfSymbolInBits=8*SizeOf(tSymbol); type { Число бит в символе } tSymbolBitsCounter=0..cSizeOfSymbolInBits; { Структуры данных под буфер ОЗУ ------------------- } const { Максимальная длина в БАЙТАХ буфера в ОЗУ } cMaxByteBufferLength=High(integer)-1024; { Максимальная длина в СИМВОЛАХ буфера в ОЗУ } cMaxBufferLength=(High(integer)-1024) div SizeOf(tSymbol); type { Максимальное целое число } tLargestInt=int64; { Индекс для буфера } tBufferIndex=0..cMaxBufferLength-1; tBufferSize=0..cMaxBufferLength; { Индекс для символов } tByteBufferIndex=0..cMaxByteBufferLength-1; tByteBufferSize=0..cMaxByteBufferLength; { Буфер символов } tBuffer=array[tBufferIndex] of tSymbol; tPBuffer=^tBuffer; { Буфер байтов } tByteBuffer=array[tByteBufferIndex] of byte; tPByteBuffer=^tByteBuffer; { Счетчик символа } tFriquency=longword; { Структуры данных под буфер ОЗУ --END----------------- } { Данные под таблицу счетчиков/интервалов/вероятностей ------------------- } const { Используется длинная арифметика. При вычислениях значение tVeryLongUInt будет умножаться на tFriquency, как результат - возможно переполнение tVeryLongUInt. Чтобы гарантировать себя от переполнения определим максимальное значение tVeryLongUInt меньше чем его реальное максимальное значение, так чтобы при умножении на tFriquency переполнение было бы невозможно.} cAriVeryLongUIntMaxValue:tVeryLongUInt=(Digit0:0); { инициируется в исполняемой секции модуля } cAriVeryLongUIntMaxValueEx:tVeryLongUIntEx=(MostSignificantDigitIndex:0); { инициируется в исполняемой секции модуля } { Число разрядов длинного целого, которые мы используем. Это меньше, чем полное число разрядов чтобы избежать переполнения при умножении } cAriVeryLongUIntShift=cMaxDigitsCount-(SizeOf(tFriquency) div SizeOf(tDigit)); type { Данные по статистике символов - количество вхождений символа в сообщение } tAriStatistics=array[tSymbol] of tFriquency; { Данные по диапазону, приписываемому символу} tRange=record Start:tFriquency; { начало } Length:tFriquency; { длина = количеству этих символов в сообщении } end; { данные по полному счетчику } tTotalShift=0..32; tTotalCountData=record SymbolCount:tFriquency; { полное число символов } PowerOf2:tTotalShift; { если PowerOf2>0 значит SymbolCount=2^PowerOf2 и можно применять сдвиг вправо на PowerOf2 бит вместо деления на SymbolCount} MostSignificantDigitIndex:tDigitIndex; {номер старшего ненулевого слова } end; { Данные диапазонов для всех символов ДЛЯ КОДИРОВАНИЯ} tAriRanges=record Total:tTotalCountData; Ranges:array[tSymbol] of tRange; MaxCounter:tFriquency; end; { Массив диапазонов ДЛЯ ДеКОДИРОВАНИЯ. Содержит только ПРИСУТСТВУЮЩИЕ в сообщении символы и дополнительные данные, ускоряющие декодирование.} tAriRangesForDecode=record Total:tTotalCountData; { полное число символов } Starts:array[tSymbolIndex] of tFriquency; { начала интервалов ненулевых символов } Lengths:array[tSymbolIndex] of tFriquency; { статистика ненулевых символов } Symbols:array[tSymbolIndex] of tSymbol; { символ, соответствующий интервалу } LastSymbolIndex:tSymbolIndex; { номер последного символа с НЕНУЛЕВОЙ статистикой } end; { ОЧЕНЬ БОЛЬШОЙ ДИАПАЗОН для вычислений Арифметического кодирования } tAriVeryLargeRange=record EncodedSymbolCount:word; { число закодированных символов } Start:tVeryLongUIntEx; { начало кодового интервала в диапазоне [0..cAriVeryLongUIntMaxValue)} Length:tVeryLongUIntEx; { длина кодового интервала в диапазоне [0..cAriVeryLongUIntMaxValue)} end; { ОЧЕНЬ БОЛЬШОЙ КОД для хранения кода Арифметического кодирования} tAriVeryLargeCode=record Value:tVeryLongUIntEx; { значение кода в диапазоне [0..cAriVeryLongUIntMaxValue) } NonDecodedSymbolCount:word; { число НЕдекодированных символов кода } end; { Счетчик символов для кодека} tVeryLongCounter= int64; IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// begin { Используется длинная арифметика. При вычислениях значение tVeryLongUInt будет умножаться на tFriquency (longword), как результат - возможно переполнение tVeryLongUInt. Чтобы гарантировать себя от переполнения определим максимальное ДОПУСТИМОЕ значение tVeryLongUInt меньше чем его реальное максимальное значение, так чтобы при умножении на tFriquency переполнение было бы невозможно.} { инициирование константы сAriVeryLongUIntMaxValue} { cAriVeryLongUIntMaxValue:=(2^16)^n, n=cMaxDigitsCount-(SizeOf(tFriquency) div SizeOf(tDigit))} cAriVeryLongUIntMaxValue.Digits[cAriVeryLongUIntShift]:=1; { что равно (2^16)^cAriVeryLongUIntShift } vlaAssign(cAriVeryLongUIntMaxValue, cAriVeryLongUIntMaxValueEx); end. ////////////////////////////////////////////////////////////////////////////////