Reorganize some code in deflate_compress_near_optimal()

This commit is contained in:
Eric Biggers 2016-05-21 10:33:58 -05:00
parent a11c44317b
commit 00bf9daff9

View File

@ -25,7 +25,7 @@
/* /*
* Note: when compiling this file, SUPPORT_NEAR_OPTIMAL_PARSING should be * Note: when compiling this file, SUPPORT_NEAR_OPTIMAL_PARSING should be
* defined to either 0 or 1. When defined to 1, the near-optimal parsing * defined to either 0 or 1. When defined to 1, the near-optimal parsing
* algorithm is enabled at compression level 80 and above. The near-optimal * algorithm is enabled at compression level 8 and above. The near-optimal
* parsing algorithm produces a compression ratio significantly better than the * parsing algorithm produces a compression ratio significantly better than the
* greedy and lazy algorithms implemented here, and also the algorithm used by * greedy and lazy algorithms implemented here, and also the algorithm used by
* zlib at level 9. However, it is slow. * zlib at level 9. However, it is slow.
@ -2190,52 +2190,29 @@ deflate_compress_near_optimal(struct deflate_compressor * restrict c,
const u8 *in_next = in; const u8 *in_next = in;
const u8 *in_end = in_next + in_nbytes; const u8 *in_end = in_next + in_nbytes;
struct deflate_output_bitstream os; struct deflate_output_bitstream os;
const u8 *in_cur_base; const u8 *in_cur_base = in_next;
const u8 *in_next_slide; const u8 *in_next_slide = in_next + MIN(in_end - in_next, MATCHFINDER_WINDOW_SIZE);
unsigned max_len; unsigned max_len = DEFLATE_MAX_MATCH_LEN;
unsigned nice_len; unsigned nice_len = MIN(c->nice_match_length, max_len);
struct lz_match *cache_ptr;
struct lz_match *cache_end;
const u8 *in_block_begin;
const u8 *in_block_end;
u32 next_hashes[2] = {0, 0}; u32 next_hashes[2] = {0, 0};
deflate_init_output(&os, out, out_nbytes_avail); deflate_init_output(&os, out, out_nbytes_avail);
deflate_reset_symbol_frequencies(c); deflate_reset_symbol_frequencies(c);
bt_matchfinder_init(&c->bt_mf); bt_matchfinder_init(&c->bt_mf);
in_cur_base = in_next;
in_next_slide = in_next + MIN(in_end - in_next, MATCHFINDER_WINDOW_SIZE);
max_len = DEFLATE_MAX_MATCH_LEN;
nice_len = MIN(c->nice_match_length, max_len);
do { do {
/* Starting a new DEFLATE block. */ /* Starting a new DEFLATE block. */
cache_ptr = c->cached_matches; struct lz_match *cache_ptr = c->cached_matches;
cache_end = &c->cached_matches[CACHE_LEN - (MAX_MATCHES_PER_POS + 1)]; struct lz_match * const cache_end = &c->cached_matches[CACHE_LEN - (MAX_MATCHES_PER_POS + 1)];
in_block_begin = in_next; const u8 * const in_block_begin = in_next;
in_block_end = in_next + MIN(in_end - in_next, OPTIM_BLOCK_LENGTH); const u8 * const in_block_end = in_next + MIN(in_end - in_next, OPTIM_BLOCK_LENGTH);
/* Set the initial cost model. */
if (in_next == in)
deflate_set_default_costs(c);
else
deflate_adjust_costs(c);
/* Find all match possibilities in this block. */ /* Find all match possibilities in this block. */
do { do {
struct lz_match *matches; struct lz_match *matches;
unsigned best_len; unsigned best_len;
/* Decrease the maximum and nice match lengths if we're
* approaching the end of the input buffer. */
if (unlikely(max_len > in_end - in_next)) {
max_len = in_end - in_next;
nice_len = MIN(max_len, nice_len);
}
/* Force the block to end if the match cache may /* Force the block to end if the match cache may
* overflow. This case is very unlikely. */ * overflow. This case is very unlikely. */
if (unlikely(cache_ptr > cache_end)) if (unlikely(cache_ptr > cache_end))
@ -2249,6 +2226,13 @@ deflate_compress_near_optimal(struct deflate_compressor * restrict c,
MATCHFINDER_WINDOW_SIZE); MATCHFINDER_WINDOW_SIZE);
} }
/* Decrease the maximum and nice match lengths if we're
* approaching the end of the input buffer. */
if (unlikely(max_len > in_end - in_next)) {
max_len = in_end - in_next;
nice_len = MIN(nice_len, max_len);
}
/* /*
* Find matches with the current position using the * Find matches with the current position using the
* binary tree matchfinder and save them in * binary tree matchfinder and save them in
@ -2267,10 +2251,8 @@ deflate_compress_near_optimal(struct deflate_compressor * restrict c,
* advantage of hash chains is negated. * advantage of hash chains is negated.
*/ */
matches = cache_ptr; matches = cache_ptr;
if (max_len < BT_MATCHFINDER_REQUIRED_NBYTES) { best_len = 0;
best_len = 0; if (likely(max_len >= BT_MATCHFINDER_REQUIRED_NBYTES)) {
cache_ptr = matches;
} else {
cache_ptr = bt_matchfinder_get_matches(&c->bt_mf, cache_ptr = bt_matchfinder_get_matches(&c->bt_mf,
in_cur_base, in_cur_base,
in_next - in_cur_base, in_next - in_cur_base,
@ -2308,16 +2290,16 @@ deflate_compress_near_optimal(struct deflate_compressor * restrict c,
best_len >= MIN(nice_len, in_block_end - in_next)) { best_len >= MIN(nice_len, in_block_end - in_next)) {
--best_len; --best_len;
do { do {
if (unlikely(max_len > in_end - in_next)) {
max_len = in_end - in_next;
nice_len = MIN(max_len, nice_len);
}
if (in_next == in_next_slide) { if (in_next == in_next_slide) {
bt_matchfinder_slide_window(&c->bt_mf); bt_matchfinder_slide_window(&c->bt_mf);
in_cur_base = in_next; in_cur_base = in_next;
in_next_slide = in_next + MIN(in_end - in_next, in_next_slide = in_next + MIN(in_end - in_next,
MATCHFINDER_WINDOW_SIZE); MATCHFINDER_WINDOW_SIZE);
} }
if (unlikely(max_len > in_end - in_next)) {
max_len = in_end - in_next;
nice_len = MIN(nice_len, max_len);
}
if (max_len >= BT_MATCHFINDER_REQUIRED_NBYTES) { if (max_len >= BT_MATCHFINDER_REQUIRED_NBYTES) {
bt_matchfinder_skip_position(&c->bt_mf, bt_matchfinder_skip_position(&c->bt_mf,
in_cur_base, in_cur_base,
@ -2338,7 +2320,10 @@ deflate_compress_near_optimal(struct deflate_compressor * restrict c,
/* All the matches for this block have been cached. Now compute /* All the matches for this block have been cached. Now compute
* a near-optimal sequence of literals and matches, and output * a near-optimal sequence of literals and matches, and output
* the block. */ * the block. */
if (in_block_begin == in)
deflate_set_default_costs(c);
else
deflate_adjust_costs(c);
deflate_optimize_and_write_block(c, &os, in_next - in_block_begin, deflate_optimize_and_write_block(c, &os, in_next - in_block_begin,
cache_ptr, in_next == in_end); cache_ptr, in_next == in_end);
} while (in_next != in_end); } while (in_next != in_end);