Add option -d (decompress) to fpga_compress. Allows testing.

Improve zlib deflate (note: no change required to inflate).
This commit is contained in:
pwpiwi 2015-05-18 08:49:38 +02:00
commit 4b3f6d79ea
5 changed files with 204 additions and 11 deletions

View file

@ -1153,7 +1153,11 @@ local uInt longest_match(s, cur_match)
register Bytef *scan = s->window + s->strstart; /* current string */
register Bytef *match; /* matched string */
register int len; /* length of current match */
#ifdef ZLIB_PM3_TUNED
int best_len = MIN_MATCH-1; // lift the restriction on prev-length
#else
int best_len = s->prev_length; /* best match length so far */
#endif
int nice_match = s->nice_match; /* stop if match long enough */
IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
s->strstart - (IPos)MAX_DIST(s) : NIL;
@ -1721,6 +1725,104 @@ local block_state deflate_fast(s, flush)
return block_done;
}
#ifdef ZLIB_PM3_TUNED
local uInt try_harder(s, strstart, lookahead, hash_head, level)
deflate_state *s;
uInt strstart;
uInt lookahead;
IPos hash_head;
uInt level;
{
uInt strstart_save = s->strstart;
s->strstart = strstart;
uInt lookahead_save = s->lookahead;
s->lookahead = lookahead;
uInt ins_h_save = s->ins_h;
uInt combined_gain;
uInt best_combined_gain = 0;
uInt match_length;
uInt prev_length = s->prev_length < MIN_MATCH ? 1 : s->prev_length;
uInt best_prev_length = prev_length;
uInt current_match_start = s->match_start;
uInt current_match_length = s->match_length;
do {
if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
match_length = longest_match (s, hash_head);
/* longest_match() sets match_start */
} else {
match_length = MIN_MATCH - 1;
}
#if TOO_FAR <= 32767
if (match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) {
match_length = MIN_MATCH-1;
}
#endif
if (s->strstart == strstart) { // store match at current position
current_match_length = match_length;
current_match_start = s->match_start;
}
if (s->strstart - strstart + 1 < MIN_MATCH) { // previous match reduced to one or two literals
combined_gain = 0; // need one literal per byte: no gain (assuming 8 bits per literal)
} else {
combined_gain = s->strstart - strstart + 1 - MIN_MATCH; // (possibly truncated) previous_length - 3 literals
}
if (level > 1 && s->strstart+1 <= s->window_size - MIN_LOOKAHEAD) { // test one level more
s->prev_length = match_length;
uInt save_ins_h = s->ins_h;
UPDATE_HASH(s, s->ins_h, s->window[(s->strstart+1) + (MIN_MATCH-1)]);
combined_gain += try_harder(s, s->strstart+1, s->lookahead-1, s->head[s->ins_h], level-1);
s->ins_h = save_ins_h;
} else {
if (match_length < MIN_MATCH) {
combined_gain += 0; // no gain
} else {
combined_gain += match_length - MIN_MATCH; // match_length bytes coded as approx three literals
}
}
// if (combined_length > s->lookahead - 1) {
// combined_length = s->lookahead;
// }
if (combined_gain >= best_combined_gain) { // in case of a tie we prefer the longer prev_length
best_combined_gain = combined_gain;
best_prev_length = s->strstart - strstart + 1;
}
s->strstart++;
s->lookahead--;
UPDATE_HASH(s, s->ins_h, s->window[(s->strstart) + (MIN_MATCH-1)]);
hash_head = s->head[s->ins_h];
// if (s->strstart - strstart + 1 == MIN_MATCH-1) { // a match with length == 2 is not possible
// s->strstart++;
// s->lookahead--;
// UPDATE_HASH(s, s->ins_h, s->window[(s->strstart) + (MIN_MATCH-1)]);
// hash_head = s->head[s->ins_h];
// }
} while (s->strstart <= strstart-1 + prev_length // try to truncate the previous match to 1, 3, ... prev_length
&& s->strstart <= s->window_size - MIN_LOOKAHEAD); // watch out for the end of the input
s->strstart = strstart_save;
s->lookahead = lookahead_save;
s->ins_h = ins_h_save;
s->match_length = current_match_length;
s->match_start = current_match_start;
if (prev_length >= MIN_MATCH) {
if (best_prev_length != prev_length && best_prev_length >= MIN_MATCH) {
printf("at %d, level %d: Reducing prev_length from %d to %d\n", s->strstart, level, prev_length, best_prev_length);
}
}
if (best_prev_length >= MIN_MATCH) {
s->prev_length = best_prev_length;
s->match_length = MIN_MATCH - 1;
} else {
s->prev_length = MIN_MATCH - 1;
}
return best_combined_gain;
}
#endif
#ifndef FASTEST
/* ===========================================================================
* Same as above, but achieves better compression. We use a lazy
@ -1757,11 +1859,16 @@ local block_state deflate_slow(s, flush)
INSERT_STRING(s, s->strstart, hash_head);
}
/* Find the longest match, discarding those <= prev_length.
*/
/* Find the longest match, discarding those <= prev_length. */
s->prev_length = s->match_length, s->prev_match = s->match_start;
s->match_length = MIN_MATCH-1;
#ifdef ZLIB_PM3_TUNED
if (s->prev_length < s->max_lazy_match) {
try_harder(s, s->strstart, s->lookahead, hash_head, 1);
}
#else
if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
s->strstart - hash_head <= MAX_DIST(s)) {
/* To simplify the code, we prevent matches with the string
@ -1784,6 +1891,7 @@ local block_state deflate_slow(s, flush)
s->match_length = MIN_MATCH-1;
}
}
#endif /* ZLIB_PM3_TUNED */
/* If there was a match at the previous step and the current
* match is not better, output the previous match:
*/

View file

@ -847,8 +847,8 @@ int flush;
break;
case 1: /* fixed block */
#ifdef ZLIB_PM3_TUNED
Dbprintf("FATAL error. Compressed FPGA files with fixed code blocks are not supported!");
for(;;);
strm->msg = (char *)"fixed block coding not supported";
state->mode = BAD;
#else
fixedtables(state);
Tracev((stderr, "inflate: fixed codes block%s\n",

View file

@ -989,7 +989,9 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
#ifdef DEBUG
s->compressed_len += 3 + s->opt_len;
#endif
#ifndef ZLIB_PM3_TUNED
}
#endif
Assert (s->compressed_len == s->bits_sent, "bad compressed size");
/* The above check is made mod 2^32, for files larger than 512 MB
* and uLong implemented on 32 bits.