- unsigned num_possible_matches;
- struct raw_match *possible_matches;
- struct raw_match match;
- unsigned longest_match_len;
-
- if (ctx->optimum_cur_idx != ctx->optimum_end_idx) {
- /* Case 2: Return the next match/literal already found. */
- match.len = ctx->optimum[ctx->optimum_cur_idx].next.link -
- ctx->optimum_cur_idx;
- match.offset = ctx->optimum[ctx->optimum_cur_idx].next.match_offset;
-
- ctx->optimum_cur_idx = ctx->optimum[ctx->optimum_cur_idx].next.link;
- return match;
+ LZX_ASSERT(num_matches > 0);
+
+ unsigned i;
+ unsigned len;
+ unsigned offset_slot;
+ u32 position_cost;
+ u32 cost;
+ u32 offset_data;
+
+
+#if 1 /* Optimized version */
+
+ if (matches[num_matches - 1].offset < LZX_NUM_FAST_OFFSETS) {
+
+ /*
+ * Offset is small; the offset slot can be looked up directly in
+ * c->offset_slot_fast.
+ *
+ * Additional optimizations:
+ *
+ * - Since the offset is small, it falls in the exponential part
+ * of the offset slot bases and the number of extra offset
+ * bits can be calculated directly as (offset_slot >> 1) - 1.
+ *
+ * - Just consider the number of extra offset bits; don't
+ * account for the aligned offset code. Usually this has
+ * almost no effect on the compression ratio.
+ *
+ * - Start out in a loop optimized for small lengths. When the
+ * length becomes high enough that a length symbol will be
+ * needed, jump into a loop optimized for big lengths.
+ */
+
+ LZX_ASSERT(offset_slot <= 37); /* for extra bits formula */
+
+ len = 2;
+ i = 0;
+ do {
+ offset_slot = c->offset_slot_fast[matches[i].offset];
+ position_cost = cur_optimum_ptr->cost +
+ ((offset_slot >> 1) - 1);
+ offset_data = matches[i].offset + LZX_OFFSET_OFFSET;
+ do {
+ if (len >= LZX_MIN_MATCH_LEN + LZX_NUM_PRIMARY_LENS)
+ goto biglen;
+ cost = position_cost +
+ lzx_match_cost_raw_smalllen(len, offset_slot,
+ &c->costs);
+ if (cost < (cur_optimum_ptr + len)->cost) {
+ (cur_optimum_ptr + len)->cost = cost;
+ (cur_optimum_ptr + len)->mc_item_data =
+ (offset_data << MC_OFFSET_SHIFT) | len;
+ }
+ } while (++len <= matches[i].len);
+ } while (++i != num_matches);
+
+ return;
+
+ do {
+ offset_slot = c->offset_slot_fast[matches[i].offset];
+ biglen:
+ position_cost = cur_optimum_ptr->cost +
+ ((offset_slot >> 1) - 1) +
+ c->costs.main[LZX_NUM_CHARS +
+ ((offset_slot << 3) |
+ LZX_NUM_PRIMARY_LENS)];
+ offset_data = matches[i].offset + LZX_OFFSET_OFFSET;
+ do {
+ cost = position_cost +
+ c->costs.len[len - LZX_MIN_MATCH_LEN -
+ LZX_NUM_PRIMARY_LENS];
+ if (cost < (cur_optimum_ptr + len)->cost) {
+ (cur_optimum_ptr + len)->cost = cost;
+ (cur_optimum_ptr + len)->mc_item_data =
+ (offset_data << MC_OFFSET_SHIFT) | len;
+ }
+ } while (++len <= matches[i].len);
+ } while (++i != num_matches);
+ } else {
+ len = 2;
+ i = 0;
+ do {
+ offset_data = matches[i].offset + LZX_OFFSET_OFFSET;
+ offset_slot = lzx_get_offset_slot_raw(offset_data);
+ position_cost = cur_optimum_ptr->cost +
+ lzx_extra_offset_bits[offset_slot];
+ do {
+ cost = position_cost +
+ lzx_match_cost_raw(len, offset_slot, &c->costs);
+ if (cost < (cur_optimum_ptr + len)->cost) {
+ (cur_optimum_ptr + len)->cost = cost;
+ (cur_optimum_ptr + len)->mc_item_data =
+ (offset_data << MC_OFFSET_SHIFT) | len;
+ }
+ } while (++len <= matches[i].len);
+ } while (++i != num_matches);