zstd-ruby 1.3.8.0 → 1.4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -5
  3. data/README.md +1 -1
  4. data/ext/zstdruby/libzstd/Makefile +133 -61
  5. data/ext/zstdruby/libzstd/README.md +51 -18
  6. data/ext/zstdruby/libzstd/common/bitstream.h +38 -39
  7. data/ext/zstdruby/libzstd/common/compiler.h +41 -6
  8. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  9. data/ext/zstdruby/libzstd/common/debug.c +11 -31
  10. data/ext/zstdruby/libzstd/common/debug.h +11 -31
  11. data/ext/zstdruby/libzstd/common/entropy_common.c +13 -33
  12. data/ext/zstdruby/libzstd/common/error_private.c +2 -1
  13. data/ext/zstdruby/libzstd/common/error_private.h +6 -2
  14. data/ext/zstdruby/libzstd/common/fse.h +13 -33
  15. data/ext/zstdruby/libzstd/common/fse_decompress.c +12 -35
  16. data/ext/zstdruby/libzstd/common/huf.h +15 -33
  17. data/ext/zstdruby/libzstd/common/mem.h +75 -2
  18. data/ext/zstdruby/libzstd/common/pool.c +8 -4
  19. data/ext/zstdruby/libzstd/common/pool.h +2 -2
  20. data/ext/zstdruby/libzstd/common/threading.c +52 -6
  21. data/ext/zstdruby/libzstd/common/threading.h +36 -4
  22. data/ext/zstdruby/libzstd/common/xxhash.c +25 -37
  23. data/ext/zstdruby/libzstd/common/xxhash.h +11 -31
  24. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
  25. data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
  26. data/ext/zstdruby/libzstd/common/zstd_internal.h +203 -22
  27. data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -42
  28. data/ext/zstdruby/libzstd/compress/hist.c +15 -35
  29. data/ext/zstdruby/libzstd/compress/hist.h +12 -32
  30. data/ext/zstdruby/libzstd/compress/huf_compress.c +92 -92
  31. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1460 -1472
  32. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +330 -65
  33. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
  34. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +419 -0
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +845 -0
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  39. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +525 -0
  40. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +65 -43
  41. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
  42. data/ext/zstdruby/libzstd/compress/zstd_fast.c +264 -159
  43. data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
  44. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +74 -42
  45. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +2 -2
  46. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +33 -11
  47. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +7 -2
  48. data/ext/zstdruby/libzstd/compress/zstd_opt.c +108 -125
  49. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  50. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +129 -93
  51. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +46 -28
  52. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +76 -60
  53. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +14 -10
  54. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
  55. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +471 -258
  56. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +471 -346
  57. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +3 -3
  58. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +25 -4
  59. data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
  60. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
  61. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
  62. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  63. data/ext/zstdruby/libzstd/dictBuilder/cover.c +220 -65
  64. data/ext/zstdruby/libzstd/dictBuilder/cover.h +81 -7
  65. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +85 -56
  66. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +43 -19
  67. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +73 -35
  68. data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
  69. data/ext/zstdruby/libzstd/dll/example/build_package.bat +3 -2
  70. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +49 -15
  71. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +142 -117
  72. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +13 -8
  73. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +54 -25
  74. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +13 -8
  75. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +55 -25
  76. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +13 -8
  77. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +62 -29
  78. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +13 -8
  79. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +145 -109
  80. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +14 -9
  81. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +56 -26
  82. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +11 -6
  83. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +65 -28
  84. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +11 -6
  85. data/ext/zstdruby/libzstd/libzstd.pc.in +3 -2
  86. data/ext/zstdruby/libzstd/zstd.h +921 -597
  87. data/lib/zstd-ruby/version.rb +1 -1
  88. data/zstd-ruby.gemspec +2 -2
  89. metadata +19 -14
  90. data/ext/zstdruby/libzstd/dll/libzstd.def +0 -87
@@ -1,10 +1,11 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
6
6
  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
7
  * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
8
9
  */
9
10
 
10
11
  #ifndef ZSTD_LDM_H
@@ -15,7 +16,7 @@ extern "C" {
15
16
  #endif
16
17
 
17
18
  #include "zstd_compress_internal.h" /* ldmParams_t, U32 */
18
- #include "zstd.h" /* ZSTD_CCtx, size_t */
19
+ #include "../zstd.h" /* ZSTD_CCtx, size_t */
19
20
 
20
21
  /*-*************************************
21
22
  * Long distance matching
@@ -23,6 +24,10 @@ extern "C" {
23
24
 
24
25
  #define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_LIMIT_DEFAULT
25
26
 
27
+ void ZSTD_ldm_fillHashTable(
28
+ ldmState_t* state, const BYTE* ip,
29
+ const BYTE* iend, ldmParams_t const* params);
30
+
26
31
  /**
27
32
  * ZSTD_ldm_generateSequences():
28
33
  *
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -64,9 +64,15 @@ MEM_STATIC double ZSTD_fCost(U32 price)
64
64
  }
65
65
  #endif
66
66
 
67
+ static int ZSTD_compressedLiterals(optState_t const* const optPtr)
68
+ {
69
+ return optPtr->literalCompressionMode != ZSTD_lcm_uncompressed;
70
+ }
71
+
67
72
  static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
68
73
  {
69
- optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
74
+ if (ZSTD_compressedLiterals(optPtr))
75
+ optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
70
76
  optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);
71
77
  optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);
72
78
  optPtr->offCodeSumBasePrice = WEIGHT(optPtr->offCodeSum, optLevel);
@@ -99,6 +105,7 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
99
105
  const BYTE* const src, size_t const srcSize,
100
106
  int const optLevel)
101
107
  {
108
+ int const compressedLiterals = ZSTD_compressedLiterals(optPtr);
102
109
  DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize);
103
110
  optPtr->priceType = zop_dynamic;
104
111
 
@@ -113,9 +120,10 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
113
120
  /* huffman table presumed generated by dictionary */
114
121
  optPtr->priceType = zop_dynamic;
115
122
 
116
- assert(optPtr->litFreq != NULL);
117
- optPtr->litSum = 0;
118
- { unsigned lit;
123
+ if (compressedLiterals) {
124
+ unsigned lit;
125
+ assert(optPtr->litFreq != NULL);
126
+ optPtr->litSum = 0;
119
127
  for (lit=0; lit<=MaxLit; lit++) {
120
128
  U32 const scaleLog = 11; /* scale to 2K */
121
129
  U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit);
@@ -163,10 +171,11 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
163
171
  } else { /* not a dictionary */
164
172
 
165
173
  assert(optPtr->litFreq != NULL);
166
- { unsigned lit = MaxLit;
174
+ if (compressedLiterals) {
175
+ unsigned lit = MaxLit;
167
176
  HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
177
+ optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
168
178
  }
169
- optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
170
179
 
171
180
  { unsigned ll;
172
181
  for (ll=0; ll<=MaxLL; ll++)
@@ -190,7 +199,8 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
190
199
 
191
200
  } else { /* new block : re-use previous statistics, scaled down */
192
201
 
193
- optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
202
+ if (compressedLiterals)
203
+ optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
194
204
  optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0);
195
205
  optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0);
196
206
  optPtr->offCodeSum = ZSTD_downscaleStat(optPtr->offCodeFreq, MaxOff, 0);
@@ -207,6 +217,10 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
207
217
  int optLevel)
208
218
  {
209
219
  if (litLength == 0) return 0;
220
+
221
+ if (!ZSTD_compressedLiterals(optPtr))
222
+ return (litLength << 3) * BITCOST_MULTIPLIER; /* Uncompressed - 8 bytes per literal. */
223
+
210
224
  if (optPtr->priceType == zop_predef)
211
225
  return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */
212
226
 
@@ -235,40 +249,6 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
235
249
  }
236
250
  }
237
251
 
238
- /* ZSTD_litLengthContribution() :
239
- * @return ( cost(litlength) - cost(0) )
240
- * this value can then be added to rawLiteralsCost()
241
- * to provide a cost which is directly comparable to a match ending at same position */
242
- static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel)
243
- {
244
- if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel);
245
-
246
- /* dynamic statistics */
247
- { U32 const llCode = ZSTD_LLcode(litLength);
248
- int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER)
249
- + WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
250
- - WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
251
- #if 1
252
- return contribution;
253
- #else
254
- return MAX(0, contribution); /* sometimes better, sometimes not ... */
255
- #endif
256
- }
257
- }
258
-
259
- /* ZSTD_literalsContribution() :
260
- * creates a fake cost for the literals part of a sequence
261
- * which can be compared to the ending cost of a match
262
- * should a new match start at this position */
263
- static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLength,
264
- const optState_t* const optPtr,
265
- int optLevel)
266
- {
267
- int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
268
- + ZSTD_litLengthContribution(litLength, optPtr, optLevel);
269
- return contribution;
270
- }
271
-
272
252
  /* ZSTD_getMatchPrice() :
273
253
  * Provides the cost of the match part (offset + matchLength) of a sequence
274
254
  * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
@@ -310,7 +290,8 @@ static void ZSTD_updateStats(optState_t* const optPtr,
310
290
  U32 offsetCode, U32 matchLength)
311
291
  {
312
292
  /* literals */
313
- { U32 u;
293
+ if (ZSTD_compressedLiterals(optPtr)) {
294
+ U32 u;
314
295
  for (u=0; u < litLength; u++)
315
296
  optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
316
297
  optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
@@ -357,13 +338,15 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
357
338
 
358
339
  /* Update hashTable3 up to ip (excluded)
359
340
  Assumption : always within prefix (i.e. not within extDict) */
360
- static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE* const ip)
341
+ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms,
342
+ U32* nextToUpdate3,
343
+ const BYTE* const ip)
361
344
  {
362
345
  U32* const hashTable3 = ms->hashTable3;
363
346
  U32 const hashLog3 = ms->hashLog3;
364
347
  const BYTE* const base = ms->window.base;
365
- U32 idx = ms->nextToUpdate3;
366
- U32 const target = ms->nextToUpdate3 = (U32)(ip - base);
348
+ U32 idx = *nextToUpdate3;
349
+ U32 const target = (U32)(ip - base);
367
350
  size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);
368
351
  assert(hashLog3 > 0);
369
352
 
@@ -372,6 +355,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
372
355
  idx++;
373
356
  }
374
357
 
358
+ *nextToUpdate3 = target;
375
359
  return hashTable3[hash3];
376
360
  }
377
361
 
@@ -488,9 +472,11 @@ static U32 ZSTD_insertBt1(
488
472
  } }
489
473
 
490
474
  *smallerPtr = *largerPtr = 0;
491
- if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
492
- assert(matchEndIdx > current + 8);
493
- return matchEndIdx - (current + 8);
475
+ { U32 positions = 0;
476
+ if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384)); /* speed optimization */
477
+ assert(matchEndIdx > current + 8);
478
+ return MAX(positions, matchEndIdx - (current + 8));
479
+ }
494
480
  }
495
481
 
496
482
  FORCE_INLINE_TEMPLATE
@@ -505,8 +491,13 @@ void ZSTD_updateTree_internal(
505
491
  DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
506
492
  idx, target, dictMode);
507
493
 
508
- while(idx < target)
509
- idx += ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
494
+ while(idx < target) {
495
+ U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
496
+ assert(idx < (U32)(idx + forward));
497
+ idx += forward;
498
+ }
499
+ assert((size_t)(ip - base) <= (size_t)(U32)(-1));
500
+ assert((size_t)(iend - base) <= (size_t)(U32)(-1));
510
501
  ms->nextToUpdate = target;
511
502
  }
512
503
 
@@ -516,11 +507,12 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
516
507
 
517
508
  FORCE_INLINE_TEMPLATE
518
509
  U32 ZSTD_insertBtAndGetAllMatches (
510
+ ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
519
511
  ZSTD_matchState_t* ms,
512
+ U32* nextToUpdate3,
520
513
  const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
521
- U32 rep[ZSTD_REP_NUM],
514
+ const U32 rep[ZSTD_REP_NUM],
522
515
  U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
523
- ZSTD_match_t* matches,
524
516
  const U32 lengthToBeat,
525
517
  U32 const mls /* template */)
526
518
  {
@@ -541,8 +533,8 @@ U32 ZSTD_insertBtAndGetAllMatches (
541
533
  U32 const dictLimit = ms->window.dictLimit;
542
534
  const BYTE* const dictEnd = dictBase + dictLimit;
543
535
  const BYTE* const prefixStart = base + dictLimit;
544
- U32 const btLow = btMask >= current ? 0 : current - btMask;
545
- U32 const windowLow = ms->window.lowLimit;
536
+ U32 const btLow = (btMask >= current) ? 0 : current - btMask;
537
+ U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog);
546
538
  U32 const matchLow = windowLow ? windowLow : 1;
547
539
  U32* smallerPtr = bt + 2*(current&btMask);
548
540
  U32* largerPtr = bt + 2*(current&btMask) + 1;
@@ -577,7 +569,10 @@ U32 ZSTD_insertBtAndGetAllMatches (
577
569
  U32 repLen = 0;
578
570
  assert(current >= dictLimit);
579
571
  if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */
580
- if (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch)) {
572
+ /* We must validate the repcode offset because when we're using a dictionary the
573
+ * valid offset range shrinks when the dictionary goes out of bounds.
574
+ */
575
+ if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) {
581
576
  repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;
582
577
  }
583
578
  } else { /* repIndex < dictLimit || repIndex >= current */
@@ -612,7 +607,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
612
607
 
613
608
  /* HC3 match finder */
614
609
  if ((mls == 3) /*static*/ && (bestLength < mls)) {
615
- U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
610
+ U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);
616
611
  if ((matchIndex3 >= matchLow)
617
612
  & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
618
613
  size_t mlen;
@@ -638,9 +633,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
638
633
  (ip+mlen == iLimit) ) { /* best possible length */
639
634
  ms->nextToUpdate = current+1; /* skip insertion */
640
635
  return 1;
641
- }
642
- }
643
- }
636
+ } } }
644
637
  /* no dictMatchState lookup: dicts don't have a populated HC3 table */
645
638
  }
646
639
 
@@ -648,19 +641,21 @@ U32 ZSTD_insertBtAndGetAllMatches (
648
641
 
649
642
  while (nbCompares-- && (matchIndex >= matchLow)) {
650
643
  U32* const nextPtr = bt + 2*(matchIndex & btMask);
651
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
652
644
  const BYTE* match;
645
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
653
646
  assert(current > matchIndex);
654
647
 
655
648
  if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {
656
649
  assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */
657
650
  match = base + matchIndex;
651
+ if (matchIndex >= dictLimit) assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
658
652
  matchLength += ZSTD_count(ip+matchLength, match+matchLength, iLimit);
659
653
  } else {
660
654
  match = dictBase + matchIndex;
655
+ assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
661
656
  matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
662
657
  if (matchIndex+matchLength >= dictLimit)
663
- match = base + matchIndex; /* prepare for match[matchLength] */
658
+ match = base + matchIndex; /* prepare for match[matchLength] read */
664
659
  }
665
660
 
666
661
  if (matchLength > bestLength) {
@@ -745,10 +740,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
745
740
 
746
741
 
747
742
  FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
743
+ ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
748
744
  ZSTD_matchState_t* ms,
745
+ U32* nextToUpdate3,
749
746
  const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
750
- U32 rep[ZSTD_REP_NUM], U32 const ll0,
751
- ZSTD_match_t* matches, U32 const lengthToBeat)
747
+ const U32 rep[ZSTD_REP_NUM],
748
+ U32 const ll0,
749
+ U32 const lengthToBeat)
752
750
  {
753
751
  const ZSTD_compressionParameters* const cParams = &ms->cParams;
754
752
  U32 const matchLengthSearch = cParams->minMatch;
@@ -757,12 +755,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
757
755
  ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
758
756
  switch(matchLengthSearch)
759
757
  {
760
- case 3 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 3);
758
+ case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3);
761
759
  default :
762
- case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4);
763
- case 5 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 5);
760
+ case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4);
761
+ case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5);
764
762
  case 7 :
765
- case 6 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 6);
763
+ case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6);
766
764
  }
767
765
  }
768
766
 
@@ -770,30 +768,6 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
770
768
  /*-*******************************
771
769
  * Optimal parser
772
770
  *********************************/
773
- typedef struct repcodes_s {
774
- U32 rep[3];
775
- } repcodes_t;
776
-
777
- static repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
778
- {
779
- repcodes_t newReps;
780
- if (offset >= ZSTD_REP_NUM) { /* full offset */
781
- newReps.rep[2] = rep[1];
782
- newReps.rep[1] = rep[0];
783
- newReps.rep[0] = offset - ZSTD_REP_MOVE;
784
- } else { /* repcode */
785
- U32 const repCode = offset + ll0;
786
- if (repCode > 0) { /* note : if repCode==0, no change */
787
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
788
- newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
789
- newReps.rep[1] = rep[0];
790
- newReps.rep[0] = currentOffset;
791
- } else { /* repCode == 0 */
792
- memcpy(&newReps, rep, sizeof(newReps));
793
- }
794
- }
795
- return newReps;
796
- }
797
771
 
798
772
 
799
773
  static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
@@ -810,7 +784,7 @@ listStats(const U32* table, int lastEltID)
810
784
  int enb;
811
785
  for (enb=0; enb < nbElts; enb++) {
812
786
  (void)table;
813
- //RAWLOG(2, "%3i:%3i, ", enb, table[enb]);
787
+ /* RAWLOG(2, "%3i:%3i, ", enb, table[enb]); */
814
788
  RAWLOG(2, "%4i,", table[enb]);
815
789
  }
816
790
  RAWLOG(2, " \n");
@@ -838,6 +812,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
838
812
 
839
813
  U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
840
814
  U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
815
+ U32 nextToUpdate3 = ms->nextToUpdate;
841
816
 
842
817
  ZSTD_optimal_t* const opt = optStatePtr->priceTable;
843
818
  ZSTD_match_t* const matches = optStatePtr->matchTable;
@@ -847,7 +822,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
847
822
  DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
848
823
  (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
849
824
  assert(optLevel <= 2);
850
- ms->nextToUpdate3 = ms->nextToUpdate;
851
825
  ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
852
826
  ip += (ip==prefixStart);
853
827
 
@@ -858,19 +832,24 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
858
832
  /* find first match */
859
833
  { U32 const litlen = (U32)(ip - anchor);
860
834
  U32 const ll0 = !litlen;
861
- U32 const nbMatches = ZSTD_BtGetAllMatches(ms, ip, iend, dictMode, rep, ll0, matches, minMatch);
835
+ U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
862
836
  if (!nbMatches) { ip++; continue; }
863
837
 
864
838
  /* initialize opt[0] */
865
839
  { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
866
840
  opt[0].mlen = 0; /* means is_a_literal */
867
841
  opt[0].litlen = litlen;
868
- opt[0].price = ZSTD_literalsContribution(anchor, litlen, optStatePtr, optLevel);
842
+ /* We don't need to include the actual price of the literals because
843
+ * it is static for the duration of the forward pass, and is included
844
+ * in every price. We include the literal length to avoid negative
845
+ * prices when we subtract the previous literal length.
846
+ */
847
+ opt[0].price = ZSTD_litLengthPrice(litlen, optStatePtr, optLevel);
869
848
 
870
849
  /* large match -> immediate encoding */
871
850
  { U32 const maxML = matches[nbMatches-1].len;
872
851
  U32 const maxOffset = matches[nbMatches-1].off;
873
- DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new serie",
852
+ DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
874
853
  nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
875
854
 
876
855
  if (maxML > sufficient_len) {
@@ -894,7 +873,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
894
873
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
895
874
  U32 const offset = matches[matchNb].off;
896
875
  U32 const end = matches[matchNb].len;
897
- repcodes_t const repHistory = ZSTD_updateRep(rep, offset, ll0);
898
876
  for ( ; pos <= end ; pos++ ) {
899
877
  U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
900
878
  U32 const sequencePrice = literalsPrice + matchPrice;
@@ -904,8 +882,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
904
882
  opt[pos].off = offset;
905
883
  opt[pos].litlen = litlen;
906
884
  opt[pos].price = sequencePrice;
907
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
908
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
909
885
  } }
910
886
  last_pos = pos-1;
911
887
  }
@@ -932,7 +908,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
932
908
  opt[cur].off = 0;
933
909
  opt[cur].litlen = litlen;
934
910
  opt[cur].price = price;
935
- memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep));
936
911
  } else {
937
912
  DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
938
913
  inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
@@ -940,6 +915,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
940
915
  }
941
916
  }
942
917
 
918
+ /* Set the repcodes of the current position. We must do it here
919
+ * because we rely on the repcodes of the 2nd to last sequence being
920
+ * correct to set the next chunks repcodes during the backward
921
+ * traversal.
922
+ */
923
+ ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(repcodes_t));
924
+ assert(cur >= opt[cur].mlen);
925
+ if (opt[cur].mlen != 0) {
926
+ U32 const prev = cur - opt[cur].mlen;
927
+ repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
928
+ memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
929
+ } else {
930
+ memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
931
+ }
932
+
943
933
  /* last match must start at a minimum distance of 8 from oend */
944
934
  if (inr > ilimit) continue;
945
935
 
@@ -955,7 +945,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
955
945
  U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
956
946
  U32 const previousPrice = opt[cur].price;
957
947
  U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
958
- U32 const nbMatches = ZSTD_BtGetAllMatches(ms, inr, iend, dictMode, opt[cur].rep, ll0, matches, minMatch);
948
+ U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
959
949
  U32 matchNb;
960
950
  if (!nbMatches) {
961
951
  DEBUGLOG(7, "rPos:%u : no match found", cur);
@@ -980,7 +970,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
980
970
  /* set prices using matches found at position == cur */
981
971
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
982
972
  U32 const offset = matches[matchNb].off;
983
- repcodes_t const repHistory = ZSTD_updateRep(opt[cur].rep, offset, ll0);
984
973
  U32 const lastML = matches[matchNb].len;
985
974
  U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;
986
975
  U32 mlen;
@@ -1000,8 +989,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1000
989
  opt[pos].off = offset;
1001
990
  opt[pos].litlen = litlen;
1002
991
  opt[pos].price = price;
1003
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
1004
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
1005
992
  } else {
1006
993
  DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
1007
994
  pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
@@ -1017,6 +1004,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1017
1004
  _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1018
1005
  assert(opt[0].mlen == 0);
1019
1006
 
1007
+ /* Set the next chunk's repcodes based on the repcodes of the beginning
1008
+ * of the last match, and the last sequence. This avoids us having to
1009
+ * update them while traversing the sequences.
1010
+ */
1011
+ if (lastSequence.mlen != 0) {
1012
+ repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
1013
+ memcpy(rep, &reps, sizeof(reps));
1014
+ } else {
1015
+ memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
1016
+ }
1017
+
1020
1018
  { U32 const storeEnd = cur + 1;
1021
1019
  U32 storeStart = storeEnd;
1022
1020
  U32 seqPos = cur;
@@ -1053,33 +1051,18 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1053
1051
  continue; /* will finish */
1054
1052
  }
1055
1053
 
1056
- /* repcodes update : like ZSTD_updateRep(), but update in place */
1057
- if (offCode >= ZSTD_REP_NUM) { /* full offset */
1058
- rep[2] = rep[1];
1059
- rep[1] = rep[0];
1060
- rep[0] = offCode - ZSTD_REP_MOVE;
1061
- } else { /* repcode */
1062
- U32 const repCode = offCode + (llen==0);
1063
- if (repCode) { /* note : if repCode==0, no change */
1064
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
1065
- if (repCode >= 2) rep[2] = rep[1];
1066
- rep[1] = rep[0];
1067
- rep[0] = currentOffset;
1068
- } }
1069
-
1070
1054
  assert(anchor + llen <= iend);
1071
1055
  ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
1072
- ZSTD_storeSeq(seqStore, llen, anchor, offCode, mlen-MINMATCH);
1056
+ ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
1073
1057
  anchor += advance;
1074
1058
  ip = anchor;
1075
1059
  } }
1076
1060
  ZSTD_setBasePrices(optStatePtr, optLevel);
1077
1061
  }
1078
-
1079
1062
  } /* while (ip < ilimit) */
1080
1063
 
1081
1064
  /* Return the last literals size */
1082
- return iend - anchor;
1065
+ return (size_t)(iend - anchor);
1083
1066
  }
1084
1067
 
1085
1068
 
@@ -1108,7 +1091,8 @@ static U32 ZSTD_upscaleStat(unsigned* table, U32 lastEltIndex, int bonus)
1108
1091
  /* used in 2-pass strategy */
1109
1092
  MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
1110
1093
  {
1111
- optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
1094
+ if (ZSTD_compressedLiterals(optPtr))
1095
+ optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
1112
1096
  optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0);
1113
1097
  optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0);
1114
1098
  optPtr->offCodeSum = ZSTD_upscaleStat(optPtr->offCodeFreq, MaxOff, 0);
@@ -1117,7 +1101,7 @@ MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
1117
1101
  /* ZSTD_initStats_ultra():
1118
1102
  * make a first compression pass, just to seed stats with more accurate starting values.
1119
1103
  * only works on first block, with no dictionary and no ldm.
1120
- * this function cannot error, hence its constract must be respected.
1104
+ * this function cannot error, hence its contract must be respected.
1121
1105
  */
1122
1106
  static void
1123
1107
  ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
@@ -1142,7 +1126,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
1142
1126
  ms->window.dictLimit += (U32)srcSize;
1143
1127
  ms->window.lowLimit = ms->window.dictLimit;
1144
1128
  ms->nextToUpdate = ms->window.dictLimit;
1145
- ms->nextToUpdate3 = ms->window.dictLimit;
1146
1129
 
1147
1130
  /* re-inforce weight of collected statistics */
1148
1131
  ZSTD_upscaleStats(&ms->opt);