+lzms_skip_bytes(struct lzms_compressor *ctx, input_idx_t n)
+{
+ while (n--)
+ lz_sarray_skip_position(&ctx->lz_sarray);
+}
+
+static u32
+lzms_get_prev_literal_cost(struct lzms_compressor *ctx,
+ struct lzms_adaptive_state *state)
+{
+ u8 literal = ctx->window[lz_sarray_get_pos(&ctx->lz_sarray) - 1];
+ u32 cost = 0;
+
+ state->lru.upcoming_offset = 0;
+ lzms_update_lz_lru_queues(&state->lru);
+
+ cost += lzms_rc_bit_cost(&ctx->main_range_encoder,
+ &state->main_state, 0);
+
+ cost += lzms_huffman_symbol_cost(&ctx->literal_encoder, literal);
+
+ return cost;
+}
+
+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);
+}
+
+/*
+ * The main loop for the LZMS compressor.
+ *
+ * Notes:
+ *
+ * - This uses near-optimal LZ parsing backed by a suffix-array match-finder.
+ * More details can be found in the corresponding files (lz_optimal.h,
+ * lz_sarray.{h,c}).
+ *
+ * - This does not output any delta matches. It would take a specialized
+ * algorithm to find them, then more code in lz_optimal.h and here to handle
+ * evaluating and outputting them.
+ *
+ * - The costs of literals and matches are estimated using the range encoder
+ * states and the semi-adaptive Huffman codes. Except for range encoding
+ * states, costs are assumed to be constant throughout a single run of the
+ * parsing algorithm, which can parse up to @optim_array_length (from the
+ * `struct wimlib_lzms_compressor_params') bytes of data. This introduces a
+ * source of inaccuracy because the probabilities and Huffman codes can change
+ * over this part of the data.
+ */