📄 arithmetic.c
字号:
#include "spiht.h"
#include "spihtdecode.h"
static int QccENTArithmeticModelInitialize(QccENTArithmeticModel *model)
{
if (model == NULL)
return(0);
model->num_contexts = 0;
model->num_symbols = NULL;
model->translate_symbol_to_index = NULL;
model->translate_index_to_symbol = NULL;
model->cumulative_frequencies = NULL;
model->frequencies = NULL;
model->low = model->high = 0;
model->bits_to_follow = 0;
model->garbage_bits = 0;
model->target_num_bits = QCCENT_ANYNUMBITS;
model->adaptive_model = QCCENT_ADAPTIVE;
model->context_function = NULL;
model->current_context = 0;
model->current_code_value = 0;
return(0);
}
static void QccENTArithmeticFreeArray(int **array, int num_contexts)
{
int context;
if (array == NULL)
return;
for (context = 0; context < num_contexts; context++)
if (array[context] != NULL)
free(array[context]);
free(array);
}
static void QccENTArithmeticFreeModelArrays(QccENTArithmeticModel *model)
{
if (model == NULL)
return;
QccENTArithmeticFreeArray(model->translate_symbol_to_index,
model->num_contexts);
QccENTArithmeticFreeArray(model->translate_index_to_symbol,
model->num_contexts);
QccENTArithmeticFreeArray(model->cumulative_frequencies,
model->num_contexts);
QccENTArithmeticFreeArray(model->frequencies,
model->num_contexts);
}
static int **QccENTArithmeticAllocArray(const int *num_symbols,
int num_contexts)
{
int **array = NULL;
int context;
if (num_symbols == NULL)
return(NULL);
if ((array = (int **)malloc(sizeof(int *)*num_contexts)) == NULL)
{
QccErrorAddMessage("(QccENTArithmeticAllocArray): Error allocating memory");
return(NULL);
}
/* Save an extra space total cumulative frequency */
for (context = 0; context < num_contexts; context++)
if ((array[context] =
(int *)malloc(sizeof(int)*(num_symbols[context] + 1))) == NULL)
{
QccErrorAddMessage("(QccENTArithmeticAllocArray): Error allocating memory");
QccENTArithmeticFreeArray(array, num_contexts);
return(NULL);
}
return(array);
}
static int QccENTArithmeticAllocModelArrays(QccENTArithmeticModel *model)
{
if (model == NULL)
return(0);
if (model->num_symbols == NULL)
return(0);
if ((model->translate_symbol_to_index =
QccENTArithmeticAllocArray(model->num_symbols, model->num_contexts))
== NULL)
{
QccErrorAddMessage("(QccENTArithmeticAllocModelArrays): Error calling QccENTArithmeticAllocArray()");
QccENTArithmeticFreeModelArrays(model);
return(0);
}
if ((model->translate_index_to_symbol =
QccENTArithmeticAllocArray(model->num_symbols, model->num_contexts))
== NULL)
{
QccErrorAddMessage("(QccENTArithmeticAllocModelArrays): Error calling QccENTArithmeticAllocArray()");
QccENTArithmeticFreeModelArrays(model);
return(0);
}
if ((model->cumulative_frequencies =
QccENTArithmeticAllocArray(model->num_symbols, model->num_contexts))
== NULL)
{
QccErrorAddMessage("(QccENTArithmeticAllocModelArrays): Error calling QccENTArithmeticAllocArray()");
QccENTArithmeticFreeModelArrays(model);
return(0);
}
if ((model->frequencies =
QccENTArithmeticAllocArray(model->num_symbols, model->num_contexts))
== NULL)
{
QccErrorAddMessage("(QccENTArithmeticAllocModelArrays): Error calling QccENTArithmeticAllocArray()");
QccENTArithmeticFreeModelArrays(model);
return(0);
}
return(0);
}
static int QccENTArithmeticUpdateModel(QccENTArithmeticModel *model,
int symbol_index, int context)
{
int new_index;
int cum = 0;
int symbol1, symbol2;
if (model == NULL)
return(0);
if (model->cumulative_frequencies[context][0] == QCCENT_MAXFREQUENCY)
for (new_index = model->num_symbols[context]; new_index >= 0; new_index--)
{
model->frequencies[context][new_index] =
(model->frequencies[context][new_index] + 1)/2;
model->cumulative_frequencies[context][new_index] = cum;
cum += model->frequencies[context][new_index];
}
for (new_index = symbol_index;
(model->frequencies[context][new_index] ==
model->frequencies[context][new_index - 1]);
new_index--);
if (new_index < symbol_index)
{
symbol1 = model->translate_index_to_symbol[context][new_index];
symbol2 = model->translate_index_to_symbol[context][symbol_index];
model->translate_index_to_symbol[context][new_index] = symbol2;
model->translate_index_to_symbol[context][symbol_index] = symbol1;
model->translate_symbol_to_index[context][symbol1] = symbol_index;
model->translate_symbol_to_index[context][symbol2] = new_index;
}
model->frequencies[context][new_index] += 1;
while (new_index > 0)
{
new_index--;
model->cumulative_frequencies[context][new_index] += 1;
}
return(0);
}
void QccENTArithmeticFreeModel(QccENTArithmeticModel *model)
{
if (model == NULL)
return;
QccENTArithmeticFreeModelArrays(model);
if (model->num_symbols != NULL)
free(model->num_symbols);
free(model);
}
static int
QccENTArithmeticOutputBitPlusFollowingOppositeBits(int bit_value,
QccENTArithmeticModel
*model,
QccBitBuffer *output_buffer)
{
if (QccBitBufferPutBit(output_buffer, bit_value))
{
QccErrorAddMessage("(QccENTArithmeticOutputBitPlusFollowingOppositeBits): Error calling QccBitBufferPutBit()");
return(1);
}
if (model->target_num_bits != QCCENT_ANYNUMBITS)
if (output_buffer->bit_cnt >= model->target_num_bits)
return(2);
while (model->bits_to_follow > 0)
{
if (QccBitBufferPutBit(output_buffer, !bit_value))
{
QccErrorAddMessage("(QccENTArithmeticOutputBitPlusFollowingOppositeBits): Error calling QccBitBufferPutBit()");
return(1);
}
if (model->target_num_bits != QCCENT_ANYNUMBITS)
if (output_buffer->bit_cnt >= model->target_num_bits)
return(2);
model->bits_to_follow--;
}
return(0);
}
static int QccENTArithmeticEncodeSymbol(int symbol_index, int context,
QccENTArithmeticModel *model,
QccBitBuffer *output_buffer)
{
int return_value;
long range;
range = (long)(model->high - model->low) + 1;
model->high = model->low +
(range * model->cumulative_frequencies[context][symbol_index - 1]) /
model->cumulative_frequencies[context][0] - 1;
model->low = model->low +
(range * model->cumulative_frequencies[context][symbol_index]) /
model->cumulative_frequencies[context][0];
for (;;)
{
if (model->high < QCCENT_HALFVALUE)
{
return_value =
QccENTArithmeticOutputBitPlusFollowingOppositeBits(0, model,
output_buffer);
if (return_value == 2)
return(2);
else
if (return_value == 1)
{
QccErrorAddMessage("(QccENTArithmeticEncodeSymbol): Error calling QccENTArithmeticOutputBitPlusFollowingOppositeBits()");
return(1);
}
}
else if (model->low >= QCCENT_HALFVALUE)
{
return_value =
QccENTArithmeticOutputBitPlusFollowingOppositeBits(1, model,
output_buffer);
if (return_value == 2)
return(2);
else
if (return_value == 1)
{
QccErrorAddMessage("(QccENTArithmeticEncodeSymbol): Error calling QccENTArithmeticOutputBitPlusFollowingOppositeBits()");
return(1);
}
model->low -= QCCENT_HALFVALUE;
model->high -= QCCENT_HALFVALUE;
}
else if ((model->low >= QCCENT_FIRSTQUARTERVALUE) &&
(model->high < QCCENT_THIRDQUARTERVALUE))
{
model->bits_to_follow += 1;
model->low -= QCCENT_FIRSTQUARTERVALUE;
model->high -= QCCENT_FIRSTQUARTERVALUE;
}
else
break;
model->low *= 2;
model->high = model->high*2 + 1;
}
return(0);
}
int QccENTArithmeticEncode(const int *symbol_stream,
int symbol_stream_length,
QccENTArithmeticModel *model,
QccBitBuffer *output_buffer)
{
int return_value;
int current_symbol;
int symbol_index;
if (symbol_stream == NULL)
return(0);
if (output_buffer == NULL)
return(0);
if (model == NULL)
return(0);
for (current_symbol = 0; current_symbol < symbol_stream_length;
current_symbol++)
{
if (model->context_function != NULL)
model->current_context =
(model->context_function)(symbol_stream, current_symbol);
if ((model->current_context < 0) ||
(model->current_context >= model->num_contexts))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -