Home | History | Annotate | Download | only in enc
      1 /* Copyright 2013 Google Inc. All Rights Reserved.
      2 
      3    Distributed under MIT license.
      4    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
      5 */
      6 
      7 /* Function to find backward reference copies. */
      8 
      9 #include "./backward_references_hq.h"
     10 
     11 #include <string.h>  /* memcpy, memset */
     12 
     13 #include "../common/constants.h"
     14 #include <brotli/types.h>
     15 #include "./command.h"
     16 #include "./fast_log.h"
     17 #include "./find_match_length.h"
     18 #include "./literal_cost.h"
     19 #include "./memory.h"
     20 #include "./port.h"
     21 #include "./prefix.h"
     22 #include "./quality.h"
     23 
     24 #if defined(__cplusplus) || defined(c_plusplus)
     25 extern "C" {
     26 #endif
     27 
     28 static const float kInfinity = 1.7e38f;  /* ~= 2 ^ 127 */
     29 
     30 static const uint32_t kDistanceCacheIndex[] = {
     31   0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
     32 };
     33 static const int kDistanceCacheOffset[] = {
     34   0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3
     35 };
     36 
     37 void BrotliInitZopfliNodes(ZopfliNode* array, size_t length) {
     38   ZopfliNode stub;
     39   size_t i;
     40   stub.length = 1;
     41   stub.distance = 0;
     42   stub.insert_length = 0;
     43   stub.u.cost = kInfinity;
     44   for (i = 0; i < length; ++i) array[i] = stub;
     45 }
     46 
     47 static BROTLI_INLINE uint32_t ZopfliNodeCopyLength(const ZopfliNode* self) {
     48   return self->length & 0xffffff;
     49 }
     50 
     51 static BROTLI_INLINE uint32_t ZopfliNodeLengthCode(const ZopfliNode* self) {
     52   const uint32_t modifier = self->length >> 24;
     53   return ZopfliNodeCopyLength(self) + 9u - modifier;
     54 }
     55 
     56 static BROTLI_INLINE uint32_t ZopfliNodeCopyDistance(const ZopfliNode* self) {
     57   return self->distance & 0x1ffffff;
     58 }
     59 
     60 static BROTLI_INLINE uint32_t ZopfliNodeDistanceCode(const ZopfliNode* self) {
     61   const uint32_t short_code = self->distance >> 25;
     62   return short_code == 0 ?
     63       ZopfliNodeCopyDistance(self) + BROTLI_NUM_DISTANCE_SHORT_CODES - 1 :
     64       short_code - 1;
     65 }
     66 
     67 static BROTLI_INLINE uint32_t ZopfliNodeCommandLength(const ZopfliNode* self) {
     68   return ZopfliNodeCopyLength(self) + self->insert_length;
     69 }
     70 
     71 /* Histogram based cost model for zopflification. */
     72 typedef struct ZopfliCostModel {
     73   /* The insert and copy length symbols. */
     74   float cost_cmd_[BROTLI_NUM_COMMAND_SYMBOLS];
     75   float cost_dist_[BROTLI_NUM_DISTANCE_SYMBOLS];
     76   /* Cumulative costs of literals per position in the stream. */
     77   float* literal_costs_;
     78   float min_cost_cmd_;
     79   size_t num_bytes_;
     80 } ZopfliCostModel;
     81 
     82 static void InitZopfliCostModel(
     83     MemoryManager* m, ZopfliCostModel* self, size_t num_bytes) {
     84   self->num_bytes_ = num_bytes;
     85   self->literal_costs_ = BROTLI_ALLOC(m, float, num_bytes + 2);
     86   if (BROTLI_IS_OOM(m)) return;
     87 }
     88 
     89 static void CleanupZopfliCostModel(MemoryManager* m, ZopfliCostModel* self) {
     90   BROTLI_FREE(m, self->literal_costs_);
     91 }
     92 
     93 static void SetCost(const uint32_t* histogram, size_t histogram_size,
     94                     float* cost) {
     95   size_t sum = 0;
     96   float log2sum;
     97   size_t i;
     98   for (i = 0; i < histogram_size; i++) {
     99     sum += histogram[i];
    100   }
    101   log2sum = (float)FastLog2(sum);
    102   for (i = 0; i < histogram_size; i++) {
    103     if (histogram[i] == 0) {
    104       cost[i] = log2sum + 2;
    105       continue;
    106     }
    107 
    108     /* Shannon bits for this symbol. */
    109     cost[i] = log2sum - (float)FastLog2(histogram[i]);
    110 
    111     /* Cannot be coded with less than 1 bit */
    112     if (cost[i] < 1) cost[i] = 1;
    113   }
    114 }
    115 
    116 static void ZopfliCostModelSetFromCommands(ZopfliCostModel* self,
    117                                            size_t position,
    118                                            const uint8_t* ringbuffer,
    119                                            size_t ringbuffer_mask,
    120                                            const Command* commands,
    121                                            size_t num_commands,
    122                                            size_t last_insert_len) {
    123   uint32_t histogram_literal[BROTLI_NUM_LITERAL_SYMBOLS];
    124   uint32_t histogram_cmd[BROTLI_NUM_COMMAND_SYMBOLS];
    125   uint32_t histogram_dist[BROTLI_NUM_DISTANCE_SYMBOLS];
    126   float cost_literal[BROTLI_NUM_LITERAL_SYMBOLS];
    127   size_t pos = position - last_insert_len;
    128   float min_cost_cmd = kInfinity;
    129   size_t i;
    130   float* cost_cmd = self->cost_cmd_;
    131 
    132   memset(histogram_literal, 0, sizeof(histogram_literal));
    133   memset(histogram_cmd, 0, sizeof(histogram_cmd));
    134   memset(histogram_dist, 0, sizeof(histogram_dist));
    135 
    136   for (i = 0; i < num_commands; i++) {
    137     size_t inslength = commands[i].insert_len_;
    138     size_t copylength = CommandCopyLen(&commands[i]);
    139     size_t distcode = commands[i].dist_prefix_;
    140     size_t cmdcode = commands[i].cmd_prefix_;
    141     size_t j;
    142 
    143     histogram_cmd[cmdcode]++;
    144     if (cmdcode >= 128) histogram_dist[distcode]++;
    145 
    146     for (j = 0; j < inslength; j++) {
    147       histogram_literal[ringbuffer[(pos + j) & ringbuffer_mask]]++;
    148     }
    149 
    150     pos += inslength + copylength;
    151   }
    152 
    153   SetCost(histogram_literal, BROTLI_NUM_LITERAL_SYMBOLS, cost_literal);
    154   SetCost(histogram_cmd, BROTLI_NUM_COMMAND_SYMBOLS, cost_cmd);
    155   SetCost(histogram_dist, BROTLI_NUM_DISTANCE_SYMBOLS, self->cost_dist_);
    156 
    157   for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) {
    158     min_cost_cmd = BROTLI_MIN(float, min_cost_cmd, cost_cmd[i]);
    159   }
    160   self->min_cost_cmd_ = min_cost_cmd;
    161 
    162   {
    163     float* literal_costs = self->literal_costs_;
    164     size_t num_bytes = self->num_bytes_;
    165     literal_costs[0] = 0.0;
    166     for (i = 0; i < num_bytes; ++i) {
    167       literal_costs[i + 1] = literal_costs[i] +
    168           cost_literal[ringbuffer[(position + i) & ringbuffer_mask]];
    169     }
    170   }
    171 }
    172 
    173 static void ZopfliCostModelSetFromLiteralCosts(ZopfliCostModel* self,
    174                                                size_t position,
    175                                                const uint8_t* ringbuffer,
    176                                                size_t ringbuffer_mask) {
    177   float* literal_costs = self->literal_costs_;
    178   float* cost_dist = self->cost_dist_;
    179   float* cost_cmd = self->cost_cmd_;
    180   size_t num_bytes = self->num_bytes_;
    181   size_t i;
    182   BrotliEstimateBitCostsForLiterals(position, num_bytes, ringbuffer_mask,
    183                                     ringbuffer, &literal_costs[1]);
    184   literal_costs[0] = 0.0;
    185   for (i = 0; i < num_bytes; ++i) {
    186     literal_costs[i + 1] += literal_costs[i];
    187   }
    188   for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) {
    189     cost_cmd[i] = (float)FastLog2(11 + (uint32_t)i);
    190   }
    191   for (i = 0; i < BROTLI_NUM_DISTANCE_SYMBOLS; ++i) {
    192     cost_dist[i] = (float)FastLog2(20 + (uint32_t)i);
    193   }
    194   self->min_cost_cmd_ = (float)FastLog2(11);
    195 }
    196 
    197 static BROTLI_INLINE float ZopfliCostModelGetCommandCost(
    198     const ZopfliCostModel* self, uint16_t cmdcode) {
    199   return self->cost_cmd_[cmdcode];
    200 }
    201 
    202 static BROTLI_INLINE float ZopfliCostModelGetDistanceCost(
    203     const ZopfliCostModel* self, size_t distcode) {
    204   return self->cost_dist_[distcode];
    205 }
    206 
    207 static BROTLI_INLINE float ZopfliCostModelGetLiteralCosts(
    208     const ZopfliCostModel* self, size_t from, size_t to) {
    209   return self->literal_costs_[to] - self->literal_costs_[from];
    210 }
    211 
    212 static BROTLI_INLINE float ZopfliCostModelGetMinCostCmd(
    213     const ZopfliCostModel* self) {
    214   return self->min_cost_cmd_;
    215 }
    216 
    217 /* REQUIRES: len >= 2, start_pos <= pos */
    218 /* REQUIRES: cost < kInfinity, nodes[start_pos].cost < kInfinity */
    219 /* Maintains the "ZopfliNode array invariant". */
    220 static BROTLI_INLINE void UpdateZopfliNode(ZopfliNode* nodes, size_t pos,
    221     size_t start_pos, size_t len, size_t len_code, size_t dist,
    222     size_t short_code, float cost) {
    223   ZopfliNode* next = &nodes[pos + len];
    224   next->length = (uint32_t)(len | ((len + 9u - len_code) << 24));
    225   next->distance = (uint32_t)(dist | (short_code << 25));
    226   next->insert_length = (uint32_t)(pos - start_pos);
    227   next->u.cost = cost;
    228 }
    229 
    230 typedef struct PosData {
    231   size_t pos;
    232   int distance_cache[4];
    233   float costdiff;
    234   float cost;
    235 } PosData;
    236 
    237 /* Maintains the smallest 8 cost difference together with their positions */
    238 typedef struct StartPosQueue {
    239   PosData q_[8];
    240   size_t idx_;
    241 } StartPosQueue;
    242 
    243 static BROTLI_INLINE void InitStartPosQueue(StartPosQueue* self) {
    244   self->idx_ = 0;
    245 }
    246 
    247 static size_t StartPosQueueSize(const StartPosQueue* self) {
    248   return BROTLI_MIN(size_t, self->idx_, 8);
    249 }
    250 
    251 static void StartPosQueuePush(StartPosQueue* self, const PosData* posdata) {
    252   size_t offset = ~(self->idx_++) & 7;
    253   size_t len = StartPosQueueSize(self);
    254   size_t i;
    255   PosData* q = self->q_;
    256   q[offset] = *posdata;
    257   /* Restore the sorted order. In the list of |len| items at most |len - 1|
    258      adjacent element comparisons / swaps are required. */
    259   for (i = 1; i < len; ++i) {
    260     if (q[offset & 7].costdiff > q[(offset + 1) & 7].costdiff) {
    261       BROTLI_SWAP(PosData, q, offset & 7, (offset + 1) & 7);
    262     }
    263     ++offset;
    264   }
    265 }
    266 
    267 static const PosData* StartPosQueueAt(const StartPosQueue* self, size_t k) {
    268   return &self->q_[(k - self->idx_) & 7];
    269 }
    270 
    271 /* Returns the minimum possible copy length that can improve the cost of any */
    272 /* future position. */
    273 static size_t ComputeMinimumCopyLength(const float start_cost,
    274                                        const ZopfliNode* nodes,
    275                                        const size_t num_bytes,
    276                                        const size_t pos) {
    277   /* Compute the minimum possible cost of reaching any future position. */
    278   float min_cost = start_cost;
    279   size_t len = 2;
    280   size_t next_len_bucket = 4;
    281   size_t next_len_offset = 10;
    282   while (pos + len <= num_bytes && nodes[pos + len].u.cost <= min_cost) {
    283     /* We already reached (pos + len) with no more cost than the minimum
    284        possible cost of reaching anything from this pos, so there is no point in
    285        looking for lengths <= len. */
    286     ++len;
    287     if (len == next_len_offset) {
    288       /* We reached the next copy length code bucket, so we add one more
    289          extra bit to the minimum cost. */
    290       min_cost += 1.0f;
    291       next_len_offset += next_len_bucket;
    292       next_len_bucket *= 2;
    293     }
    294   }
    295   return len;
    296 }
    297 
    298 /* REQUIRES: nodes[pos].cost < kInfinity
    299    REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */
    300 static uint32_t ComputeDistanceShortcut(const size_t block_start,
    301                                         const size_t pos,
    302                                         const size_t max_backward,
    303                                         const ZopfliNode* nodes) {
    304   const size_t clen = ZopfliNodeCopyLength(&nodes[pos]);
    305   const size_t ilen = nodes[pos].insert_length;
    306   const size_t dist = ZopfliNodeCopyDistance(&nodes[pos]);
    307   /* Since |block_start + pos| is the end position of the command, the copy part
    308      starts from |block_start + pos - clen|. Distances that are greater than
    309      this or greater than |max_backward| are static dictionary references, and
    310      do not update the last distances. Also distance code 0 (last distance)
    311      does not update the last distances. */
    312   if (pos == 0) {
    313     return 0;
    314   } else if (dist + clen <= block_start + pos &&
    315              dist <= max_backward &&
    316              ZopfliNodeDistanceCode(&nodes[pos]) > 0) {
    317     return (uint32_t)pos;
    318   } else {
    319     return nodes[pos - clen - ilen].u.shortcut;
    320   }
    321 }
    322 
    323 /* Fills in dist_cache[0..3] with the last four distances (as defined by
    324    Section 4. of the Spec) that would be used at (block_start + pos) if we
    325    used the shortest path of commands from block_start, computed from
    326    nodes[0..pos]. The last four distances at block_start are in
    327    starting_dist_cache[0..3].
    328    REQUIRES: nodes[pos].cost < kInfinity
    329    REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */
    330 static void ComputeDistanceCache(const size_t pos,
    331                                  const int* starting_dist_cache,
    332                                  const ZopfliNode* nodes,
    333                                  int* dist_cache) {
    334   int idx = 0;
    335   size_t p = nodes[pos].u.shortcut;
    336   while (idx < 4 && p > 0) {
    337     const size_t ilen = nodes[p].insert_length;
    338     const size_t clen = ZopfliNodeCopyLength(&nodes[p]);
    339     const size_t dist = ZopfliNodeCopyDistance(&nodes[p]);
    340     dist_cache[idx++] = (int)dist;
    341     /* Because of prerequisite, p >= clen + ilen >= 2. */
    342     p = nodes[p - clen - ilen].u.shortcut;
    343   }
    344   for (; idx < 4; ++idx) {
    345     dist_cache[idx] = *starting_dist_cache++;
    346   }
    347 }
    348 
    349 /* Maintains "ZopfliNode array invariant" and pushes node to the queue, if it
    350    is eligible. */
    351 static void EvaluateNode(
    352     const size_t block_start, const size_t pos, const size_t max_backward_limit,
    353     const int* starting_dist_cache, const ZopfliCostModel* model,
    354     StartPosQueue* queue, ZopfliNode* nodes) {
    355   /* Save cost, because ComputeDistanceCache invalidates it. */
    356   float node_cost = nodes[pos].u.cost;
    357   nodes[pos].u.shortcut = ComputeDistanceShortcut(
    358       block_start, pos, max_backward_limit, nodes);
    359   if (node_cost <= ZopfliCostModelGetLiteralCosts(model, 0, pos)) {
    360     PosData posdata;
    361     posdata.pos = pos;
    362     posdata.cost = node_cost;
    363     posdata.costdiff = node_cost -
    364         ZopfliCostModelGetLiteralCosts(model, 0, pos);
    365     ComputeDistanceCache(
    366         pos, starting_dist_cache, nodes, posdata.distance_cache);
    367     StartPosQueuePush(queue, &posdata);
    368   }
    369 }
    370 
    371 /* Returns longest copy length. */
    372 static size_t UpdateNodes(
    373     const size_t num_bytes, const size_t block_start, const size_t pos,
    374     const uint8_t* ringbuffer, const size_t ringbuffer_mask,
    375     const BrotliEncoderParams* params, const size_t max_backward_limit,
    376     const int* starting_dist_cache, const size_t num_matches,
    377     const BackwardMatch* matches, const ZopfliCostModel* model,
    378     StartPosQueue* queue, ZopfliNode* nodes) {
    379   const size_t cur_ix = block_start + pos;
    380   const size_t cur_ix_masked = cur_ix & ringbuffer_mask;
    381   const size_t max_distance = BROTLI_MIN(size_t, cur_ix, max_backward_limit);
    382   const size_t max_len = num_bytes - pos;
    383   const size_t max_zopfli_len = MaxZopfliLen(params);
    384   const size_t max_iters = MaxZopfliCandidates(params);
    385   size_t min_len;
    386   size_t result = 0;
    387   size_t k;
    388 
    389   EvaluateNode(block_start, pos, max_backward_limit, starting_dist_cache, model,
    390                queue, nodes);
    391 
    392   {
    393     const PosData* posdata = StartPosQueueAt(queue, 0);
    394     float min_cost = (posdata->cost + ZopfliCostModelGetMinCostCmd(model) +
    395         ZopfliCostModelGetLiteralCosts(model, posdata->pos, pos));
    396     min_len = ComputeMinimumCopyLength(min_cost, nodes, num_bytes, pos);
    397   }
    398 
    399   /* Go over the command starting positions in order of increasing cost
    400      difference. */
    401   for (k = 0; k < max_iters && k < StartPosQueueSize(queue); ++k) {
    402     const PosData* posdata = StartPosQueueAt(queue, k);
    403     const size_t start = posdata->pos;
    404     const uint16_t inscode = GetInsertLengthCode(pos - start);
    405     const float start_costdiff = posdata->costdiff;
    406     const float base_cost = start_costdiff + (float)GetInsertExtra(inscode) +
    407         ZopfliCostModelGetLiteralCosts(model, 0, pos);
    408 
    409     /* Look for last distance matches using the distance cache from this
    410        starting position. */
    411     size_t best_len = min_len - 1;
    412     size_t j = 0;
    413     for (; j < BROTLI_NUM_DISTANCE_SHORT_CODES && best_len < max_len; ++j) {
    414       const size_t idx = kDistanceCacheIndex[j];
    415       const size_t backward =
    416           (size_t)(posdata->distance_cache[idx] + kDistanceCacheOffset[j]);
    417       size_t prev_ix = cur_ix - backward;
    418       if (prev_ix >= cur_ix) {
    419         continue;
    420       }
    421       if (BROTLI_PREDICT_FALSE(backward > max_distance)) {
    422         continue;
    423       }
    424       prev_ix &= ringbuffer_mask;
    425 
    426       if (cur_ix_masked + best_len > ringbuffer_mask ||
    427           prev_ix + best_len > ringbuffer_mask ||
    428           ringbuffer[cur_ix_masked + best_len] !=
    429               ringbuffer[prev_ix + best_len]) {
    430         continue;
    431       }
    432       {
    433         const size_t len =
    434             FindMatchLengthWithLimit(&ringbuffer[prev_ix],
    435                                      &ringbuffer[cur_ix_masked],
    436                                      max_len);
    437         const float dist_cost = base_cost +
    438             ZopfliCostModelGetDistanceCost(model, j);
    439         size_t l;
    440         for (l = best_len + 1; l <= len; ++l) {
    441           const uint16_t copycode = GetCopyLengthCode(l);
    442           const uint16_t cmdcode =
    443               CombineLengthCodes(inscode, copycode, j == 0);
    444           const float cost = (cmdcode < 128 ? base_cost : dist_cost) +
    445               (float)GetCopyExtra(copycode) +
    446               ZopfliCostModelGetCommandCost(model, cmdcode);
    447           if (cost < nodes[pos + l].u.cost) {
    448             UpdateZopfliNode(nodes, pos, start, l, l, backward, j + 1, cost);
    449             result = BROTLI_MAX(size_t, result, l);
    450           }
    451           best_len = l;
    452         }
    453       }
    454     }
    455 
    456     /* At higher iterations look only for new last distance matches, since
    457        looking only for new command start positions with the same distances
    458        does not help much. */
    459     if (k >= 2) continue;
    460 
    461     {
    462       /* Loop through all possible copy lengths at this position. */
    463       size_t len = min_len;
    464       for (j = 0; j < num_matches; ++j) {
    465         BackwardMatch match = matches[j];
    466         size_t dist = match.distance;
    467         BROTLI_BOOL is_dictionary_match = TO_BROTLI_BOOL(dist > max_distance);
    468         /* We already tried all possible last distance matches, so we can use
    469            normal distance code here. */
    470         size_t dist_code = dist + BROTLI_NUM_DISTANCE_SHORT_CODES - 1;
    471         uint16_t dist_symbol;
    472         uint32_t distextra;
    473         uint32_t distnumextra;
    474         float dist_cost;
    475         size_t max_match_len;
    476         PrefixEncodeCopyDistance(dist_code, 0, 0, &dist_symbol, &distextra);
    477         distnumextra = distextra >> 24;
    478         dist_cost = base_cost + (float)distnumextra +
    479             ZopfliCostModelGetDistanceCost(model, dist_symbol);
    480 
    481         /* Try all copy lengths up until the maximum copy length corresponding
    482            to this distance. If the distance refers to the static dictionary, or
    483            the maximum length is long enough, try only one maximum length. */
    484         max_match_len = BackwardMatchLength(&match);
    485         if (len < max_match_len &&
    486             (is_dictionary_match || max_match_len > max_zopfli_len)) {
    487           len = max_match_len;
    488         }
    489         for (; len <= max_match_len; ++len) {
    490           const size_t len_code =
    491               is_dictionary_match ? BackwardMatchLengthCode(&match) : len;
    492           const uint16_t copycode = GetCopyLengthCode(len_code);
    493           const uint16_t cmdcode = CombineLengthCodes(inscode, copycode, 0);
    494           const float cost = dist_cost + (float)GetCopyExtra(copycode) +
    495               ZopfliCostModelGetCommandCost(model, cmdcode);
    496           if (cost < nodes[pos + len].u.cost) {
    497             UpdateZopfliNode(nodes, pos, start, len, len_code, dist, 0, cost);
    498             result = BROTLI_MAX(size_t, result, len);
    499           }
    500         }
    501       }
    502     }
    503   }
    504   return result;
    505 }
    506 
    507 static size_t ComputeShortestPathFromNodes(size_t num_bytes,
    508     ZopfliNode* nodes) {
    509   size_t index = num_bytes;
    510   size_t num_commands = 0;
    511   while (nodes[index].insert_length == 0 && nodes[index].length == 1) --index;
    512   nodes[index].u.next = BROTLI_UINT32_MAX;
    513   while (index != 0) {
    514     size_t len = ZopfliNodeCommandLength(&nodes[index]);
    515     index -= len;
    516     nodes[index].u.next = (uint32_t)len;
    517     num_commands++;
    518   }
    519   return num_commands;
    520 }
    521 
    522 /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */
    523 void BrotliZopfliCreateCommands(const size_t num_bytes,
    524                                 const size_t block_start,
    525                                 const size_t max_backward_limit,
    526                                 const ZopfliNode* nodes,
    527                                 int* dist_cache,
    528                                 size_t* last_insert_len,
    529                                 Command* commands,
    530                                 size_t* num_literals) {
    531   size_t pos = 0;
    532   uint32_t offset = nodes[0].u.next;
    533   size_t i;
    534   for (i = 0; offset != BROTLI_UINT32_MAX; i++) {
    535     const ZopfliNode* next = &nodes[pos + offset];
    536     size_t copy_length = ZopfliNodeCopyLength(next);
    537     size_t insert_length = next->insert_length;
    538     pos += insert_length;
    539     offset = next->u.next;
    540     if (i == 0) {
    541       insert_length += *last_insert_len;
    542       *last_insert_len = 0;
    543     }
    544     {
    545       size_t distance = ZopfliNodeCopyDistance(next);
    546       size_t len_code = ZopfliNodeLengthCode(next);
    547       size_t max_distance =
    548           BROTLI_MIN(size_t, block_start + pos, max_backward_limit);
    549       BROTLI_BOOL is_dictionary = TO_BROTLI_BOOL(distance > max_distance);
    550       size_t dist_code = ZopfliNodeDistanceCode(next);
    551 
    552       InitCommand(
    553           &commands[i], insert_length, copy_length, len_code, dist_code);
    554 
    555       if (!is_dictionary && dist_code > 0) {
    556         dist_cache[3] = dist_cache[2];
    557         dist_cache[2] = dist_cache[1];
    558         dist_cache[1] = dist_cache[0];
    559         dist_cache[0] = (int)distance;
    560       }
    561     }
    562 
    563     *num_literals += insert_length;
    564     pos += copy_length;
    565   }
    566   *last_insert_len += num_bytes - pos;
    567 }
    568 
    569 static size_t ZopfliIterate(size_t num_bytes,
    570                             size_t position,
    571                             const uint8_t* ringbuffer,
    572                             size_t ringbuffer_mask,
    573                             const BrotliEncoderParams* params,
    574                             const size_t max_backward_limit,
    575                             const int* dist_cache,
    576                             const ZopfliCostModel* model,
    577                             const uint32_t* num_matches,
    578                             const BackwardMatch* matches,
    579                             ZopfliNode* nodes) {
    580   const size_t max_zopfli_len = MaxZopfliLen(params);
    581   StartPosQueue queue;
    582   size_t cur_match_pos = 0;
    583   size_t i;
    584   nodes[0].length = 0;
    585   nodes[0].u.cost = 0;
    586   InitStartPosQueue(&queue);
    587   for (i = 0; i + 3 < num_bytes; i++) {
    588     size_t skip = UpdateNodes(num_bytes, position, i, ringbuffer,
    589         ringbuffer_mask, params, max_backward_limit, dist_cache,
    590         num_matches[i], &matches[cur_match_pos], model, &queue, nodes);
    591     if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0;
    592     cur_match_pos += num_matches[i];
    593     if (num_matches[i] == 1 &&
    594         BackwardMatchLength(&matches[cur_match_pos - 1]) > max_zopfli_len) {
    595       skip = BROTLI_MAX(size_t,
    596           BackwardMatchLength(&matches[cur_match_pos - 1]), skip);
    597     }
    598     if (skip > 1) {
    599       skip--;
    600       while (skip) {
    601         i++;
    602         if (i + 3 >= num_bytes) break;
    603         EvaluateNode(
    604             position, i, max_backward_limit, dist_cache, model, &queue, nodes);
    605         cur_match_pos += num_matches[i];
    606         skip--;
    607       }
    608     }
    609   }
    610   return ComputeShortestPathFromNodes(num_bytes, nodes);
    611 }
    612 
    613 /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */
    614 size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
    615                                        const BrotliDictionary* dictionary,
    616                                        size_t num_bytes,
    617                                        size_t position,
    618                                        const uint8_t* ringbuffer,
    619                                        size_t ringbuffer_mask,
    620                                        const BrotliEncoderParams* params,
    621                                        const size_t max_backward_limit,
    622                                        const int* dist_cache,
    623                                        HasherHandle hasher,
    624                                        ZopfliNode* nodes) {
    625   const size_t max_zopfli_len = MaxZopfliLen(params);
    626   ZopfliCostModel model;
    627   StartPosQueue queue;
    628   BackwardMatch matches[MAX_NUM_MATCHES_H10];
    629   const size_t store_end = num_bytes >= StoreLookaheadH10() ?
    630       position + num_bytes - StoreLookaheadH10() + 1 : position;
    631   size_t i;
    632   nodes[0].length = 0;
    633   nodes[0].u.cost = 0;
    634   InitZopfliCostModel(m, &model, num_bytes);
    635   if (BROTLI_IS_OOM(m)) return 0;
    636   ZopfliCostModelSetFromLiteralCosts(
    637       &model, position, ringbuffer, ringbuffer_mask);
    638   InitStartPosQueue(&queue);
    639   for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; i++) {
    640     const size_t pos = position + i;
    641     const size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);
    642     size_t num_matches = FindAllMatchesH10(hasher, dictionary, ringbuffer,
    643         ringbuffer_mask, pos, num_bytes - i, max_distance, params, matches);
    644     size_t skip;
    645     if (num_matches > 0 &&
    646         BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len) {
    647       matches[0] = matches[num_matches - 1];
    648       num_matches = 1;
    649     }
    650     skip = UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask,
    651         params, max_backward_limit, dist_cache, num_matches, matches, &model,
    652         &queue, nodes);
    653     if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0;
    654     if (num_matches == 1 && BackwardMatchLength(&matches[0]) > max_zopfli_len) {
    655       skip = BROTLI_MAX(size_t, BackwardMatchLength(&matches[0]), skip);
    656     }
    657     if (skip > 1) {
    658       /* Add the tail of the copy to the hasher. */
    659       StoreRangeH10(hasher, ringbuffer, ringbuffer_mask, pos + 1, BROTLI_MIN(
    660           size_t, pos + skip, store_end));
    661       skip--;
    662       while (skip) {
    663         i++;
    664         if (i + HashTypeLengthH10() - 1 >= num_bytes) break;
    665         EvaluateNode(
    666             position, i, max_backward_limit, dist_cache, &model, &queue, nodes);
    667         skip--;
    668       }
    669     }
    670   }
    671   CleanupZopfliCostModel(m, &model);
    672   return ComputeShortestPathFromNodes(num_bytes, nodes);
    673 }
    674 
    675 void BrotliCreateZopfliBackwardReferences(
    676     MemoryManager* m, const BrotliDictionary* dictionary, size_t num_bytes,
    677     size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
    678     const BrotliEncoderParams* params, HasherHandle hasher, int* dist_cache,
    679     size_t* last_insert_len, Command* commands, size_t* num_commands,
    680     size_t* num_literals) {
    681   const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
    682   ZopfliNode* nodes;
    683   nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);
    684   if (BROTLI_IS_OOM(m)) return;
    685   BrotliInitZopfliNodes(nodes, num_bytes + 1);
    686   *num_commands += BrotliZopfliComputeShortestPath(m, dictionary, num_bytes,
    687       position, ringbuffer, ringbuffer_mask, params, max_backward_limit,
    688       dist_cache, hasher, nodes);
    689   if (BROTLI_IS_OOM(m)) return;
    690   BrotliZopfliCreateCommands(num_bytes, position, max_backward_limit, nodes,
    691       dist_cache, last_insert_len, commands, num_literals);
    692   BROTLI_FREE(m, nodes);
    693 }
    694 
    695 void BrotliCreateHqZopfliBackwardReferences(
    696     MemoryManager* m, const BrotliDictionary* dictionary, size_t num_bytes,
    697     size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
    698     const BrotliEncoderParams* params, HasherHandle hasher, int* dist_cache,
    699     size_t* last_insert_len, Command* commands, size_t* num_commands,
    700     size_t* num_literals) {
    701   const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
    702   uint32_t* num_matches = BROTLI_ALLOC(m, uint32_t, num_bytes);
    703   size_t matches_size = 4 * num_bytes;
    704   const size_t store_end = num_bytes >= StoreLookaheadH10() ?
    705       position + num_bytes - StoreLookaheadH10() + 1 : position;
    706   size_t cur_match_pos = 0;
    707   size_t i;
    708   size_t orig_num_literals;
    709   size_t orig_last_insert_len;
    710   int orig_dist_cache[4];
    711   size_t orig_num_commands;
    712   ZopfliCostModel model;
    713   ZopfliNode* nodes;
    714   BackwardMatch* matches = BROTLI_ALLOC(m, BackwardMatch, matches_size);
    715   if (BROTLI_IS_OOM(m)) return;
    716   for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; ++i) {
    717     const size_t pos = position + i;
    718     size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);
    719     size_t max_length = num_bytes - i;
    720     size_t num_found_matches;
    721     size_t cur_match_end;
    722     size_t j;
    723     /* Ensure that we have enough free slots. */
    724     BROTLI_ENSURE_CAPACITY(m, BackwardMatch, matches, matches_size,
    725         cur_match_pos + MAX_NUM_MATCHES_H10);
    726     if (BROTLI_IS_OOM(m)) return;
    727     num_found_matches = FindAllMatchesH10(hasher, dictionary, ringbuffer,
    728         ringbuffer_mask, pos, max_length, max_distance, params,
    729         &matches[cur_match_pos]);
    730     cur_match_end = cur_match_pos + num_found_matches;
    731     for (j = cur_match_pos; j + 1 < cur_match_end; ++j) {
    732       assert(BackwardMatchLength(&matches[j]) <
    733           BackwardMatchLength(&matches[j + 1]));
    734       assert(matches[j].distance > max_distance ||
    735              matches[j].distance <= matches[j + 1].distance);
    736     }
    737     num_matches[i] = (uint32_t)num_found_matches;
    738     if (num_found_matches > 0) {
    739       const size_t match_len = BackwardMatchLength(&matches[cur_match_end - 1]);
    740       if (match_len > MAX_ZOPFLI_LEN_QUALITY_11) {
    741         const size_t skip = match_len - 1;
    742         matches[cur_match_pos++] = matches[cur_match_end - 1];
    743         num_matches[i] = 1;
    744         /* Add the tail of the copy to the hasher. */
    745         StoreRangeH10(hasher, ringbuffer, ringbuffer_mask, pos + 1,
    746                       BROTLI_MIN(size_t, pos + match_len, store_end));
    747         memset(&num_matches[i + 1], 0, skip * sizeof(num_matches[0]));
    748         i += skip;
    749       } else {
    750         cur_match_pos = cur_match_end;
    751       }
    752     }
    753   }
    754   orig_num_literals = *num_literals;
    755   orig_last_insert_len = *last_insert_len;
    756   memcpy(orig_dist_cache, dist_cache, 4 * sizeof(dist_cache[0]));
    757   orig_num_commands = *num_commands;
    758   nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);
    759   if (BROTLI_IS_OOM(m)) return;
    760   InitZopfliCostModel(m, &model, num_bytes);
    761   if (BROTLI_IS_OOM(m)) return;
    762   for (i = 0; i < 2; i++) {
    763     BrotliInitZopfliNodes(nodes, num_bytes + 1);
    764     if (i == 0) {
    765       ZopfliCostModelSetFromLiteralCosts(
    766           &model, position, ringbuffer, ringbuffer_mask);
    767     } else {
    768       ZopfliCostModelSetFromCommands(&model, position, ringbuffer,
    769           ringbuffer_mask, commands, *num_commands - orig_num_commands,
    770           orig_last_insert_len);
    771     }
    772     *num_commands = orig_num_commands;
    773     *num_literals = orig_num_literals;
    774     *last_insert_len = orig_last_insert_len;
    775     memcpy(dist_cache, orig_dist_cache, 4 * sizeof(dist_cache[0]));
    776     *num_commands += ZopfliIterate(num_bytes, position, ringbuffer,
    777         ringbuffer_mask, params, max_backward_limit, dist_cache,
    778         &model, num_matches, matches, nodes);
    779     BrotliZopfliCreateCommands(num_bytes, position, max_backward_limit,
    780         nodes, dist_cache, last_insert_len, commands, num_literals);
    781   }
    782   CleanupZopfliCostModel(m, &model);
    783   BROTLI_FREE(m, nodes);
    784   BROTLI_FREE(m, matches);
    785   BROTLI_FREE(m, num_matches);
    786 }
    787 
    788 #if defined(__cplusplus) || defined(c_plusplus)
    789 }  /* extern "C" */
    790 #endif
    791