📄 struct_model1.c
字号:
/*---------------------------------------------*/
/* Zzip/Zzlib compressor struct_model1.c */
/* struct model compress/uncompress order-0 */
/*---------------------------------------------*/
/*
This file is a part of zzip and/or zzlib, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1999-2001 Damien Debin. All Rights Reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
Damien Debin
<damien@debin.net>
This program is based on (at least) the work of: Mike Burrows,
David Wheeler, Peter Fenwick, Alistair Moffat, Ian H. Witten,
Robert Sedgewick, Jon Bentley, Brenton Chapin, Stephen R. Tate,
Szymon Grabowski, Bernhard Balkenhol, Stefan Kurtz
*/
#include "zzip.h"
#include "ac-common.h"
/*---------------------------------------------*/
typedef struct
{
uint32 char_to_index;
uint32 index_to_char;
} s_SM1_i;
typedef struct
{
uint32 freq;
uint32 cum;
} s_SM1_f;
static s_SM1_i SM1_i[NO_LEVEL_1 + 1] ALIGN;
static s_SM1_i tab_SM1_i[NO_LEVEL_1][256] ALIGN;
static s_SM1_f SM1_f[NO_LEVEL_1 + 1] ALIGN;
static s_SM1_f tab_SM1_f[NO_LEVEL_1][256] ALIGN;
/*---------------------------------------------*/
/* Start the model (init) sub-function */
static
void Start_Model_2(s_SM1_i *t_i,
s_SM1_f *t_f)
{
uint i;
for (i = 0; i < t_f[0].freq; ++i)
{
t_i[i].char_to_index = i + 1;
t_i[i + 1].index_to_char = i;
}
t_f[0].cum = t_f[0].freq;
for (i = 1; i <= t_f[0].freq; ++i)
{
t_f[i].freq = 1;
t_f[i].cum = t_f[0].freq - i;
}
}
/*---------------------------------------------*/
/* Start the model (init) main function */
static
void Start_Model()
{
uint i, cum = 0, max, l;
for (i = 0; i < NO_LEVEL_1; ++i)
{
SM1_i[i].char_to_index = i + 1;
SM1_i[i + 1].index_to_char = i;
}
SM1_f[0 + 1].freq = 1;
i = 1;
max = block.mtf_max_char - 1;
while (max > 0)
{
l = 1 << i;
if (max < l)
{
i--;
tab_SM1_f[i][0].freq += max;
tab_SM1_f[i + 1][0].freq = 0;
Start_Model_2(tab_SM1_i[i], tab_SM1_f[i]);
max = 0;
}
else
{
max -= l;
SM1_f[i + 1].freq = 1;
tab_SM1_f[i][0].freq = l;
Start_Model_2(tab_SM1_i[i], tab_SM1_f[i]);
}
i++;
}
SM1_f[0].freq = i;
for (; i > 0; --i)
{
SM1_f[i].cum = cum;
cum += SM1_f[i].freq;
}
SM1_f[0].cum = cum;
}
/*---------------------------------------------*/
/* Update of the model for the specified symbol (structured model level 2) */
INLINE static
void Update_Model_2(uint symbol,
s_SM1_i *t_i,
s_SM1_f *t_f)
{
uint k, fs, cum;
uint max = MIN(t_f[0].freq * MAX_FREQUENCY2, MAX_FREQ_MODEL);
if (t_f[0].cum >= max)
{
cum = 0;
for (k = t_f[0].freq; k > 0; --k)
{
t_f[k].cum = cum;
cum += (t_f[k].freq = (t_f[k].freq + 1) >> 1);
}
t_f[0].cum = cum;
}
k = symbol - 1;
fs = t_f[symbol].freq;
while ((k > 0) && (fs == t_f[k].freq)) k--;
if (++k < symbol)
{
uint ch_k, ch_symbol;
ch_k = t_i[k].index_to_char;
ch_symbol = t_i[symbol].index_to_char;
t_i[k].index_to_char = ch_symbol;
t_i[symbol].index_to_char = ch_k;
t_i[ch_k].char_to_index = symbol;
t_i[ch_symbol].char_to_index = k;
}
t_f[k].freq++;
while (k > 0) t_f[--k].cum++;
}
/*---------------------------------------------*/
/* Update of the model (twice) for the specified symbol (structured model level 1) */
INLINE static
void Update_Model_1(const uint smbl)
{
uint k, fs, cum, symbol = smbl;
if (SM1_f[0].cum >= MAX_FREQUENCY1)
{
cum = 0;
for (k = SM1_f[0].freq; k > 0; --k)
{
SM1_f[k].cum = cum;
cum += (SM1_f[k].freq = (SM1_f[k].freq + 1) >> 1);
}
SM1_f[0].cum = cum; }
k = symbol - 1; fs = SM1_f[symbol].freq;
while ((k > 0) && (fs == SM1_f[k].freq)) k--;
if (++k < symbol)
{
uint ch_k, ch_symbol;
ch_k = SM1_i[k].index_to_char;
ch_symbol = SM1_i[symbol].index_to_char;
SM1_i[k].index_to_char = ch_symbol;
SM1_i[symbol].index_to_char = ch_k;
SM1_i[ch_k].char_to_index = symbol;
SM1_i[ch_symbol].char_to_index = k;
}
symbol = k; k--; fs++;
while ((k > 0) && (fs == SM1_f[k].freq)) k--;
if (++k < symbol)
{
uint ch_k, ch_symbol;
ch_k = SM1_i[k].index_to_char;
ch_symbol = SM1_i[symbol].index_to_char;
SM1_i[k].index_to_char = ch_symbol;
SM1_i[symbol].index_to_char = ch_k;
SM1_i[ch_k].char_to_index = symbol;
SM1_i[ch_symbol].char_to_index = k;
}
SM1_f[k].freq++;
SM1_f[symbol].freq++;
while (symbol > k) SM1_f[--symbol].cum++;
while (symbol > 0) SM1_f[--symbol].cum += 2;
}
/*---------------------------------------------*/
#ifndef SFX
/* Compress a block with an order-0 Structured Model */
uint32 Zip_SM1(uint32 len,
uint8 *bufin)
{
uint32 i = 0;
uint32 buffer = 0, low, high, bits_to_go;
sint32 bits_to_follow;
uint8 *buf = NULL;
buf = block.buffer;
Start_Model();
START_OUTPUTING_BITS();
START_ENCODING();
while (i < len)
{
uint j, ch, symbol;
ch = bufin[i++] - 2;
j = 0;
if (ch != 0)
{
ch++;
while ((ch >> ++j) != 1);
if (tab_SM1_f[j][0].freq == 0) j--;
ch -= 1 << j;
}
symbol = SM1_i[j].char_to_index;
ENCODE_SYMBOL_SM1(symbol, SM1_f, SM1_f[0].cum);
Update_Model_1(symbol);
if (j != 0)
{
symbol = tab_SM1_i[j][ch].char_to_index;
ENCODE_SYMBOL_SM1(symbol, tab_SM1_f[j], tab_SM1_f[j][0].cum);
Update_Model_2(symbol, tab_SM1_i[j], tab_SM1_f[j]);
}
}
DONE_ENCODING();
DONE_OUTPUTING_BITS();
return (buf - block.buffer);
}
#endif /* !SFX */
/*---------------------------------------------*/
/* Uncompress a block with an order-0 Structured Model */
void Unzip_SM1(uint32 len,
uint8 *bufout)
{
uint32 i = 0, buffer = 0, low, high, value, bits_to_go;
uint8 *buf = NULL, *length_buf = NULL;
buf = block.buffer;
length_buf = block.buffer_length;
Start_Model();
START_INPUTING_BITS();
START_DECODING();
while (i < len)
{
uint ch, ch2, symbol;
DECODE_SYMBOL_SM1(symbol, SM1_f);
ch = SM1_i[symbol].index_to_char;
Update_Model_1(symbol);
if (ch > 0)
{
ch2 = ch;
DECODE_SYMBOL_SM1(symbol, tab_SM1_f[ch2]);
ch = tab_SM1_i[ch2][symbol].index_to_char;
Update_Model_2(symbol, tab_SM1_i[ch2], tab_SM1_f[ch2]);
ch += 1 << ch2;
ch--;
}
bufout[i++] = ch + 2;
}
}
/*---------------------------------------------*/
/* end struct_model1.c */
/*---------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -