extzstd 0.3 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.ja.md +8 -0
  3. data/README.md +1 -1
  4. data/contrib/zstd/CHANGELOG +94 -0
  5. data/contrib/zstd/CONTRIBUTING.md +351 -1
  6. data/contrib/zstd/Makefile +32 -10
  7. data/contrib/zstd/README.md +33 -10
  8. data/contrib/zstd/TESTING.md +2 -2
  9. data/contrib/zstd/appveyor.yml +42 -4
  10. data/contrib/zstd/lib/Makefile +128 -60
  11. data/contrib/zstd/lib/README.md +47 -16
  12. data/contrib/zstd/lib/common/bitstream.h +38 -39
  13. data/contrib/zstd/lib/common/compiler.h +40 -5
  14. data/contrib/zstd/lib/common/cpu.h +1 -1
  15. data/contrib/zstd/lib/common/debug.c +11 -31
  16. data/contrib/zstd/lib/common/debug.h +11 -31
  17. data/contrib/zstd/lib/common/entropy_common.c +13 -33
  18. data/contrib/zstd/lib/common/error_private.c +2 -1
  19. data/contrib/zstd/lib/common/error_private.h +6 -2
  20. data/contrib/zstd/lib/common/fse.h +12 -32
  21. data/contrib/zstd/lib/common/fse_decompress.c +12 -35
  22. data/contrib/zstd/lib/common/huf.h +15 -33
  23. data/contrib/zstd/lib/common/mem.h +75 -2
  24. data/contrib/zstd/lib/common/pool.c +8 -4
  25. data/contrib/zstd/lib/common/pool.h +2 -2
  26. data/contrib/zstd/lib/common/threading.c +50 -4
  27. data/contrib/zstd/lib/common/threading.h +36 -4
  28. data/contrib/zstd/lib/common/xxhash.c +23 -35
  29. data/contrib/zstd/lib/common/xxhash.h +11 -31
  30. data/contrib/zstd/lib/common/zstd_common.c +1 -1
  31. data/contrib/zstd/lib/common/zstd_errors.h +2 -1
  32. data/contrib/zstd/lib/common/zstd_internal.h +154 -26
  33. data/contrib/zstd/lib/compress/fse_compress.c +17 -40
  34. data/contrib/zstd/lib/compress/hist.c +15 -35
  35. data/contrib/zstd/lib/compress/hist.h +12 -32
  36. data/contrib/zstd/lib/compress/huf_compress.c +92 -92
  37. data/contrib/zstd/lib/compress/zstd_compress.c +1191 -1330
  38. data/contrib/zstd/lib/compress/zstd_compress_internal.h +317 -55
  39. data/contrib/zstd/lib/compress/zstd_compress_literals.c +158 -0
  40. data/contrib/zstd/lib/compress/zstd_compress_literals.h +29 -0
  41. data/contrib/zstd/lib/compress/zstd_compress_sequences.c +419 -0
  42. data/contrib/zstd/lib/compress/zstd_compress_sequences.h +54 -0
  43. data/contrib/zstd/lib/compress/zstd_compress_superblock.c +845 -0
  44. data/contrib/zstd/lib/compress/zstd_compress_superblock.h +32 -0
  45. data/contrib/zstd/lib/compress/zstd_cwksp.h +525 -0
  46. data/contrib/zstd/lib/compress/zstd_double_fast.c +65 -43
  47. data/contrib/zstd/lib/compress/zstd_double_fast.h +2 -2
  48. data/contrib/zstd/lib/compress/zstd_fast.c +92 -66
  49. data/contrib/zstd/lib/compress/zstd_fast.h +2 -2
  50. data/contrib/zstd/lib/compress/zstd_lazy.c +74 -42
  51. data/contrib/zstd/lib/compress/zstd_lazy.h +1 -1
  52. data/contrib/zstd/lib/compress/zstd_ldm.c +32 -10
  53. data/contrib/zstd/lib/compress/zstd_ldm.h +7 -2
  54. data/contrib/zstd/lib/compress/zstd_opt.c +81 -114
  55. data/contrib/zstd/lib/compress/zstd_opt.h +1 -1
  56. data/contrib/zstd/lib/compress/zstdmt_compress.c +95 -51
  57. data/contrib/zstd/lib/compress/zstdmt_compress.h +3 -2
  58. data/contrib/zstd/lib/decompress/huf_decompress.c +76 -60
  59. data/contrib/zstd/lib/decompress/zstd_ddict.c +12 -8
  60. data/contrib/zstd/lib/decompress/zstd_ddict.h +2 -2
  61. data/contrib/zstd/lib/decompress/zstd_decompress.c +292 -172
  62. data/contrib/zstd/lib/decompress/zstd_decompress_block.c +459 -338
  63. data/contrib/zstd/lib/decompress/zstd_decompress_block.h +3 -3
  64. data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +18 -4
  65. data/contrib/zstd/lib/deprecated/zbuff.h +9 -8
  66. data/contrib/zstd/lib/deprecated/zbuff_common.c +2 -2
  67. data/contrib/zstd/lib/deprecated/zbuff_compress.c +1 -1
  68. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +1 -1
  69. data/contrib/zstd/lib/dictBuilder/cover.c +164 -54
  70. data/contrib/zstd/lib/dictBuilder/cover.h +52 -7
  71. data/contrib/zstd/lib/dictBuilder/fastcover.c +60 -43
  72. data/contrib/zstd/lib/dictBuilder/zdict.c +43 -19
  73. data/contrib/zstd/lib/dictBuilder/zdict.h +56 -28
  74. data/contrib/zstd/lib/legacy/zstd_legacy.h +8 -4
  75. data/contrib/zstd/lib/legacy/zstd_v01.c +110 -110
  76. data/contrib/zstd/lib/legacy/zstd_v01.h +1 -1
  77. data/contrib/zstd/lib/legacy/zstd_v02.c +23 -13
  78. data/contrib/zstd/lib/legacy/zstd_v02.h +1 -1
  79. data/contrib/zstd/lib/legacy/zstd_v03.c +23 -13
  80. data/contrib/zstd/lib/legacy/zstd_v03.h +1 -1
  81. data/contrib/zstd/lib/legacy/zstd_v04.c +30 -17
  82. data/contrib/zstd/lib/legacy/zstd_v04.h +1 -1
  83. data/contrib/zstd/lib/legacy/zstd_v05.c +113 -102
  84. data/contrib/zstd/lib/legacy/zstd_v05.h +2 -2
  85. data/contrib/zstd/lib/legacy/zstd_v06.c +20 -18
  86. data/contrib/zstd/lib/legacy/zstd_v06.h +1 -1
  87. data/contrib/zstd/lib/legacy/zstd_v07.c +25 -19
  88. data/contrib/zstd/lib/legacy/zstd_v07.h +1 -1
  89. data/contrib/zstd/lib/libzstd.pc.in +3 -2
  90. data/contrib/zstd/lib/zstd.h +265 -88
  91. data/ext/extzstd.h +1 -1
  92. data/ext/libzstd_conf.h +8 -0
  93. data/ext/zstd_common.c +1 -3
  94. data/ext/zstd_compress.c +3 -3
  95. data/ext/zstd_decompress.c +1 -5
  96. data/ext/zstd_dictbuilder.c +2 -3
  97. data/ext/zstd_dictbuilder_fastcover.c +1 -3
  98. data/ext/zstd_legacy_v01.c +2 -0
  99. data/ext/zstd_legacy_v02.c +2 -0
  100. data/ext/zstd_legacy_v03.c +2 -0
  101. data/ext/zstd_legacy_v04.c +2 -0
  102. data/ext/zstd_legacy_v05.c +2 -0
  103. data/ext/zstd_legacy_v06.c +2 -0
  104. data/ext/zstd_legacy_v07.c +2 -0
  105. data/lib/extzstd.rb +18 -10
  106. data/lib/extzstd/version.rb +1 -1
  107. metadata +15 -6
@@ -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
@@ -249,40 +249,6 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
249
249
  }
250
250
  }
251
251
 
252
- /* ZSTD_litLengthContribution() :
253
- * @return ( cost(litlength) - cost(0) )
254
- * this value can then be added to rawLiteralsCost()
255
- * to provide a cost which is directly comparable to a match ending at same position */
256
- static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel)
257
- {
258
- if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel);
259
-
260
- /* dynamic statistics */
261
- { U32 const llCode = ZSTD_LLcode(litLength);
262
- int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER)
263
- + WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
264
- - WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
265
- #if 1
266
- return contribution;
267
- #else
268
- return MAX(0, contribution); /* sometimes better, sometimes not ... */
269
- #endif
270
- }
271
- }
272
-
273
- /* ZSTD_literalsContribution() :
274
- * creates a fake cost for the literals part of a sequence
275
- * which can be compared to the ending cost of a match
276
- * should a new match start at this position */
277
- static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLength,
278
- const optState_t* const optPtr,
279
- int optLevel)
280
- {
281
- int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
282
- + ZSTD_litLengthContribution(litLength, optPtr, optLevel);
283
- return contribution;
284
- }
285
-
286
252
  /* ZSTD_getMatchPrice() :
287
253
  * Provides the cost of the match part (offset + matchLength) of a sequence
288
254
  * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
@@ -372,13 +338,15 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
372
338
 
373
339
  /* Update hashTable3 up to ip (excluded)
374
340
  Assumption : always within prefix (i.e. not within extDict) */
375
- 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)
376
344
  {
377
345
  U32* const hashTable3 = ms->hashTable3;
378
346
  U32 const hashLog3 = ms->hashLog3;
379
347
  const BYTE* const base = ms->window.base;
380
- U32 idx = ms->nextToUpdate3;
381
- U32 const target = ms->nextToUpdate3 = (U32)(ip - base);
348
+ U32 idx = *nextToUpdate3;
349
+ U32 const target = (U32)(ip - base);
382
350
  size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);
383
351
  assert(hashLog3 > 0);
384
352
 
@@ -387,6 +355,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
387
355
  idx++;
388
356
  }
389
357
 
358
+ *nextToUpdate3 = target;
390
359
  return hashTable3[hash3];
391
360
  }
392
361
 
@@ -503,9 +472,11 @@ static U32 ZSTD_insertBt1(
503
472
  } }
504
473
 
505
474
  *smallerPtr = *largerPtr = 0;
506
- if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
507
- assert(matchEndIdx > current + 8);
508
- 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
+ }
509
480
  }
510
481
 
511
482
  FORCE_INLINE_TEMPLATE
@@ -520,8 +491,13 @@ void ZSTD_updateTree_internal(
520
491
  DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
521
492
  idx, target, dictMode);
522
493
 
523
- while(idx < target)
524
- 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));
525
501
  ms->nextToUpdate = target;
526
502
  }
527
503
 
@@ -531,11 +507,12 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
531
507
 
532
508
  FORCE_INLINE_TEMPLATE
533
509
  U32 ZSTD_insertBtAndGetAllMatches (
510
+ ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
534
511
  ZSTD_matchState_t* ms,
512
+ U32* nextToUpdate3,
535
513
  const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
536
- U32 rep[ZSTD_REP_NUM],
514
+ const U32 rep[ZSTD_REP_NUM],
537
515
  U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
538
- ZSTD_match_t* matches,
539
516
  const U32 lengthToBeat,
540
517
  U32 const mls /* template */)
541
518
  {
@@ -556,8 +533,8 @@ U32 ZSTD_insertBtAndGetAllMatches (
556
533
  U32 const dictLimit = ms->window.dictLimit;
557
534
  const BYTE* const dictEnd = dictBase + dictLimit;
558
535
  const BYTE* const prefixStart = base + dictLimit;
559
- U32 const btLow = btMask >= current ? 0 : current - btMask;
560
- 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);
561
538
  U32 const matchLow = windowLow ? windowLow : 1;
562
539
  U32* smallerPtr = bt + 2*(current&btMask);
563
540
  U32* largerPtr = bt + 2*(current&btMask) + 1;
@@ -592,7 +569,10 @@ U32 ZSTD_insertBtAndGetAllMatches (
592
569
  U32 repLen = 0;
593
570
  assert(current >= dictLimit);
594
571
  if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */
595
- 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))) {
596
576
  repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;
597
577
  }
598
578
  } else { /* repIndex < dictLimit || repIndex >= current */
@@ -627,7 +607,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
627
607
 
628
608
  /* HC3 match finder */
629
609
  if ((mls == 3) /*static*/ && (bestLength < mls)) {
630
- U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
610
+ U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);
631
611
  if ((matchIndex3 >= matchLow)
632
612
  & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
633
613
  size_t mlen;
@@ -653,9 +633,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
653
633
  (ip+mlen == iLimit) ) { /* best possible length */
654
634
  ms->nextToUpdate = current+1; /* skip insertion */
655
635
  return 1;
656
- }
657
- }
658
- }
636
+ } } }
659
637
  /* no dictMatchState lookup: dicts don't have a populated HC3 table */
660
638
  }
661
639
 
@@ -663,19 +641,21 @@ U32 ZSTD_insertBtAndGetAllMatches (
663
641
 
664
642
  while (nbCompares-- && (matchIndex >= matchLow)) {
665
643
  U32* const nextPtr = bt + 2*(matchIndex & btMask);
666
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
667
644
  const BYTE* match;
645
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
668
646
  assert(current > matchIndex);
669
647
 
670
648
  if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {
671
649
  assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */
672
650
  match = base + matchIndex;
651
+ if (matchIndex >= dictLimit) assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
673
652
  matchLength += ZSTD_count(ip+matchLength, match+matchLength, iLimit);
674
653
  } else {
675
654
  match = dictBase + matchIndex;
655
+ assert(memcmp(match, ip, matchLength) == 0); /* ensure early section of match is equal as expected */
676
656
  matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
677
657
  if (matchIndex+matchLength >= dictLimit)
678
- match = base + matchIndex; /* prepare for match[matchLength] */
658
+ match = base + matchIndex; /* prepare for match[matchLength] read */
679
659
  }
680
660
 
681
661
  if (matchLength > bestLength) {
@@ -760,10 +740,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
760
740
 
761
741
 
762
742
  FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
743
+ ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
763
744
  ZSTD_matchState_t* ms,
745
+ U32* nextToUpdate3,
764
746
  const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
765
- U32 rep[ZSTD_REP_NUM], U32 const ll0,
766
- ZSTD_match_t* matches, U32 const lengthToBeat)
747
+ const U32 rep[ZSTD_REP_NUM],
748
+ U32 const ll0,
749
+ U32 const lengthToBeat)
767
750
  {
768
751
  const ZSTD_compressionParameters* const cParams = &ms->cParams;
769
752
  U32 const matchLengthSearch = cParams->minMatch;
@@ -772,12 +755,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
772
755
  ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
773
756
  switch(matchLengthSearch)
774
757
  {
775
- 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);
776
759
  default :
777
- case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4);
778
- 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);
779
762
  case 7 :
780
- 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);
781
764
  }
782
765
  }
783
766
 
@@ -785,30 +768,6 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
785
768
  /*-*******************************
786
769
  * Optimal parser
787
770
  *********************************/
788
- typedef struct repcodes_s {
789
- U32 rep[3];
790
- } repcodes_t;
791
-
792
- static repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
793
- {
794
- repcodes_t newReps;
795
- if (offset >= ZSTD_REP_NUM) { /* full offset */
796
- newReps.rep[2] = rep[1];
797
- newReps.rep[1] = rep[0];
798
- newReps.rep[0] = offset - ZSTD_REP_MOVE;
799
- } else { /* repcode */
800
- U32 const repCode = offset + ll0;
801
- if (repCode > 0) { /* note : if repCode==0, no change */
802
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
803
- newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
804
- newReps.rep[1] = rep[0];
805
- newReps.rep[0] = currentOffset;
806
- } else { /* repCode == 0 */
807
- memcpy(&newReps, rep, sizeof(newReps));
808
- }
809
- }
810
- return newReps;
811
- }
812
771
 
813
772
 
814
773
  static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
@@ -825,7 +784,7 @@ listStats(const U32* table, int lastEltID)
825
784
  int enb;
826
785
  for (enb=0; enb < nbElts; enb++) {
827
786
  (void)table;
828
- //RAWLOG(2, "%3i:%3i, ", enb, table[enb]);
787
+ /* RAWLOG(2, "%3i:%3i, ", enb, table[enb]); */
829
788
  RAWLOG(2, "%4i,", table[enb]);
830
789
  }
831
790
  RAWLOG(2, " \n");
@@ -853,6 +812,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
853
812
 
854
813
  U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
855
814
  U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
815
+ U32 nextToUpdate3 = ms->nextToUpdate;
856
816
 
857
817
  ZSTD_optimal_t* const opt = optStatePtr->priceTable;
858
818
  ZSTD_match_t* const matches = optStatePtr->matchTable;
@@ -862,7 +822,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
862
822
  DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
863
823
  (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
864
824
  assert(optLevel <= 2);
865
- ms->nextToUpdate3 = ms->nextToUpdate;
866
825
  ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
867
826
  ip += (ip==prefixStart);
868
827
 
@@ -873,14 +832,19 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
873
832
  /* find first match */
874
833
  { U32 const litlen = (U32)(ip - anchor);
875
834
  U32 const ll0 = !litlen;
876
- 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);
877
836
  if (!nbMatches) { ip++; continue; }
878
837
 
879
838
  /* initialize opt[0] */
880
839
  { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
881
840
  opt[0].mlen = 0; /* means is_a_literal */
882
841
  opt[0].litlen = litlen;
883
- 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);
884
848
 
885
849
  /* large match -> immediate encoding */
886
850
  { U32 const maxML = matches[nbMatches-1].len;
@@ -909,7 +873,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
909
873
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
910
874
  U32 const offset = matches[matchNb].off;
911
875
  U32 const end = matches[matchNb].len;
912
- repcodes_t const repHistory = ZSTD_updateRep(rep, offset, ll0);
913
876
  for ( ; pos <= end ; pos++ ) {
914
877
  U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
915
878
  U32 const sequencePrice = literalsPrice + matchPrice;
@@ -919,8 +882,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
919
882
  opt[pos].off = offset;
920
883
  opt[pos].litlen = litlen;
921
884
  opt[pos].price = sequencePrice;
922
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
923
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
924
885
  } }
925
886
  last_pos = pos-1;
926
887
  }
@@ -947,7 +908,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
947
908
  opt[cur].off = 0;
948
909
  opt[cur].litlen = litlen;
949
910
  opt[cur].price = price;
950
- memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep));
951
911
  } else {
952
912
  DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
953
913
  inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
@@ -955,6 +915,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
955
915
  }
956
916
  }
957
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
+
958
933
  /* last match must start at a minimum distance of 8 from oend */
959
934
  if (inr > ilimit) continue;
960
935
 
@@ -970,7 +945,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
970
945
  U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
971
946
  U32 const previousPrice = opt[cur].price;
972
947
  U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
973
- 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);
974
949
  U32 matchNb;
975
950
  if (!nbMatches) {
976
951
  DEBUGLOG(7, "rPos:%u : no match found", cur);
@@ -995,7 +970,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
995
970
  /* set prices using matches found at position == cur */
996
971
  for (matchNb = 0; matchNb < nbMatches; matchNb++) {
997
972
  U32 const offset = matches[matchNb].off;
998
- repcodes_t const repHistory = ZSTD_updateRep(opt[cur].rep, offset, ll0);
999
973
  U32 const lastML = matches[matchNb].len;
1000
974
  U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;
1001
975
  U32 mlen;
@@ -1015,8 +989,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1015
989
  opt[pos].off = offset;
1016
990
  opt[pos].litlen = litlen;
1017
991
  opt[pos].price = price;
1018
- ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
1019
- memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
1020
992
  } else {
1021
993
  DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
1022
994
  pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
@@ -1032,6 +1004,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
1032
1004
  _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1033
1005
  assert(opt[0].mlen == 0);
1034
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
+
1035
1018
  { U32 const storeEnd = cur + 1;
1036
1019
  U32 storeStart = storeEnd;
1037
1020
  U32 seqPos = cur;
@@ -1068,33 +1051,18 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
1068
1051
  continue; /* will finish */
1069
1052
  }
1070
1053
 
1071
- /* repcodes update : like ZSTD_updateRep(), but update in place */
1072
- if (offCode >= ZSTD_REP_NUM) { /* full offset */
1073
- rep[2] = rep[1];
1074
- rep[1] = rep[0];
1075
- rep[0] = offCode - ZSTD_REP_MOVE;
1076
- } else { /* repcode */
1077
- U32 const repCode = offCode + (llen==0);
1078
- if (repCode) { /* note : if repCode==0, no change */
1079
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
1080
- if (repCode >= 2) rep[2] = rep[1];
1081
- rep[1] = rep[0];
1082
- rep[0] = currentOffset;
1083
- } }
1084
-
1085
1054
  assert(anchor + llen <= iend);
1086
1055
  ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
1087
- ZSTD_storeSeq(seqStore, llen, anchor, offCode, mlen-MINMATCH);
1056
+ ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
1088
1057
  anchor += advance;
1089
1058
  ip = anchor;
1090
1059
  } }
1091
1060
  ZSTD_setBasePrices(optStatePtr, optLevel);
1092
1061
  }
1093
-
1094
1062
  } /* while (ip < ilimit) */
1095
1063
 
1096
1064
  /* Return the last literals size */
1097
- return iend - anchor;
1065
+ return (size_t)(iend - anchor);
1098
1066
  }
1099
1067
 
1100
1068
 
@@ -1158,7 +1126,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
1158
1126
  ms->window.dictLimit += (U32)srcSize;
1159
1127
  ms->window.lowLimit = ms->window.dictLimit;
1160
1128
  ms->nextToUpdate = ms->window.dictLimit;
1161
- ms->nextToUpdate3 = ms->window.dictLimit;
1162
1129
 
1163
1130
  /* re-inforce weight of collected statistics */
1164
1131
  ZSTD_upscaleStats(&ms->opt);