1/*
2Copyright 2011 Google Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15
16Author: lode.vandevenne@gmail.com (Lode Vandevenne)
17Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
18*/
19
20#include "squeeze.h"
21
22#include <assert.h>
23#include <math.h>
24#include <stdio.h>
25
26#include "blocksplitter.h"
27#include "deflate.h"
28#include "tree.h"
29#include "util.h"
30
31typedef struct SymbolStats {
32  /* The literal and length symbols. */
33  size_t litlens[288];
34  /* The 32 unique dist symbols, not the 32768 possible dists. */
35  size_t dists[32];
36
37  double ll_symbols[288];  /* Length of each lit/len symbol in bits. */
38  double d_symbols[32];  /* Length of each dist symbol in bits. */
39} SymbolStats;
40
41/* Sets everything to 0. */
42static void InitStats(SymbolStats* stats) {
43  memset(stats->litlens, 0, 288 * sizeof(stats->litlens[0]));
44  memset(stats->dists, 0, 32 * sizeof(stats->dists[0]));
45
46  memset(stats->ll_symbols, 0, 288 * sizeof(stats->ll_symbols[0]));
47  memset(stats->d_symbols, 0, 32 * sizeof(stats->d_symbols[0]));
48}
49
50static void CopyStats(SymbolStats* source, SymbolStats* dest) {
51  memcpy(dest->litlens, source->litlens, 288 * sizeof(dest->litlens[0]));
52  memcpy(dest->dists, source->dists, 32 * sizeof(dest->dists[0]));
53
54  memcpy(dest->ll_symbols, source->ll_symbols,
55         288 * sizeof(dest->ll_symbols[0]));
56  memcpy(dest->d_symbols, source->d_symbols, 32 * sizeof(dest->d_symbols[0]));
57}
58
59/* Adds the bit lengths. */
60static void AddWeighedStatFreqs(const SymbolStats* stats1, double w1,
61                                const SymbolStats* stats2, double w2,
62                                SymbolStats* result) {
63  size_t i;
64  for (i = 0; i < 288; i++) {
65    result->litlens[i] =
66        (size_t) (stats1->litlens[i] * w1 + stats2->litlens[i] * w2);
67  }
68  for (i = 0; i < 32; i++) {
69    result->dists[i] =
70        (size_t) (stats1->dists[i] * w1 + stats2->dists[i] * w2);
71  }
72  result->litlens[256] = 1;  /* End symbol. */
73}
74
75typedef struct RanState {
76  unsigned int m_w, m_z;
77} RanState;
78
79static void InitRanState(RanState* state) {
80  state->m_w = 1;
81  state->m_z = 2;
82}
83
84/* Get random number: "Multiply-With-Carry" generator of G. Marsaglia */
85static unsigned int Ran(RanState* state) {
86  state->m_z = 36969 * (state->m_z & 65535) + (state->m_z >> 16);
87  state->m_w = 18000 * (state->m_w & 65535) + (state->m_w >> 16);
88  return (state->m_z << 16) + state->m_w;  /* 32-bit result. */
89}
90
91static void RandomizeFreqs(RanState* state, size_t* freqs, int n) {
92  int i;
93  for (i = 0; i < n; i++) {
94    if ((Ran(state) >> 4) % 3 == 0) freqs[i] = freqs[Ran(state) % n];
95  }
96}
97
98static void RandomizeStatFreqs(RanState* state, SymbolStats* stats) {
99  RandomizeFreqs(state, stats->litlens, 288);
100  RandomizeFreqs(state, stats->dists, 32);
101  stats->litlens[256] = 1;  /* End symbol. */
102}
103
104static void ClearStatFreqs(SymbolStats* stats) {
105  size_t i;
106  for (i = 0; i < 288; i++) stats->litlens[i] = 0;
107  for (i = 0; i < 32; i++) stats->dists[i] = 0;
108}
109
110/*
111Function that calculates a cost based on a model for the given LZ77 symbol.
112litlen: means literal symbol if dist is 0, length otherwise.
113*/
114typedef double CostModelFun(unsigned litlen, unsigned dist, void* context);
115
116/*
117Cost model which should exactly match fixed tree.
118type: CostModelFun
119*/
120static double GetCostFixed(unsigned litlen, unsigned dist, void* unused) {
121  (void)unused;
122  if (dist == 0) {
123    if (litlen <= 143) return 8;
124    else return 9;
125  } else {
126    int dbits = ZopfliGetDistExtraBits(dist);
127    int lbits = ZopfliGetLengthExtraBits(litlen);
128    int lsym = ZopfliGetLengthSymbol(litlen);
129    double cost = 0;
130    if (lsym <= 279) cost += 7;
131    else cost += 8;
132    cost += 5;  /* Every dist symbol has length 5. */
133    return cost + dbits + lbits;
134  }
135}
136
137/*
138Cost model based on symbol statistics.
139type: CostModelFun
140*/
141static double GetCostStat(unsigned litlen, unsigned dist, void* context) {
142  SymbolStats* stats = (SymbolStats*)context;
143  if (dist == 0) {
144    return stats->ll_symbols[litlen];
145  } else {
146    int lsym = ZopfliGetLengthSymbol(litlen);
147    int lbits = ZopfliGetLengthExtraBits(litlen);
148    int dsym = ZopfliGetDistSymbol(dist);
149    int dbits = ZopfliGetDistExtraBits(dist);
150    return stats->ll_symbols[lsym] + lbits + stats->d_symbols[dsym] + dbits;
151  }
152}
153
154/*
155Finds the minimum possible cost this cost model can return for valid length and
156distance symbols.
157*/
158static double GetCostModelMinCost(CostModelFun* costmodel, void* costcontext) {
159  double mincost;
160  int bestlength = 0; /* length that has lowest cost in the cost model */
161  int bestdist = 0; /* distance that has lowest cost in the cost model */
162  int i;
163  /*
164  Table of distances that have a different distance symbol in the deflate
165  specification. Each value is the first distance that has a new symbol. Only
166  different symbols affect the cost model so only these need to be checked.
167  See RFC 1951 section 3.2.5. Compressed blocks (length and distance codes).
168  */
169  static const int dsymbols[30] = {
170    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
171    769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
172  };
173
174  mincost = ZOPFLI_LARGE_FLOAT;
175  for (i = 3; i < 259; i++) {
176    double c = costmodel(i, 1, costcontext);
177    if (c < mincost) {
178      bestlength = i;
179      mincost = c;
180    }
181  }
182
183  mincost = ZOPFLI_LARGE_FLOAT;
184  for (i = 0; i < 30; i++) {
185    double c = costmodel(3, dsymbols[i], costcontext);
186    if (c < mincost) {
187      bestdist = dsymbols[i];
188      mincost = c;
189    }
190  }
191
192  return costmodel(bestlength, bestdist, costcontext);
193}
194
195/*
196Performs the forward pass for "squeeze". Gets the most optimal length to reach
197every byte from a previous byte, using cost calculations.
198s: the ZopfliBlockState
199in: the input data array
200instart: where to start
201inend: where to stop (not inclusive)
202costmodel: function to calculate the cost of some lit/len/dist pair.
203costcontext: abstract context for the costmodel function
204length_array: output array of size (inend - instart) which will receive the best
205    length to reach this byte from a previous byte.
206returns the cost that was, according to the costmodel, needed to get to the end.
207*/
208static double GetBestLengths(ZopfliBlockState *s,
209                             const unsigned char* in,
210                             size_t instart, size_t inend,
211                             CostModelFun* costmodel, void* costcontext,
212                             unsigned short* length_array) {
213  /* Best cost to get here so far. */
214  size_t blocksize = inend - instart;
215  float* costs;
216  size_t i = 0, k;
217  unsigned short leng;
218  unsigned short dist;
219  unsigned short sublen[259];
220  size_t windowstart = instart > ZOPFLI_WINDOW_SIZE
221      ? instart - ZOPFLI_WINDOW_SIZE : 0;
222  ZopfliHash hash;
223  ZopfliHash* h = &hash;
224  double result;
225  double mincost = GetCostModelMinCost(costmodel, costcontext);
226
227  if (instart == inend) return 0;
228
229  costs = (float*)malloc(sizeof(float) * (blocksize + 1));
230  if (!costs) exit(-1); /* Allocation failed. */
231
232  ZopfliInitHash(ZOPFLI_WINDOW_SIZE, h);
233  ZopfliWarmupHash(in, windowstart, inend, h);
234  for (i = windowstart; i < instart; i++) {
235    ZopfliUpdateHash(in, i, inend, h);
236  }
237
238  for (i = 1; i < blocksize + 1; i++) costs[i] = ZOPFLI_LARGE_FLOAT;
239  costs[0] = 0;  /* Because it's the start. */
240  length_array[0] = 0;
241
242  for (i = instart; i < inend; i++) {
243    size_t j = i - instart;  /* Index in the costs array and length_array. */
244    ZopfliUpdateHash(in, i, inend, h);
245
246#ifdef ZOPFLI_SHORTCUT_LONG_REPETITIONS
247    /* If we're in a long repetition of the same character and have more than
248    ZOPFLI_MAX_MATCH characters before and after our position. */
249    if (h->same[i & ZOPFLI_WINDOW_MASK] > ZOPFLI_MAX_MATCH * 2
250        && i > instart + ZOPFLI_MAX_MATCH + 1
251        && i + ZOPFLI_MAX_MATCH * 2 + 1 < inend
252        && h->same[(i - ZOPFLI_MAX_MATCH) & ZOPFLI_WINDOW_MASK]
253            > ZOPFLI_MAX_MATCH) {
254      double symbolcost = costmodel(ZOPFLI_MAX_MATCH, 1, costcontext);
255      /* Set the length to reach each one to ZOPFLI_MAX_MATCH, and the cost to
256      the cost corresponding to that length. Doing this, we skip
257      ZOPFLI_MAX_MATCH values to avoid calling ZopfliFindLongestMatch. */
258      for (k = 0; k < ZOPFLI_MAX_MATCH; k++) {
259        costs[j + ZOPFLI_MAX_MATCH] = costs[j] + symbolcost;
260        length_array[j + ZOPFLI_MAX_MATCH] = ZOPFLI_MAX_MATCH;
261        i++;
262        j++;
263        ZopfliUpdateHash(in, i, inend, h);
264      }
265    }
266#endif
267
268    ZopfliFindLongestMatch(s, h, in, i, inend, ZOPFLI_MAX_MATCH, sublen,
269                           &dist, &leng);
270
271    /* Literal. */
272    if (i + 1 <= inend) {
273      double newCost = costs[j] + costmodel(in[i], 0, costcontext);
274      assert(newCost >= 0);
275      if (newCost < costs[j + 1]) {
276        costs[j + 1] = newCost;
277        length_array[j + 1] = 1;
278      }
279    }
280    /* Lengths. */
281    for (k = 3; k <= leng && i + k <= inend; k++) {
282      double newCost;
283
284      /* Calling the cost model is expensive, avoid this if we are already at
285      the minimum possible cost that it can return. */
286     if (costs[j + k] - costs[j] <= mincost) continue;
287
288      newCost = costs[j] + costmodel(k, sublen[k], costcontext);
289      assert(newCost >= 0);
290      if (newCost < costs[j + k]) {
291        assert(k <= ZOPFLI_MAX_MATCH);
292        costs[j + k] = newCost;
293        length_array[j + k] = k;
294      }
295    }
296  }
297
298  assert(costs[blocksize] >= 0);
299  result = costs[blocksize];
300
301  ZopfliCleanHash(h);
302  free(costs);
303
304  return result;
305}
306
307/*
308Calculates the optimal path of lz77 lengths to use, from the calculated
309length_array. The length_array must contain the optimal length to reach that
310byte. The path will be filled with the lengths to use, so its data size will be
311the amount of lz77 symbols.
312*/
313static void TraceBackwards(size_t size, const unsigned short* length_array,
314                           unsigned short** path, size_t* pathsize) {
315  size_t index = size;
316  if (size == 0) return;
317  for (;;) {
318    ZOPFLI_APPEND_DATA(length_array[index], path, pathsize);
319    assert(length_array[index] <= index);
320    assert(length_array[index] <= ZOPFLI_MAX_MATCH);
321    assert(length_array[index] != 0);
322    index -= length_array[index];
323    if (index == 0) break;
324  }
325
326  /* Mirror result. */
327  for (index = 0; index < *pathsize / 2; index++) {
328    unsigned short temp = (*path)[index];
329    (*path)[index] = (*path)[*pathsize - index - 1];
330    (*path)[*pathsize - index - 1] = temp;
331  }
332}
333
334static void FollowPath(ZopfliBlockState* s,
335                       const unsigned char* in, size_t instart, size_t inend,
336                       unsigned short* path, size_t pathsize,
337                       ZopfliLZ77Store* store) {
338  size_t i, j, pos = 0;
339  size_t windowstart = instart > ZOPFLI_WINDOW_SIZE
340      ? instart - ZOPFLI_WINDOW_SIZE : 0;
341
342  size_t total_length_test = 0;
343
344  ZopfliHash hash;
345  ZopfliHash* h = &hash;
346
347  if (instart == inend) return;
348
349  ZopfliInitHash(ZOPFLI_WINDOW_SIZE, h);
350  ZopfliWarmupHash(in, windowstart, inend, h);
351  for (i = windowstart; i < instart; i++) {
352    ZopfliUpdateHash(in, i, inend, h);
353  }
354
355  pos = instart;
356  for (i = 0; i < pathsize; i++) {
357    unsigned short length = path[i];
358    unsigned short dummy_length;
359    unsigned short dist;
360    assert(pos < inend);
361
362    ZopfliUpdateHash(in, pos, inend, h);
363
364    /* Add to output. */
365    if (length >= ZOPFLI_MIN_MATCH) {
366      /* Get the distance by recalculating longest match. The found length
367      should match the length from the path. */
368      ZopfliFindLongestMatch(s, h, in, pos, inend, length, 0,
369                             &dist, &dummy_length);
370      assert(!(dummy_length != length && length > 2 && dummy_length > 2));
371      ZopfliVerifyLenDist(in, inend, pos, dist, length);
372      ZopfliStoreLitLenDist(length, dist, store);
373      total_length_test += length;
374    } else {
375      length = 1;
376      ZopfliStoreLitLenDist(in[pos], 0, store);
377      total_length_test++;
378    }
379
380
381    assert(pos + length <= inend);
382    for (j = 1; j < length; j++) {
383      ZopfliUpdateHash(in, pos + j, inend, h);
384    }
385
386    pos += length;
387  }
388
389  ZopfliCleanHash(h);
390}
391
392/* Calculates the entropy of the statistics */
393static void CalculateStatistics(SymbolStats* stats) {
394  ZopfliCalculateEntropy(stats->litlens, 288, stats->ll_symbols);
395  ZopfliCalculateEntropy(stats->dists, 32, stats->d_symbols);
396}
397
398/* Appends the symbol statistics from the store. */
399static void GetStatistics(const ZopfliLZ77Store* store, SymbolStats* stats) {
400  size_t i;
401  for (i = 0; i < store->size; i++) {
402    if (store->dists[i] == 0) {
403      stats->litlens[store->litlens[i]]++;
404    } else {
405      stats->litlens[ZopfliGetLengthSymbol(store->litlens[i])]++;
406      stats->dists[ZopfliGetDistSymbol(store->dists[i])]++;
407    }
408  }
409  stats->litlens[256] = 1;  /* End symbol. */
410
411  CalculateStatistics(stats);
412}
413
414/*
415Does a single run for ZopfliLZ77Optimal. For good compression, repeated runs
416with updated statistics should be performed.
417
418s: the block state
419in: the input data array
420instart: where to start
421inend: where to stop (not inclusive)
422path: pointer to dynamically allocated memory to store the path
423pathsize: pointer to the size of the dynamic path array
424length_array: array if size (inend - instart) used to store lengths
425costmodel: function to use as the cost model for this squeeze run
426costcontext: abstract context for the costmodel function
427store: place to output the LZ77 data
428returns the cost that was, according to the costmodel, needed to get to the end.
429    This is not the actual cost.
430*/
431static double LZ77OptimalRun(ZopfliBlockState* s,
432    const unsigned char* in, size_t instart, size_t inend,
433    unsigned short** path, size_t* pathsize,
434    unsigned short* length_array, CostModelFun* costmodel,
435    void* costcontext, ZopfliLZ77Store* store) {
436  double cost = GetBestLengths(
437      s, in, instart, inend, costmodel, costcontext, length_array);
438  free(*path);
439  *path = 0;
440  *pathsize = 0;
441  TraceBackwards(inend - instart, length_array, path, pathsize);
442  FollowPath(s, in, instart, inend, *path, *pathsize, store);
443  assert(cost < ZOPFLI_LARGE_FLOAT);
444  return cost;
445}
446
447void ZopfliLZ77Optimal(ZopfliBlockState *s,
448                       const unsigned char* in, size_t instart, size_t inend,
449                       ZopfliLZ77Store* store) {
450  /* Dist to get to here with smallest cost. */
451  size_t blocksize = inend - instart;
452  unsigned short* length_array =
453      (unsigned short*)malloc(sizeof(unsigned short) * (blocksize + 1));
454  unsigned short* path = 0;
455  size_t pathsize = 0;
456  ZopfliLZ77Store currentstore;
457  SymbolStats stats, beststats, laststats;
458  int i;
459  double cost;
460  double bestcost = ZOPFLI_LARGE_FLOAT;
461  double lastcost = 0;
462  /* Try randomizing the costs a bit once the size stabilizes. */
463  RanState ran_state;
464  int lastrandomstep = -1;
465
466  if (!length_array) exit(-1); /* Allocation failed. */
467
468  InitRanState(&ran_state);
469  InitStats(&stats);
470  ZopfliInitLZ77Store(&currentstore);
471
472  /* Do regular deflate, then loop multiple shortest path runs, each time using
473  the statistics of the previous run. */
474
475  /* Initial run. */
476  ZopfliLZ77Greedy(s, in, instart, inend, &currentstore);
477  GetStatistics(&currentstore, &stats);
478
479  /* Repeat statistics with each time the cost model from the previous stat
480  run. */
481  for (i = 0; i < s->options->numiterations; i++) {
482    ZopfliCleanLZ77Store(&currentstore);
483    ZopfliInitLZ77Store(&currentstore);
484    LZ77OptimalRun(s, in, instart, inend, &path, &pathsize,
485                   length_array, GetCostStat, (void*)&stats,
486                   &currentstore);
487    cost = ZopfliCalculateBlockSize(currentstore.litlens, currentstore.dists,
488                                    0, currentstore.size, 2);
489    if (s->options->verbose_more || (s->options->verbose && cost < bestcost)) {
490      fprintf(stderr, "Iteration %d: %d bit\n", i, (int) cost);
491    }
492    if (cost < bestcost) {
493      /* Copy to the output store. */
494      ZopfliCopyLZ77Store(&currentstore, store);
495      CopyStats(&stats, &beststats);
496      bestcost = cost;
497    }
498    CopyStats(&stats, &laststats);
499    ClearStatFreqs(&stats);
500    GetStatistics(&currentstore, &stats);
501    if (lastrandomstep != -1) {
502      /* This makes it converge slower but better. Do it only once the
503      randomness kicks in so that if the user does few iterations, it gives a
504      better result sooner. */
505      AddWeighedStatFreqs(&stats, 1.0, &laststats, 0.5, &stats);
506      CalculateStatistics(&stats);
507    }
508    if (i > 5 && cost == lastcost) {
509      CopyStats(&beststats, &stats);
510      RandomizeStatFreqs(&ran_state, &stats);
511      CalculateStatistics(&stats);
512      lastrandomstep = i;
513    }
514    lastcost = cost;
515  }
516
517  free(length_array);
518  free(path);
519  ZopfliCleanLZ77Store(&currentstore);
520}
521
522void ZopfliLZ77OptimalFixed(ZopfliBlockState *s,
523                            const unsigned char* in,
524                            size_t instart, size_t inend,
525                            ZopfliLZ77Store* store)
526{
527  /* Dist to get to here with smallest cost. */
528  size_t blocksize = inend - instart;
529  unsigned short* length_array =
530      (unsigned short*)malloc(sizeof(unsigned short) * (blocksize + 1));
531  unsigned short* path = 0;
532  size_t pathsize = 0;
533
534  if (!length_array) exit(-1); /* Allocation failed. */
535
536  s->blockstart = instart;
537  s->blockend = inend;
538
539  /* Shortest path for fixed tree This one should give the shortest possible
540  result for fixed tree, no repeated runs are needed since the tree is known. */
541  LZ77OptimalRun(s, in, instart, inend, &path, &pathsize,
542                 length_array, GetCostFixed, 0, store);
543
544  free(length_array);
545  free(path);
546}
547