+static u32
+lzms_get_lz_match_cost(struct lzms_compressor *ctx,
+ struct lzms_adaptive_state *state,
+ input_idx_t length, input_idx_t offset)
+{
+ u32 cost = 0;
+ int recent_offset_idx;
+
+ cost += lzms_rc_bit_cost(&ctx->main_range_encoder,
+ &state->main_state, 1);
+ cost += lzms_rc_bit_cost(&ctx->match_range_encoder,
+ &state->match_state, 0);
+
+ for (recent_offset_idx = 0;
+ recent_offset_idx < LZMS_NUM_RECENT_OFFSETS;
+ recent_offset_idx++)
+ if (offset == state->lru.recent_offsets[recent_offset_idx])
+ break;
+
+ if (recent_offset_idx == LZMS_NUM_RECENT_OFFSETS) {
+ /* Explicit offset. */
+ cost += lzms_rc_bit_cost(&ctx->lz_match_range_encoder,
+ &state->lz_match_state, 0);
+
+ cost += lzms_offset_cost(&ctx->lz_offset_encoder, offset);
+ } else {
+ int i;
+
+ /* Recent offset. */
+ cost += lzms_rc_bit_cost(&ctx->lz_match_range_encoder,
+ &state->lz_match_state, 1);
+
+ for (i = 0; i < recent_offset_idx; i++)
+ cost += lzms_rc_bit_cost(&ctx->lz_repeat_match_range_encoders[i],
+ &state->lz_repeat_match_state[i], 0);
+
+ if (i < LZMS_NUM_RECENT_OFFSETS - 1)
+ cost += lzms_rc_bit_cost(&ctx->lz_repeat_match_range_encoders[i],
+ &state->lz_repeat_match_state[i], 1);
+
+
+ /* Initial update of the LZ match offset LRU queue. */
+ for (; i < LZMS_NUM_RECENT_OFFSETS; i++)
+ state->lru.recent_offsets[i] = state->lru.recent_offsets[i + 1];
+ }
+
+ cost += lzms_length_cost(&ctx->length_encoder, length);
+
+ state->lru.upcoming_offset = offset;
+ lzms_update_lz_lru_queues(&state->lru);
+
+ return cost;
+}
+
+static struct raw_match
+lzms_get_near_optimal_match(struct lzms_compressor *ctx)
+{
+ struct lzms_adaptive_state initial_state;
+
+ initial_state.lru = ctx->lru.lz;
+ initial_state.main_state = ctx->main_range_encoder.state;
+ initial_state.match_state = ctx->match_range_encoder.state;
+ initial_state.lz_match_state = ctx->lz_match_range_encoder.state;
+ for (int i = 0; i < LZMS_NUM_RECENT_OFFSETS - 1; i++)
+ initial_state.lz_repeat_match_state[i] =
+ ctx->lz_repeat_match_range_encoders[i].state;
+ return lz_get_near_optimal_match(&ctx->mc,
+ lzms_get_matches,
+ lzms_skip_bytes,
+ lzms_get_prev_literal_cost,
+ lzms_get_lz_match_cost,
+ ctx,
+ &initial_state);