[med-svn] [libzstd] 03/07: Fix failed merge of upstream code
Kevin Murray
daube-guest at moszumanska.debian.org
Thu Jul 21 02:46:57 UTC 2016
This is an automated email from the git hooks/post-receive script.
daube-guest pushed a commit to branch master
in repository libzstd.
commit cfaac28bfbd9db243a87f4e0d1115d56a3ca082e
Author: Kevin Murray <spam at kdmurray.id.au>
Date: Thu Jul 21 10:53:32 2016 +1000
Fix failed merge of upstream code
---
lib/divsufsort.c | 1913 ----------------------------------------------------
lib/divsufsort.h | 67 --
lib/zdict.c | 923 -------------------------
lib/zdict.h | 67 --
lib/zdict_static.h | 80 ---
lib/zstd_opt.h | 1125 ------------------------------
programs/fileio.c | 22 +-
programs/zstd.1 | 17 -
programs/zstdcli.c | 1 -
9 files changed, 1 insertion(+), 4214 deletions(-)
diff --git a/lib/divsufsort.c b/lib/divsufsort.c
deleted file mode 100644
index 60cceb0..0000000
--- a/lib/divsufsort.c
+++ /dev/null
@@ -1,1913 +0,0 @@
-/*
- * divsufsort.c for libdivsufsort-lite
- * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*- Compiler specifics -*/
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wshorten-64-to-32"
-#endif
-
-#if defined(_MSC_VER)
-# pragma warning(disable : 4244)
-# pragma warning(disable : 4127) /* C4127 : Condition expression is constant */
-#endif
-
-
-/*- Dependencies -*/
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "divsufsort.h"
-
-/*- Constants -*/
-#if defined(INLINE)
-# undef INLINE
-#endif
-#if !defined(INLINE)
-# define INLINE __inline
-#endif
-#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1)
-# undef ALPHABET_SIZE
-#endif
-#if !defined(ALPHABET_SIZE)
-# define ALPHABET_SIZE (256)
-#endif
-#define BUCKET_A_SIZE (ALPHABET_SIZE)
-#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE)
-#if defined(SS_INSERTIONSORT_THRESHOLD)
-# if SS_INSERTIONSORT_THRESHOLD < 1
-# undef SS_INSERTIONSORT_THRESHOLD
-# define SS_INSERTIONSORT_THRESHOLD (1)
-# endif
-#else
-# define SS_INSERTIONSORT_THRESHOLD (8)
-#endif
-#if defined(SS_BLOCKSIZE)
-# if SS_BLOCKSIZE < 0
-# undef SS_BLOCKSIZE
-# define SS_BLOCKSIZE (0)
-# elif 32768 <= SS_BLOCKSIZE
-# undef SS_BLOCKSIZE
-# define SS_BLOCKSIZE (32767)
-# endif
-#else
-# define SS_BLOCKSIZE (1024)
-#endif
-/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */
-#if SS_BLOCKSIZE == 0
-# define SS_MISORT_STACKSIZE (96)
-#elif SS_BLOCKSIZE <= 4096
-# define SS_MISORT_STACKSIZE (16)
-#else
-# define SS_MISORT_STACKSIZE (24)
-#endif
-#define SS_SMERGE_STACKSIZE (32)
-#define TR_INSERTIONSORT_THRESHOLD (8)
-#define TR_STACKSIZE (64)
-
-
-/*- Macros -*/
-#ifndef SWAP
-# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0)
-#endif /* SWAP */
-#ifndef MIN
-# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
-#endif /* MIN */
-#ifndef MAX
-# define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
-#endif /* MAX */
-#define STACK_PUSH(_a, _b, _c, _d)\
- do {\
- assert(ssize < STACK_SIZE);\
- stack[ssize].a = (_a), stack[ssize].b = (_b),\
- stack[ssize].c = (_c), stack[ssize++].d = (_d);\
- } while(0)
-#define STACK_PUSH5(_a, _b, _c, _d, _e)\
- do {\
- assert(ssize < STACK_SIZE);\
- stack[ssize].a = (_a), stack[ssize].b = (_b),\
- stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\
- } while(0)
-#define STACK_POP(_a, _b, _c, _d)\
- do {\
- assert(0 <= ssize);\
- if(ssize == 0) { return; }\
- (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
- (_c) = stack[ssize].c, (_d) = stack[ssize].d;\
- } while(0)
-#define STACK_POP5(_a, _b, _c, _d, _e)\
- do {\
- assert(0 <= ssize);\
- if(ssize == 0) { return; }\
- (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
- (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\
- } while(0)
-#define BUCKET_A(_c0) bucket_A[(_c0)]
-#if ALPHABET_SIZE == 256
-#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)])
-#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)])
-#else
-#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)])
-#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)])
-#endif
-
-
-/*- Private Functions -*/
-
-static const int lg_table[256]= {
- -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-};
-
-#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
-
-static INLINE
-int
-ss_ilg(int n) {
-#if SS_BLOCKSIZE == 0
- return (n & 0xffff0000) ?
- ((n & 0xff000000) ?
- 24 + lg_table[(n >> 24) & 0xff] :
- 16 + lg_table[(n >> 16) & 0xff]) :
- ((n & 0x0000ff00) ?
- 8 + lg_table[(n >> 8) & 0xff] :
- 0 + lg_table[(n >> 0) & 0xff]);
-#elif SS_BLOCKSIZE < 256
- return lg_table[n];
-#else
- return (n & 0xff00) ?
- 8 + lg_table[(n >> 8) & 0xff] :
- 0 + lg_table[(n >> 0) & 0xff];
-#endif
-}
-
-#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
-
-#if SS_BLOCKSIZE != 0
-
-static const int sqq_table[256] = {
- 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61,
- 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89,
- 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109,
-110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
-128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
-143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155,
-156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,
-169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180,
-181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191,
-192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201,
-202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211,
-212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221,
-221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230,
-230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
-239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247,
-247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255
-};
-
-static INLINE
-int
-ss_isqrt(int x) {
- int y, e;
-
- if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; }
- e = (x & 0xffff0000) ?
- ((x & 0xff000000) ?
- 24 + lg_table[(x >> 24) & 0xff] :
- 16 + lg_table[(x >> 16) & 0xff]) :
- ((x & 0x0000ff00) ?
- 8 + lg_table[(x >> 8) & 0xff] :
- 0 + lg_table[(x >> 0) & 0xff]);
-
- if(e >= 16) {
- y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7);
- if(e >= 24) { y = (y + 1 + x / y) >> 1; }
- y = (y + 1 + x / y) >> 1;
- } else if(e >= 8) {
- y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1;
- } else {
- return sqq_table[x] >> 4;
- }
-
- return (x < (y * y)) ? y - 1 : y;
-}
-
-#endif /* SS_BLOCKSIZE != 0 */
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Compares two suffixes. */
-static INLINE
-int
-ss_compare(const unsigned char *T,
- const int *p1, const int *p2,
- int depth) {
- const unsigned char *U1, *U2, *U1n, *U2n;
-
- for(U1 = T + depth + *p1,
- U2 = T + depth + *p2,
- U1n = T + *(p1 + 1) + 2,
- U2n = T + *(p2 + 1) + 2;
- (U1 < U1n) && (U2 < U2n) && (*U1 == *U2);
- ++U1, ++U2) {
- }
-
- return U1 < U1n ?
- (U2 < U2n ? *U1 - *U2 : 1) :
- (U2 < U2n ? -1 : 0);
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1)
-
-/* Insertionsort for small size groups */
-static
-void
-ss_insertionsort(const unsigned char *T, const int *PA,
- int *first, int *last, int depth) {
- int *i, *j;
- int t;
- int r;
-
- for(i = last - 2; first <= i; --i) {
- for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) {
- do { *(j - 1) = *j; } while((++j < last) && (*j < 0));
- if(last <= j) { break; }
- }
- if(r == 0) { *j = ~*j; }
- *(j - 1) = t;
- }
-}
-
-#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */
-
-
-/*---------------------------------------------------------------------------*/
-
-#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
-
-static INLINE
-void
-ss_fixdown(const unsigned char *Td, const int *PA,
- int *SA, int i, int size) {
- int j, k;
- int v;
- int c, d, e;
-
- for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
- d = Td[PA[SA[k = j++]]];
- if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; }
- if(d <= c) { break; }
- }
- SA[i] = v;
-}
-
-/* Simple top-down heapsort. */
-static
-void
-ss_heapsort(const unsigned char *Td, const int *PA, int *SA, int size) {
- int i, m;
- int t;
-
- m = size;
- if((size % 2) == 0) {
- m--;
- if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); }
- }
-
- for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); }
- if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); }
- for(i = m - 1; 0 < i; --i) {
- t = SA[0], SA[0] = SA[i];
- ss_fixdown(Td, PA, SA, 0, i);
- SA[i] = t;
- }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Returns the median of three elements. */
-static INLINE
-int *
-ss_median3(const unsigned char *Td, const int *PA,
- int *v1, int *v2, int *v3) {
- int *t;
- if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); }
- if(Td[PA[*v2]] > Td[PA[*v3]]) {
- if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; }
- else { return v3; }
- }
- return v2;
-}
-
-/* Returns the median of five elements. */
-static INLINE
-int *
-ss_median5(const unsigned char *Td, const int *PA,
- int *v1, int *v2, int *v3, int *v4, int *v5) {
- int *t;
- if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); }
- if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); }
- if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); }
- if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); }
- if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); }
- if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; }
- return v3;
-}
-
-/* Returns the pivot element. */
-static INLINE
-int *
-ss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) {
- int *middle;
- int t;
-
- t = last - first;
- middle = first + t / 2;
-
- if(t <= 512) {
- if(t <= 32) {
- return ss_median3(Td, PA, first, middle, last - 1);
- } else {
- t >>= 2;
- return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1);
- }
- }
- t >>= 3;
- first = ss_median3(Td, PA, first, first + t, first + (t << 1));
- middle = ss_median3(Td, PA, middle - t, middle, middle + t);
- last = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1);
- return ss_median3(Td, PA, first, middle, last);
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Binary partition for substrings. */
-static INLINE
-int *
-ss_partition(const int *PA,
- int *first, int *last, int depth) {
- int *a, *b;
- int t;
- for(a = first - 1, b = last;;) {
- for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; }
- for(; (a < --b) && ((PA[*b] + depth) < (PA[*b + 1] + 1));) { }
- if(b <= a) { break; }
- t = ~*b;
- *b = *a;
- *a = t;
- }
- if(first < a) { *first = ~*first; }
- return a;
-}
-
-/* Multikey introsort for medium size groups. */
-static
-void
-ss_mintrosort(const unsigned char *T, const int *PA,
- int *first, int *last,
- int depth) {
-#define STACK_SIZE SS_MISORT_STACKSIZE
- struct { int *a, *b, c; int d; } stack[STACK_SIZE];
- const unsigned char *Td;
- int *a, *b, *c, *d, *e, *f;
- int s, t;
- int ssize;
- int limit;
- int v, x = 0;
-
- for(ssize = 0, limit = ss_ilg(last - first);;) {
-
- if((last - first) <= SS_INSERTIONSORT_THRESHOLD) {
-#if 1 < SS_INSERTIONSORT_THRESHOLD
- if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); }
-#endif
- STACK_POP(first, last, depth, limit);
- continue;
- }
-
- Td = T + depth;
- if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); }
- if(limit < 0) {
- for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) {
- if((x = Td[PA[*a]]) != v) {
- if(1 < (a - first)) { break; }
- v = x;
- first = a;
- }
- }
- if(Td[PA[*first] - 1] < v) {
- first = ss_partition(PA, first, a, depth);
- }
- if((a - first) <= (last - a)) {
- if(1 < (a - first)) {
- STACK_PUSH(a, last, depth, -1);
- last = a, depth += 1, limit = ss_ilg(a - first);
- } else {
- first = a, limit = -1;
- }
- } else {
- if(1 < (last - a)) {
- STACK_PUSH(first, a, depth + 1, ss_ilg(a - first));
- first = a, limit = -1;
- } else {
- last = a, depth += 1, limit = ss_ilg(a - first);
- }
- }
- continue;
- }
-
- /* choose pivot */
- a = ss_pivot(Td, PA, first, last);
- v = Td[PA[*a]];
- SWAP(*first, *a);
-
- /* partition */
- for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { }
- if(((a = b) < last) && (x < v)) {
- for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) {
- if(x == v) { SWAP(*b, *a); ++a; }
- }
- }
- for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { }
- if((b < (d = c)) && (x > v)) {
- for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
- if(x == v) { SWAP(*c, *d); --d; }
- }
- }
- for(; b < c;) {
- SWAP(*b, *c);
- for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) {
- if(x == v) { SWAP(*b, *a); ++a; }
- }
- for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
- if(x == v) { SWAP(*c, *d); --d; }
- }
- }
-
- if(a <= d) {
- c = b - 1;
-
- if((s = a - first) > (t = b - a)) { s = t; }
- for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
- if((s = d - c) > (t = last - d - 1)) { s = t; }
- for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
-
- a = first + (b - a), c = last - (d - c);
- b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth);
-
- if((a - first) <= (last - c)) {
- if((last - c) <= (c - b)) {
- STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
- STACK_PUSH(c, last, depth, limit);
- last = a;
- } else if((a - first) <= (c - b)) {
- STACK_PUSH(c, last, depth, limit);
- STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
- last = a;
- } else {
- STACK_PUSH(c, last, depth, limit);
- STACK_PUSH(first, a, depth, limit);
- first = b, last = c, depth += 1, limit = ss_ilg(c - b);
- }
- } else {
- if((a - first) <= (c - b)) {
- STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
- STACK_PUSH(first, a, depth, limit);
- first = c;
- } else if((last - c) <= (c - b)) {
- STACK_PUSH(first, a, depth, limit);
- STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
- first = c;
- } else {
- STACK_PUSH(first, a, depth, limit);
- STACK_PUSH(c, last, depth, limit);
- first = b, last = c, depth += 1, limit = ss_ilg(c - b);
- }
- }
- } else {
- limit += 1;
- if(Td[PA[*first] - 1] < v) {
- first = ss_partition(PA, first, last, depth);
- limit = ss_ilg(last - first);
- }
- depth += 1;
- }
- }
-#undef STACK_SIZE
-}
-
-#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
-
-
-/*---------------------------------------------------------------------------*/
-
-#if SS_BLOCKSIZE != 0
-
-static INLINE
-void
-ss_blockswap(int *a, int *b, int n) {
- int t;
- for(; 0 < n; --n, ++a, ++b) {
- t = *a, *a = *b, *b = t;
- }
-}
-
-static INLINE
-void
-ss_rotate(int *first, int *middle, int *last) {
- int *a, *b, t;
- int l, r;
- l = middle - first, r = last - middle;
- for(; (0 < l) && (0 < r);) {
- if(l == r) { ss_blockswap(first, middle, l); break; }
- if(l < r) {
- a = last - 1, b = middle - 1;
- t = *a;
- do {
- *a-- = *b, *b-- = *a;
- if(b < first) {
- *a = t;
- last = a;
- if((r -= l + 1) <= l) { break; }
- a -= 1, b = middle - 1;
- t = *a;
- }
- } while(1);
- } else {
- a = first, b = middle;
- t = *a;
- do {
- *a++ = *b, *b++ = *a;
- if(last <= b) {
- *a = t;
- first = a + 1;
- if((l -= r + 1) <= r) { break; }
- a += 1, b = middle;
- t = *a;
- }
- } while(1);
- }
- }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-static
-void
-ss_inplacemerge(const unsigned char *T, const int *PA,
- int *first, int *middle, int *last,
- int depth) {
- const int *p;
- int *a, *b;
- int len, half;
- int q, r;
- int x;
-
- for(;;) {
- if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); }
- else { x = 0; p = PA + *(last - 1); }
- for(a = first, len = middle - first, half = len >> 1, r = -1;
- 0 < len;
- len = half, half >>= 1) {
- b = a + half;
- q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth);
- if(q < 0) {
- a = b + 1;
- half -= (len & 1) ^ 1;
- } else {
- r = q;
- }
- }
- if(a < middle) {
- if(r == 0) { *a = ~*a; }
- ss_rotate(a, middle, last);
- last -= middle - a;
- middle = a;
- if(first == middle) { break; }
- }
- --last;
- if(x != 0) { while(*--last < 0) { } }
- if(middle == last) { break; }
- }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Merge-forward with internal buffer. */
-static
-void
-ss_mergeforward(const unsigned char *T, const int *PA,
- int *first, int *middle, int *last,
- int *buf, int depth) {
- int *a, *b, *c, *bufend;
- int t;
- int r;
-
- bufend = buf + (middle - first) - 1;
- ss_blockswap(buf, first, middle - first);
-
- for(t = *(a = first), b = buf, c = middle;;) {
- r = ss_compare(T, PA + *b, PA + *c, depth);
- if(r < 0) {
- do {
- *a++ = *b;
- if(bufend <= b) { *bufend = t; return; }
- *b++ = *a;
- } while(*b < 0);
- } else if(r > 0) {
- do {
- *a++ = *c, *c++ = *a;
- if(last <= c) {
- while(b < bufend) { *a++ = *b, *b++ = *a; }
- *a = *b, *b = t;
- return;
- }
- } while(*c < 0);
- } else {
- *c = ~*c;
- do {
- *a++ = *b;
- if(bufend <= b) { *bufend = t; return; }
- *b++ = *a;
- } while(*b < 0);
-
- do {
- *a++ = *c, *c++ = *a;
- if(last <= c) {
- while(b < bufend) { *a++ = *b, *b++ = *a; }
- *a = *b, *b = t;
- return;
- }
- } while(*c < 0);
- }
- }
-}
-
-/* Merge-backward with internal buffer. */
-static
-void
-ss_mergebackward(const unsigned char *T, const int *PA,
- int *first, int *middle, int *last,
- int *buf, int depth) {
- const int *p1, *p2;
- int *a, *b, *c, *bufend;
- int t;
- int r;
- int x;
-
- bufend = buf + (last - middle) - 1;
- ss_blockswap(buf, middle, last - middle);
-
- x = 0;
- if(*bufend < 0) { p1 = PA + ~*bufend; x |= 1; }
- else { p1 = PA + *bufend; }
- if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; }
- else { p2 = PA + *(middle - 1); }
- for(t = *(a = last - 1), b = bufend, c = middle - 1;;) {
- r = ss_compare(T, p1, p2, depth);
- if(0 < r) {
- if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
- *a-- = *b;
- if(b <= buf) { *buf = t; break; }
- *b-- = *a;
- if(*b < 0) { p1 = PA + ~*b; x |= 1; }
- else { p1 = PA + *b; }
- } else if(r < 0) {
- if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
- *a-- = *c, *c-- = *a;
- if(c < first) {
- while(buf < b) { *a-- = *b, *b-- = *a; }
- *a = *b, *b = t;
- break;
- }
- if(*c < 0) { p2 = PA + ~*c; x |= 2; }
- else { p2 = PA + *c; }
- } else {
- if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
- *a-- = ~*b;
- if(b <= buf) { *buf = t; break; }
- *b-- = *a;
- if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
- *a-- = *c, *c-- = *a;
- if(c < first) {
- while(buf < b) { *a-- = *b, *b-- = *a; }
- *a = *b, *b = t;
- break;
- }
- if(*b < 0) { p1 = PA + ~*b; x |= 1; }
- else { p1 = PA + *b; }
- if(*c < 0) { p2 = PA + ~*c; x |= 2; }
- else { p2 = PA + *c; }
- }
- }
-}
-
-/* D&C based merge. */
-static
-void
-ss_swapmerge(const unsigned char *T, const int *PA,
- int *first, int *middle, int *last,
- int *buf, int bufsize, int depth) {
-#define STACK_SIZE SS_SMERGE_STACKSIZE
-#define GETIDX(a) ((0 <= (a)) ? (a) : (~(a)))
-#define MERGE_CHECK(a, b, c)\
- do {\
- if(((c) & 1) ||\
- (((c) & 2) && (ss_compare(T, PA + GETIDX(*((a) - 1)), PA + *(a), depth) == 0))) {\
- *(a) = ~*(a);\
- }\
- if(((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b) - 1)), PA + *(b), depth) == 0))) {\
- *(b) = ~*(b);\
- }\
- } while(0)
- struct { int *a, *b, *c; int d; } stack[STACK_SIZE];
- int *l, *r, *lm, *rm;
- int m, len, half;
- int ssize;
- int check, next;
-
- for(check = 0, ssize = 0;;) {
- if((last - middle) <= bufsize) {
- if((first < middle) && (middle < last)) {
- ss_mergebackward(T, PA, first, middle, last, buf, depth);
- }
- MERGE_CHECK(first, last, check);
- STACK_POP(first, middle, last, check);
- continue;
- }
-
- if((middle - first) <= bufsize) {
- if(first < middle) {
- ss_mergeforward(T, PA, first, middle, last, buf, depth);
- }
- MERGE_CHECK(first, last, check);
- STACK_POP(first, middle, last, check);
- continue;
- }
-
- for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1;
- 0 < len;
- len = half, half >>= 1) {
- if(ss_compare(T, PA + GETIDX(*(middle + m + half)),
- PA + GETIDX(*(middle - m - half - 1)), depth) < 0) {
- m += half + 1;
- half -= (len & 1) ^ 1;
- }
- }
-
- if(0 < m) {
- lm = middle - m, rm = middle + m;
- ss_blockswap(lm, middle, m);
- l = r = middle, next = 0;
- if(rm < last) {
- if(*rm < 0) {
- *rm = ~*rm;
- if(first < lm) { for(; *--l < 0;) { } next |= 4; }
- next |= 1;
- } else if(first < lm) {
- for(; *r < 0; ++r) { }
- next |= 2;
- }
- }
-
- if((l - first) <= (last - r)) {
- STACK_PUSH(r, rm, last, (next & 3) | (check & 4));
- middle = lm, last = l, check = (check & 3) | (next & 4);
- } else {
- if((next & 2) && (r == middle)) { next ^= 6; }
- STACK_PUSH(first, lm, l, (check & 3) | (next & 4));
- first = r, middle = rm, check = (next & 3) | (check & 4);
- }
- } else {
- if(ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) {
- *middle = ~*middle;
- }
- MERGE_CHECK(first, last, check);
- STACK_POP(first, middle, last, check);
- }
- }
-#undef STACK_SIZE
-}
-
-#endif /* SS_BLOCKSIZE != 0 */
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Substring sort */
-static
-void
-sssort(const unsigned char *T, const int *PA,
- int *first, int *last,
- int *buf, int bufsize,
- int depth, int n, int lastsuffix) {
- int *a;
-#if SS_BLOCKSIZE != 0
- int *b, *middle, *curbuf;
- int j, k, curbufsize, limit;
-#endif
- int i;
-
- if(lastsuffix != 0) { ++first; }
-
-#if SS_BLOCKSIZE == 0
- ss_mintrosort(T, PA, first, last, depth);
-#else
- if((bufsize < SS_BLOCKSIZE) &&
- (bufsize < (last - first)) &&
- (bufsize < (limit = ss_isqrt(last - first)))) {
- if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; }
- buf = middle = last - limit, bufsize = limit;
- } else {
- middle = last, limit = 0;
- }
- for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) {
-#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
- ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth);
-#elif 1 < SS_BLOCKSIZE
- ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth);
-#endif
- curbufsize = last - (a + SS_BLOCKSIZE);
- curbuf = a + SS_BLOCKSIZE;
- if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; }
- for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) {
- ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth);
- }
- }
-#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
- ss_mintrosort(T, PA, a, middle, depth);
-#elif 1 < SS_BLOCKSIZE
- ss_insertionsort(T, PA, a, middle, depth);
-#endif
- for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) {
- if(i & 1) {
- ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth);
- a -= k;
- }
- }
- if(limit != 0) {
-#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
- ss_mintrosort(T, PA, middle, last, depth);
-#elif 1 < SS_BLOCKSIZE
- ss_insertionsort(T, PA, middle, last, depth);
-#endif
- ss_inplacemerge(T, PA, first, middle, last, depth);
- }
-#endif
-
- if(lastsuffix != 0) {
- /* Insert last type B* suffix. */
- int PAi[2]; PAi[0] = PA[*(first - 1)], PAi[1] = n - 2;
- for(a = first, i = *(first - 1);
- (a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth)));
- ++a) {
- *(a - 1) = *a;
- }
- *(a - 1) = i;
- }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-static INLINE
-int
-tr_ilg(int n) {
- return (n & 0xffff0000) ?
- ((n & 0xff000000) ?
- 24 + lg_table[(n >> 24) & 0xff] :
- 16 + lg_table[(n >> 16) & 0xff]) :
- ((n & 0x0000ff00) ?
- 8 + lg_table[(n >> 8) & 0xff] :
- 0 + lg_table[(n >> 0) & 0xff]);
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Simple insertionsort for small size groups. */
-static
-void
-tr_insertionsort(const int *ISAd, int *first, int *last) {
- int *a, *b;
- int t, r;
-
- for(a = first + 1; a < last; ++a) {
- for(t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) {
- do { *(b + 1) = *b; } while((first <= --b) && (*b < 0));
- if(b < first) { break; }
- }
- if(r == 0) { *b = ~*b; }
- *(b + 1) = t;
- }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-static INLINE
-void
-tr_fixdown(const int *ISAd, int *SA, int i, int size) {
- int j, k;
- int v;
- int c, d, e;
-
- for(v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
- d = ISAd[SA[k = j++]];
- if(d < (e = ISAd[SA[j]])) { k = j; d = e; }
- if(d <= c) { break; }
- }
- SA[i] = v;
-}
-
-/* Simple top-down heapsort. */
-static
-void
-tr_heapsort(const int *ISAd, int *SA, int size) {
- int i, m;
- int t;
-
- m = size;
- if((size % 2) == 0) {
- m--;
- if(ISAd[SA[m / 2]] < ISAd[SA[m]]) { SWAP(SA[m], SA[m / 2]); }
- }
-
- for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISAd, SA, i, m); }
- if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISAd, SA, 0, m); }
- for(i = m - 1; 0 < i; --i) {
- t = SA[0], SA[0] = SA[i];
- tr_fixdown(ISAd, SA, 0, i);
- SA[i] = t;
- }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Returns the median of three elements. */
-static INLINE
-int *
-tr_median3(const int *ISAd, int *v1, int *v2, int *v3) {
- int *t;
- if(ISAd[*v1] > ISAd[*v2]) { SWAP(v1, v2); }
- if(ISAd[*v2] > ISAd[*v3]) {
- if(ISAd[*v1] > ISAd[*v3]) { return v1; }
- else { return v3; }
- }
- return v2;
-}
-
-/* Returns the median of five elements. */
-static INLINE
-int *
-tr_median5(const int *ISAd,
- int *v1, int *v2, int *v3, int *v4, int *v5) {
- int *t;
- if(ISAd[*v2] > ISAd[*v3]) { SWAP(v2, v3); }
- if(ISAd[*v4] > ISAd[*v5]) { SWAP(v4, v5); }
- if(ISAd[*v2] > ISAd[*v4]) { SWAP(v2, v4); SWAP(v3, v5); }
- if(ISAd[*v1] > ISAd[*v3]) { SWAP(v1, v3); }
- if(ISAd[*v1] > ISAd[*v4]) { SWAP(v1, v4); SWAP(v3, v5); }
- if(ISAd[*v3] > ISAd[*v4]) { return v4; }
- return v3;
-}
-
-/* Returns the pivot element. */
-static INLINE
-int *
-tr_pivot(const int *ISAd, int *first, int *last) {
- int *middle;
- int t;
-
- t = last - first;
- middle = first + t / 2;
-
- if(t <= 512) {
- if(t <= 32) {
- return tr_median3(ISAd, first, middle, last - 1);
- } else {
- t >>= 2;
- return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1);
- }
- }
- t >>= 3;
- first = tr_median3(ISAd, first, first + t, first + (t << 1));
- middle = tr_median3(ISAd, middle - t, middle, middle + t);
- last = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1);
- return tr_median3(ISAd, first, middle, last);
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-typedef struct _trbudget_t trbudget_t;
-struct _trbudget_t {
- int chance;
- int remain;
- int incval;
- int count;
-};
-
-static INLINE
-void
-trbudget_init(trbudget_t *budget, int chance, int incval) {
- budget->chance = chance;
- budget->remain = budget->incval = incval;
-}
-
-static INLINE
-int
-trbudget_check(trbudget_t *budget, int size) {
- if(size <= budget->remain) { budget->remain -= size; return 1; }
- if(budget->chance == 0) { budget->count += size; return 0; }
- budget->remain += budget->incval - size;
- budget->chance -= 1;
- return 1;
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-static INLINE
-void
-tr_partition(const int *ISAd,
- int *first, int *middle, int *last,
- int **pa, int **pb, int v) {
- int *a, *b, *c, *d, *e, *f;
- int t, s;
- int x = 0;
-
- for(b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) { }
- if(((a = b) < last) && (x < v)) {
- for(; (++b < last) && ((x = ISAd[*b]) <= v);) {
- if(x == v) { SWAP(*b, *a); ++a; }
- }
- }
- for(c = last; (b < --c) && ((x = ISAd[*c]) == v);) { }
- if((b < (d = c)) && (x > v)) {
- for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
- if(x == v) { SWAP(*c, *d); --d; }
- }
- }
- for(; b < c;) {
- SWAP(*b, *c);
- for(; (++b < c) && ((x = ISAd[*b]) <= v);) {
- if(x == v) { SWAP(*b, *a); ++a; }
- }
- for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
- if(x == v) { SWAP(*c, *d); --d; }
- }
- }
-
- if(a <= d) {
- c = b - 1;
- if((s = a - first) > (t = b - a)) { s = t; }
- for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
- if((s = d - c) > (t = last - d - 1)) { s = t; }
- for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
- first += (b - a), last -= (d - c);
- }
- *pa = first, *pb = last;
-}
-
-static
-void
-tr_copy(int *ISA, const int *SA,
- int *first, int *a, int *b, int *last,
- int depth) {
- /* sort suffixes of middle partition
- by using sorted order of suffixes of left and right partition. */
- int *c, *d, *e;
- int s, v;
-
- v = b - SA - 1;
- for(c = first, d = a - 1; c <= d; ++c) {
- if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
- *++d = s;
- ISA[s] = d - SA;
- }
- }
- for(c = last - 1, e = d + 1, d = b; e < d; --c) {
- if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
- *--d = s;
- ISA[s] = d - SA;
- }
- }
-}
-
-static
-void
-tr_partialcopy(int *ISA, const int *SA,
- int *first, int *a, int *b, int *last,
- int depth) {
- int *c, *d, *e;
- int s, v;
- int rank, lastrank, newrank = -1;
-
- v = b - SA - 1;
- lastrank = -1;
- for(c = first, d = a - 1; c <= d; ++c) {
- if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
- *++d = s;
- rank = ISA[s + depth];
- if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
- ISA[s] = newrank;
- }
- }
-
- lastrank = -1;
- for(e = d; first <= e; --e) {
- rank = ISA[*e];
- if(lastrank != rank) { lastrank = rank; newrank = e - SA; }
- if(newrank != rank) { ISA[*e] = newrank; }
- }
-
- lastrank = -1;
- for(c = last - 1, e = d + 1, d = b; e < d; --c) {
- if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
- *--d = s;
- rank = ISA[s + depth];
- if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
- ISA[s] = newrank;
- }
- }
-}
-
-static
-void
-tr_introsort(int *ISA, const int *ISAd,
- int *SA, int *first, int *last,
- trbudget_t *budget) {
-#define STACK_SIZE TR_STACKSIZE
- struct { const int *a; int *b, *c; int d, e; }stack[STACK_SIZE];
- int *a, *b, *c;
- int t;
- int v, x = 0;
- int incr = ISAd - ISA;
- int limit, next;
- int ssize, trlink = -1;
-
- for(ssize = 0, limit = tr_ilg(last - first);;) {
-
- if(limit < 0) {
- if(limit == -1) {
- /* tandem repeat partition */
- tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1);
-
- /* update ranks */
- if(a < last) {
- for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
- }
- if(b < last) {
- for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; }
- }
-
- /* push */
- if(1 < (b - a)) {
- STACK_PUSH5(NULL, a, b, 0, 0);
- STACK_PUSH5(ISAd - incr, first, last, -2, trlink);
- trlink = ssize - 2;
- }
- if((a - first) <= (last - b)) {
- if(1 < (a - first)) {
- STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink);
- last = a, limit = tr_ilg(a - first);
- } else if(1 < (last - b)) {
- first = b, limit = tr_ilg(last - b);
- } else {
- STACK_POP5(ISAd, first, last, limit, trlink);
- }
- } else {
- if(1 < (last - b)) {
- STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink);
- first = b, limit = tr_ilg(last - b);
- } else if(1 < (a - first)) {
- last = a, limit = tr_ilg(a - first);
- } else {
- STACK_POP5(ISAd, first, last, limit, trlink);
- }
- }
- } else if(limit == -2) {
- /* tandem repeat copy */
- a = stack[--ssize].b, b = stack[ssize].c;
- if(stack[ssize].d == 0) {
- tr_copy(ISA, SA, first, a, b, last, ISAd - ISA);
- } else {
- if(0 <= trlink) { stack[trlink].d = -1; }
- tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA);
- }
- STACK_POP5(ISAd, first, last, limit, trlink);
- } else {
- /* sorted partition */
- if(0 <= *first) {
- a = first;
- do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a));
- first = a;
- }
- if(first < last) {
- a = first; do { *a = ~*a; } while(*++a < 0);
- next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1;
- if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } }
-
- /* push */
- if(trbudget_check(budget, a - first)) {
- if((a - first) <= (last - a)) {
- STACK_PUSH5(ISAd, a, last, -3, trlink);
- ISAd += incr, last = a, limit = next;
- } else {
- if(1 < (last - a)) {
- STACK_PUSH5(ISAd + incr, first, a, next, trlink);
- first = a, limit = -3;
- } else {
- ISAd += incr, last = a, limit = next;
- }
- }
- } else {
- if(0 <= trlink) { stack[trlink].d = -1; }
- if(1 < (last - a)) {
- first = a, limit = -3;
- } else {
- STACK_POP5(ISAd, first, last, limit, trlink);
- }
- }
- } else {
- STACK_POP5(ISAd, first, last, limit, trlink);
- }
- }
- continue;
- }
-
- if((last - first) <= TR_INSERTIONSORT_THRESHOLD) {
- tr_insertionsort(ISAd, first, last);
- limit = -3;
- continue;
- }
-
- if(limit-- == 0) {
- tr_heapsort(ISAd, first, last - first);
- for(a = last - 1; first < a; a = b) {
- for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; }
- }
- limit = -3;
- continue;
- }
-
- /* choose pivot */
- a = tr_pivot(ISAd, first, last);
- SWAP(*first, *a);
- v = ISAd[*first];
-
- /* partition */
- tr_partition(ISAd, first, first + 1, last, &a, &b, v);
- if((last - first) != (b - a)) {
- next = (ISA[*a] != v) ? tr_ilg(b - a) : -1;
-
- /* update ranks */
- for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
- if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } }
-
- /* push */
- if((1 < (b - a)) && (trbudget_check(budget, b - a))) {
- if((a - first) <= (last - b)) {
- if((last - b) <= (b - a)) {
- if(1 < (a - first)) {
- STACK_PUSH5(ISAd + incr, a, b, next, trlink);
- STACK_PUSH5(ISAd, b, last, limit, trlink);
- last = a;
- } else if(1 < (last - b)) {
- STACK_PUSH5(ISAd + incr, a, b, next, trlink);
- first = b;
- } else {
- ISAd += incr, first = a, last = b, limit = next;
- }
- } else if((a - first) <= (b - a)) {
- if(1 < (a - first)) {
- STACK_PUSH5(ISAd, b, last, limit, trlink);
- STACK_PUSH5(ISAd + incr, a, b, next, trlink);
- last = a;
- } else {
- STACK_PUSH5(ISAd, b, last, limit, trlink);
- ISAd += incr, first = a, last = b, limit = next;
- }
- } else {
- STACK_PUSH5(ISAd, b, last, limit, trlink);
- STACK_PUSH5(ISAd, first, a, limit, trlink);
- ISAd += incr, first = a, last = b, limit = next;
- }
- } else {
- if((a - first) <= (b - a)) {
- if(1 < (last - b)) {
- STACK_PUSH5(ISAd + incr, a, b, next, trlink);
- STACK_PUSH5(ISAd, first, a, limit, trlink);
- first = b;
- } else if(1 < (a - first)) {
- STACK_PUSH5(ISAd + incr, a, b, next, trlink);
- last = a;
- } else {
- ISAd += incr, first = a, last = b, limit = next;
- }
- } else if((last - b) <= (b - a)) {
- if(1 < (last - b)) {
- STACK_PUSH5(ISAd, first, a, limit, trlink);
- STACK_PUSH5(ISAd + incr, a, b, next, trlink);
- first = b;
- } else {
- STACK_PUSH5(ISAd, first, a, limit, trlink);
- ISAd += incr, first = a, last = b, limit = next;
- }
- } else {
- STACK_PUSH5(ISAd, first, a, limit, trlink);
- STACK_PUSH5(ISAd, b, last, limit, trlink);
- ISAd += incr, first = a, last = b, limit = next;
- }
- }
- } else {
- if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; }
- if((a - first) <= (last - b)) {
- if(1 < (a - first)) {
- STACK_PUSH5(ISAd, b, last, limit, trlink);
- last = a;
- } else if(1 < (last - b)) {
- first = b;
- } else {
- STACK_POP5(ISAd, first, last, limit, trlink);
- }
- } else {
- if(1 < (last - b)) {
- STACK_PUSH5(ISAd, first, a, limit, trlink);
- first = b;
- } else if(1 < (a - first)) {
- last = a;
- } else {
- STACK_POP5(ISAd, first, last, limit, trlink);
- }
- }
- }
- } else {
- if(trbudget_check(budget, last - first)) {
- limit = tr_ilg(last - first), ISAd += incr;
- } else {
- if(0 <= trlink) { stack[trlink].d = -1; }
- STACK_POP5(ISAd, first, last, limit, trlink);
- }
- }
- }
-#undef STACK_SIZE
-}
-
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Tandem repeat sort */
-static
-void
-trsort(int *ISA, int *SA, int n, int depth) {
- int *ISAd;
- int *first, *last;
- trbudget_t budget;
- int t, skip, unsorted;
-
- trbudget_init(&budget, tr_ilg(n) * 2 / 3, n);
-/* trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */
- for(ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) {
- first = SA;
- skip = 0;
- unsorted = 0;
- do {
- if((t = *first) < 0) { first -= t; skip += t; }
- else {
- if(skip != 0) { *(first + skip) = skip; skip = 0; }
- last = SA + ISA[t] + 1;
- if(1 < (last - first)) {
- budget.count = 0;
- tr_introsort(ISA, ISAd, SA, first, last, &budget);
- if(budget.count != 0) { unsorted += budget.count; }
- else { skip = first - last; }
- } else if((last - first) == 1) {
- skip = -1;
- }
- first = last;
- }
- } while(first < (SA + n));
- if(skip != 0) { *(first + skip) = skip; }
- if(unsorted == 0) { break; }
- }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Sorts suffixes of type B*. */
-static
-int
-sort_typeBstar(const unsigned char *T, int *SA,
- int *bucket_A, int *bucket_B,
- int n, int openMP) {
- int *PAb, *ISAb, *buf;
-#ifdef LIBBSC_OPENMP
- int *curbuf;
- int l;
-#endif
- int i, j, k, t, m, bufsize;
- int c0, c1;
-#ifdef LIBBSC_OPENMP
- int d0, d1;
-#endif
- (void)openMP;
-
- /* Initialize bucket arrays. */
- for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; }
- for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; }
-
- /* Count the number of occurrences of the first one or two characters of each
- type A, B and B* suffix. Moreover, store the beginning position of all
- type B* suffixes into the array SA. */
- for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) {
- /* type A suffix. */
- do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1));
- if(0 <= i) {
- /* type B* suffix. */
- ++BUCKET_BSTAR(c0, c1);
- SA[--m] = i;
- /* type B suffix. */
- for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) {
- ++BUCKET_B(c0, c1);
- }
- }
- }
- m = n - m;
-/*
-note:
- A type B* suffix is lexicographically smaller than a type B suffix that
- begins with the same first two characters.
-*/
-
- /* Calculate the index of start/end point of each bucket. */
- for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) {
- t = i + BUCKET_A(c0);
- BUCKET_A(c0) = i + j; /* start point */
- i = t + BUCKET_B(c0, c0);
- for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) {
- j += BUCKET_BSTAR(c0, c1);
- BUCKET_BSTAR(c0, c1) = j; /* end point */
- i += BUCKET_B(c0, c1);
- }
- }
-
- if(0 < m) {
- /* Sort the type B* suffixes by their first two characters. */
- PAb = SA + n - m; ISAb = SA + m;
- for(i = m - 2; 0 <= i; --i) {
- t = PAb[i], c0 = T[t], c1 = T[t + 1];
- SA[--BUCKET_BSTAR(c0, c1)] = i;
- }
- t = PAb[m - 1], c0 = T[t], c1 = T[t + 1];
- SA[--BUCKET_BSTAR(c0, c1)] = m - 1;
-
- /* Sort the type B* substrings using sssort. */
-#ifdef LIBBSC_OPENMP
- if (openMP)
- {
- buf = SA + m;
- c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m;
-#pragma omp parallel default(shared) private(bufsize, curbuf, k, l, d0, d1)
- {
- bufsize = (n - (2 * m)) / omp_get_num_threads();
- curbuf = buf + omp_get_thread_num() * bufsize;
- k = 0;
- for(;;) {
- #pragma omp critical(sssort_lock)
- {
- if(0 < (l = j)) {
- d0 = c0, d1 = c1;
- do {
- k = BUCKET_BSTAR(d0, d1);
- if(--d1 <= d0) {
- d1 = ALPHABET_SIZE - 1;
- if(--d0 < 0) { break; }
- }
- } while(((l - k) <= 1) && (0 < (l = k)));
- c0 = d0, c1 = d1, j = k;
- }
- }
- if(l == 0) { break; }
- sssort(T, PAb, SA + k, SA + l,
- curbuf, bufsize, 2, n, *(SA + k) == (m - 1));
- }
- }
- }
- else
- {
- buf = SA + m, bufsize = n - (2 * m);
- for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {
- for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {
- i = BUCKET_BSTAR(c0, c1);
- if(1 < (j - i)) {
- sssort(T, PAb, SA + i, SA + j,
- buf, bufsize, 2, n, *(SA + i) == (m - 1));
- }
- }
- }
- }
-#else
- buf = SA + m, bufsize = n - (2 * m);
- for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {
- for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {
- i = BUCKET_BSTAR(c0, c1);
- if(1 < (j - i)) {
- sssort(T, PAb, SA + i, SA + j,
- buf, bufsize, 2, n, *(SA + i) == (m - 1));
- }
- }
- }
-#endif
-
- /* Compute ranks of type B* substrings. */
- for(i = m - 1; 0 <= i; --i) {
- if(0 <= SA[i]) {
- j = i;
- do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i]));
- SA[i + 1] = i - j;
- if(i <= 0) { break; }
- }
- j = i;
- do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0);
- ISAb[SA[i]] = j;
- }
-
- /* Construct the inverse suffix array of type B* suffixes using trsort. */
- trsort(ISAb, SA, m, 1);
-
- /* Set the sorted order of tyoe B* suffixes. */
- for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) {
- for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { }
- if(0 <= i) {
- t = i;
- for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { }
- SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t;
- }
- }
-
- /* Calculate the index of start/end point of each bucket. */
- BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */
- for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) {
- i = BUCKET_A(c0 + 1) - 1;
- for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) {
- t = i - BUCKET_B(c0, c1);
- BUCKET_B(c0, c1) = i; /* end point */
-
- /* Move all type B* suffixes to the correct position. */
- for(i = t, j = BUCKET_BSTAR(c0, c1);
- j <= k;
- --i, --k) { SA[i] = SA[k]; }
- }
- BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */
- BUCKET_B(c0, c0) = i; /* end point */
- }
- }
-
- return m;
-}
-
-/* Constructs the suffix array by using the sorted order of type B* suffixes. */
-static
-void
-construct_SA(const unsigned char *T, int *SA,
- int *bucket_A, int *bucket_B,
- int n, int m) {
- int *i, *j, *k;
- int s;
- int c0, c1, c2;
-
- if(0 < m) {
- /* Construct the sorted order of type B suffixes by using
- the sorted order of type B* suffixes. */
- for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
- /* Scan the suffix array from right to left. */
- for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
- j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
- i <= j;
- --j) {
- if(0 < (s = *j)) {
- assert(T[s] == c1);
- assert(((s + 1) < n) && (T[s] <= T[s + 1]));
- assert(T[s - 1] <= T[s]);
- *j = ~s;
- c0 = T[--s];
- if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
- if(c0 != c2) {
- if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
- k = SA + BUCKET_B(c2 = c0, c1);
- }
- assert(k < j);
- *k-- = s;
- } else {
- assert(((s == 0) && (T[s] == c1)) || (s < 0));
- *j = ~s;
- }
- }
- }
- }
-
- /* Construct the suffix array by using
- the sorted order of type B suffixes. */
- k = SA + BUCKET_A(c2 = T[n - 1]);
- *k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1);
- /* Scan the suffix array from left to right. */
- for(i = SA, j = SA + n; i < j; ++i) {
- if(0 < (s = *i)) {
- assert(T[s - 1] >= T[s]);
- c0 = T[--s];
- if((s == 0) || (T[s - 1] < c0)) { s = ~s; }
- if(c0 != c2) {
- BUCKET_A(c2) = k - SA;
- k = SA + BUCKET_A(c2 = c0);
- }
- assert(i < k);
- *k++ = s;
- } else {
- assert(s < 0);
- *i = ~s;
- }
- }
-}
-
-/* Constructs the burrows-wheeler transformed string directly
- by using the sorted order of type B* suffixes. */
-static
-int
-construct_BWT(const unsigned char *T, int *SA,
- int *bucket_A, int *bucket_B,
- int n, int m) {
- int *i, *j, *k, *orig;
- int s;
- int c0, c1, c2;
-
- if(0 < m) {
- /* Construct the sorted order of type B suffixes by using
- the sorted order of type B* suffixes. */
- for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
- /* Scan the suffix array from right to left. */
- for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
- j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
- i <= j;
- --j) {
- if(0 < (s = *j)) {
- assert(T[s] == c1);
- assert(((s + 1) < n) && (T[s] <= T[s + 1]));
- assert(T[s - 1] <= T[s]);
- c0 = T[--s];
- *j = ~((int)c0);
- if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
- if(c0 != c2) {
- if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
- k = SA + BUCKET_B(c2 = c0, c1);
- }
- assert(k < j);
- *k-- = s;
- } else if(s != 0) {
- *j = ~s;
-#ifndef NDEBUG
- } else {
- assert(T[s] == c1);
-#endif
- }
- }
- }
- }
-
- /* Construct the BWTed string by using
- the sorted order of type B suffixes. */
- k = SA + BUCKET_A(c2 = T[n - 1]);
- *k++ = (T[n - 2] < c2) ? ~((int)T[n - 2]) : (n - 1);
- /* Scan the suffix array from left to right. */
- for(i = SA, j = SA + n, orig = SA; i < j; ++i) {
- if(0 < (s = *i)) {
- assert(T[s - 1] >= T[s]);
- c0 = T[--s];
- *i = c0;
- if((0 < s) && (T[s - 1] < c0)) { s = ~((int)T[s - 1]); }
- if(c0 != c2) {
- BUCKET_A(c2) = k - SA;
- k = SA + BUCKET_A(c2 = c0);
- }
- assert(i < k);
- *k++ = s;
- } else if(s != 0) {
- *i = ~s;
- } else {
- orig = i;
- }
- }
-
- return orig - SA;
-}
-
-/* Constructs the burrows-wheeler transformed string directly
- by using the sorted order of type B* suffixes. */
-static
-int
-construct_BWT_indexes(const unsigned char *T, int *SA,
- int *bucket_A, int *bucket_B,
- int n, int m,
- unsigned char * num_indexes, int * indexes) {
- int *i, *j, *k, *orig;
- int s;
- int c0, c1, c2;
-
- int mod = n / 8;
- {
- mod |= mod >> 1; mod |= mod >> 2;
- mod |= mod >> 4; mod |= mod >> 8;
- mod |= mod >> 16; mod >>= 1;
-
- *num_indexes = (unsigned char)((n - 1) / (mod + 1));
- }
-
- if(0 < m) {
- /* Construct the sorted order of type B suffixes by using
- the sorted order of type B* suffixes. */
- for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
- /* Scan the suffix array from right to left. */
- for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
- j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
- i <= j;
- --j) {
- if(0 < (s = *j)) {
- assert(T[s] == c1);
- assert(((s + 1) < n) && (T[s] <= T[s + 1]));
- assert(T[s - 1] <= T[s]);
-
- if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = j - SA;
-
- c0 = T[--s];
- *j = ~((int)c0);
- if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
- if(c0 != c2) {
- if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
- k = SA + BUCKET_B(c2 = c0, c1);
- }
- assert(k < j);
- *k-- = s;
- } else if(s != 0) {
- *j = ~s;
-#ifndef NDEBUG
- } else {
- assert(T[s] == c1);
-#endif
- }
- }
- }
- }
-
- /* Construct the BWTed string by using
- the sorted order of type B suffixes. */
- k = SA + BUCKET_A(c2 = T[n - 1]);
- if (T[n - 2] < c2) {
- if (((n - 1) & mod) == 0) indexes[(n - 1) / (mod + 1) - 1] = k - SA;
- *k++ = ~((int)T[n - 2]);
- }
- else {
- *k++ = n - 1;
- }
-
- /* Scan the suffix array from left to right. */
- for(i = SA, j = SA + n, orig = SA; i < j; ++i) {
- if(0 < (s = *i)) {
- assert(T[s - 1] >= T[s]);
-
- if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = i - SA;
-
- c0 = T[--s];
- *i = c0;
- if(c0 != c2) {
- BUCKET_A(c2) = k - SA;
- k = SA + BUCKET_A(c2 = c0);
- }
- assert(i < k);
- if((0 < s) && (T[s - 1] < c0)) {
- if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = k - SA;
- *k++ = ~((int)T[s - 1]);
- } else
- *k++ = s;
- } else if(s != 0) {
- *i = ~s;
- } else {
- orig = i;
- }
- }
-
- return orig - SA;
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/*- Function -*/
-
-int
-divsufsort(const unsigned char *T, int *SA, int n, int openMP) {
- int *bucket_A, *bucket_B;
- int m;
- int err = 0;
-
- /* Check arguments. */
- if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; }
- else if(n == 0) { return 0; }
- else if(n == 1) { SA[0] = 0; return 0; }
- else if(n == 2) { m = (T[0] < T[1]); SA[m ^ 1] = 0, SA[m] = 1; return 0; }
-
- bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int));
- bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int));
-
- /* Suffixsort. */
- if((bucket_A != NULL) && (bucket_B != NULL)) {
- m = sort_typeBstar(T, SA, bucket_A, bucket_B, n, openMP);
- construct_SA(T, SA, bucket_A, bucket_B, n, m);
- } else {
- err = -2;
- }
-
- free(bucket_B);
- free(bucket_A);
-
- return err;
-}
-
-int
-divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP) {
- int *B;
- int *bucket_A, *bucket_B;
- int m, pidx, i;
-
- /* Check arguments. */
- if((T == NULL) || (U == NULL) || (n < 0)) { return -1; }
- else if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }
-
- if((B = A) == NULL) { B = (int *)malloc((size_t)(n + 1) * sizeof(int)); }
- bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int));
- bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int));
-
- /* Burrows-Wheeler Transform. */
- if((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) {
- m = sort_typeBstar(T, B, bucket_A, bucket_B, n, openMP);
-
- if (num_indexes == NULL || indexes == NULL) {
- pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m);
- } else {
- pidx = construct_BWT_indexes(T, B, bucket_A, bucket_B, n, m, num_indexes, indexes);
- }
-
- /* Copy to output string. */
- U[0] = T[n - 1];
- for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)B[i]; }
- for(i += 1; i < n; ++i) { U[i] = (unsigned char)B[i]; }
- pidx += 1;
- } else {
- pidx = -2;
- }
-
- free(bucket_B);
- free(bucket_A);
- if(A == NULL) { free(B); }
-
- return pidx;
-}
diff --git a/lib/divsufsort.h b/lib/divsufsort.h
deleted file mode 100644
index dac0936..0000000
--- a/lib/divsufsort.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * divsufsort.h for libdivsufsort-lite
- * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _DIVSUFSORT_H
-#define _DIVSUFSORT_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-/*- Prototypes -*/
-
-/**
- * Constructs the suffix array of a given string.
- * @param T[0..n-1] The input string.
- * @param SA[0..n-1] The output array of suffixes.
- * @param n The length of the given string.
- * @param openMP enables OpenMP optimization.
- * @return 0 if no error occurred, -1 or -2 otherwise.
- */
-int
-divsufsort(const unsigned char *T, int *SA, int n, int openMP);
-
-/**
- * Constructs the burrows-wheeler transformed string of a given string.
- * @param T[0..n-1] The input string.
- * @param U[0..n-1] The output string. (can be T)
- * @param A[0..n-1] The temporary array. (can be NULL)
- * @param n The length of the given string.
- * @param num_indexes The length of secondary indexes array. (can be NULL)
- * @param indexes The secondary indexes array. (can be NULL)
- * @param openMP enables OpenMP optimization.
- * @return The primary index if no error occurred, -1 or -2 otherwise.
- */
-int
-divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP);
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
-
-#endif /* _DIVSUFSORT_H */
diff --git a/lib/zdict.c b/lib/zdict.c
deleted file mode 100644
index d3d5784..0000000
--- a/lib/zdict.c
+++ /dev/null
@@ -1,923 +0,0 @@
-/*
- dictBuilder - dictionary builder for zstd
- Copyright (C) Yann Collet 2016
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
- distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- You can contact the author at :
- - Zstd homepage : https://www.zstd.net
-*/
-
-/*-**************************************
-* Compiler Options
-****************************************/
-/* Disable some Visual warning messages */
-#ifdef _MSC_VER
-# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#endif
-
-/* Unix Large Files support (>4GB) */
-#define _FILE_OFFSET_BITS 64
-#if (defined(__sun__) && (!defined(__LP64__))) /* Sun Solaris 32-bits requires specific definitions */
-# define _LARGEFILE_SOURCE
-#elif ! defined(__LP64__) /* No point defining Large file for 64 bit */
-# define _LARGEFILE64_SOURCE
-#endif
-
-
-/*-*************************************
-* Dependencies
-***************************************/
-#include <stdlib.h> /* malloc, free */
-#include <string.h> /* memset */
-#include <stdio.h> /* fprintf, fopen, ftello64 */
-#include <sys/types.h> /* stat64 */
-#include <sys/stat.h> /* stat64 */
-#include <time.h> /* clock */
-
-#include "mem.h" /* read */
-#include "error_private.h"
-#include "fse.h"
-#include "huff0_static.h"
-#include "zstd_internal.h"
-#include "divsufsort.h"
-#include "zdict_static.h"
-
-
-/*-*************************************
-* Compiler specifics
-***************************************/
-#if !defined(S_ISREG)
-# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
-#endif
-
-
-/*-*************************************
-* Constants
-***************************************/
-#define KB *(1 <<10)
-#define MB *(1 <<20)
-#define GB *(1U<<30)
-
-#define DICTLISTSIZE 10000
-
-#define NOISELENGTH 32
-#define PRIME1 2654435761U
-#define PRIME2 2246822519U
-
-#define MINRATIO 4
-static const U32 g_compressionLevel_default = 5;
-static const U32 g_selectivity_default = 9;
-static const size_t g_provision_entropySize = 200;
-static const size_t g_min_fast_dictContent = 192;
-
-
-/*-*************************************
-* Console display
-***************************************/
-#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
-#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
-static unsigned g_displayLevel = 0; /* 0 : no display; 1: errors; 2: default; 4: full information */
-
-#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
- if (ZDICT_GetMilliSpan(g_time) > refreshRate) \
- { g_time = clock(); DISPLAY(__VA_ARGS__); \
- if (g_displayLevel>=4) fflush(stdout); } }
-static const unsigned refreshRate = 300;
-static clock_t g_time = 0;
-
-static void ZDICT_printHex(U32 dlevel, const void* ptr, size_t length)
-{
- const BYTE* const b = (const BYTE*)ptr;
- size_t u;
- for (u=0; u<length; u++)
- {
- BYTE c = b[u];
- if (c<32 || c>126) c = '.'; /* non-printable char */
- DISPLAYLEVEL(dlevel, "%c", c);
- }
-}
-
-
-/*-********************************************************
-* Helper functions
-**********************************************************/
-static unsigned ZDICT_GetMilliSpan(clock_t nPrevious)
-{
- clock_t nCurrent = clock();
- unsigned nSpan = (unsigned)(((nCurrent - nPrevious) * 1000) / CLOCKS_PER_SEC);
- return nSpan;
-}
-
-unsigned ZDICT_isError(size_t errorCode) { return ERR_isError(errorCode); }
-
-const char* ZDICT_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
-
-
-/*-********************************************************
-* Dictionary training functions
-**********************************************************/
-static unsigned ZDICT_NbCommonBytes (register size_t val)
-{
- if (MEM_isLittleEndian()) {
- if (MEM_64bits()) {
-# if defined(_MSC_VER) && defined(_WIN64)
- unsigned long r = 0;
- _BitScanForward64( &r, (U64)val );
- return (unsigned)(r>>3);
-# elif defined(__GNUC__) && (__GNUC__ >= 3)
- return (__builtin_ctzll((U64)val) >> 3);
-# else
- static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
- return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
-# endif
- } else { /* 32 bits */
-# if defined(_MSC_VER)
- unsigned long r=0;
- _BitScanForward( &r, (U32)val );
- return (unsigned)(r>>3);
-# elif defined(__GNUC__) && (__GNUC__ >= 3)
- return (__builtin_ctz((U32)val) >> 3);
-# else
- static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
- return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
-# endif
- }
- } else { /* Big Endian CPU */
- if (MEM_64bits()) {
-# if defined(_MSC_VER) && defined(_WIN64)
- unsigned long r = 0;
- _BitScanReverse64( &r, val );
- return (unsigned)(r>>3);
-# elif defined(__GNUC__) && (__GNUC__ >= 3)
- return (__builtin_clzll(val) >> 3);
-# else
- unsigned r;
- const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
- if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
- if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
- r += (!val);
- return r;
-# endif
- } else { /* 32 bits */
-# if defined(_MSC_VER)
- unsigned long r = 0;
- _BitScanReverse( &r, (unsigned long)val );
- return (unsigned)(r>>3);
-# elif defined(__GNUC__) && (__GNUC__ >= 3)
- return (__builtin_clz((U32)val) >> 3);
-# else
- unsigned r;
- if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
- r += (!val);
- return r;
-# endif
- } }
-}
-
-
-/*! ZDICT_count() :
- Count the nb of common bytes between 2 pointers.
- Note : this function presumes end of buffer followed by noisy guard band.
-*/
-static size_t ZDICT_count(const void* pIn, const void* pMatch)
-{
- const char* const pStart = (const char*)pIn;
- for (;;) {
- size_t diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
- if (!diff) { pIn = (const char*)pIn+sizeof(size_t); pMatch = (const char*)pMatch+sizeof(size_t); continue; }
- pIn = (const char*)pIn+ZDICT_NbCommonBytes(diff);
- return (size_t)((const char*)pIn - pStart);
- }
-}
-
-
-typedef struct {
- U32 pos;
- U32 length;
- U32 savings;
-} dictItem;
-
-static void ZDICT_initDictItem(dictItem* d)
-{
- d->pos = 1;
- d->length = 0;
- d->savings = (U32)(-1);
-}
-
-
-#define LLIMIT 64 /* heuristic determined experimentally */
-#define MINMATCHLENGTH 7 /* heuristic determined experimentally */
-static dictItem ZDICT_analyzePos(
- BYTE* doneMarks,
- const int* suffix, U32 start,
- const void* buffer, U32 minRatio)
-{
- U32 lengthList[LLIMIT] = {0};
- U32 cumulLength[LLIMIT] = {0};
- U32 savings[LLIMIT] = {0};
- const BYTE* b = (const BYTE*)buffer;
- size_t length;
- size_t maxLength = LLIMIT;
- size_t pos = suffix[start];
- U32 end = start;
- dictItem solution;
-
- /* init */
- memset(&solution, 0, sizeof(solution));
- doneMarks[pos] = 1;
-
- /* trivial repetition cases */
- if ( (MEM_read16(b+pos+0) == MEM_read16(b+pos+2))
- ||(MEM_read16(b+pos+1) == MEM_read16(b+pos+3))
- ||(MEM_read16(b+pos+2) == MEM_read16(b+pos+4)) ) {
- /* skip and mark segment */
- U16 u16 = MEM_read16(b+pos+4);
- U32 u, e = 6;
- while (MEM_read16(b+pos+e) == u16) e+=2 ;
- if (b[pos+e] == b[pos+e-1]) e++;
- for (u=1; u<e; u++)
- doneMarks[pos+u] = 1;
- return solution;
- }
-
- /* look forward */
- do {
- end++;
- length = ZDICT_count(b + pos, b + suffix[end]);
- } while (length >=MINMATCHLENGTH);
-
- /* look backward */
- do {
- length = ZDICT_count(b + pos, b + *(suffix+start-1));
- if (length >=MINMATCHLENGTH) start--;
- } while(length >= MINMATCHLENGTH);
-
- /* exit if not found a minimum nb of repetitions */
- if (end-start < minRatio) {
- U32 idx;
- for(idx=start; idx<end; idx++)
- doneMarks[suffix[idx]] = 1;
- return solution;
- }
-
- {
- int i;
- U32 searchLength;
- U32 refinedStart = start;
- U32 refinedEnd = end;
-
- DISPLAYLEVEL(4, "\n");
- DISPLAYLEVEL(4, "found %3u matches of length >= %u at pos %7u ", (U32)(end-start), MINMATCHLENGTH, (U32)pos);
- DISPLAYLEVEL(4, "\n");
-
- for (searchLength = MINMATCHLENGTH ; ; searchLength++) {
- BYTE currentChar = 0;
- U32 currentCount = 0;
- U32 currentID = refinedStart;
- U32 id;
- U32 selectedCount = 0;
- U32 selectedID = currentID;
- for (id =refinedStart; id < refinedEnd; id++) {
- if (b[ suffix[id] + searchLength] != currentChar) {
- if (currentCount > selectedCount) {
- selectedCount = currentCount;
- selectedID = currentID;
- }
- currentID = id;
- currentChar = b[ suffix[id] + searchLength];
- currentCount = 0;
- }
- currentCount ++;
- }
- if (currentCount > selectedCount) { /* for last */
- selectedCount = currentCount;
- selectedID = currentID;
- }
-
- if (selectedCount < minRatio)
- break;
- refinedStart = selectedID;
- refinedEnd = refinedStart + selectedCount;
- }
-
- /* evaluate gain based on new ref */
- start = refinedStart;
- pos = suffix[refinedStart];
- end = start;
- memset(lengthList, 0, sizeof(lengthList));
-
- /* look forward */
- do {
- end++;
- length = ZDICT_count(b + pos, b + suffix[end]);
- if (length >= LLIMIT) length = LLIMIT-1;
- lengthList[length]++;
- } while (length >=MINMATCHLENGTH);
-
- /* look backward */
- do {
- length = ZDICT_count(b + pos, b + suffix[start-1]);
- if (length >= LLIMIT) length = LLIMIT-1;
- lengthList[length]++;
- if (length >=MINMATCHLENGTH) start--;
- } while(length >= MINMATCHLENGTH);
-
- /* largest useful length */
- memset(cumulLength, 0, sizeof(cumulLength));
- cumulLength[maxLength-1] = lengthList[maxLength-1];
- for (i=(int)(maxLength-2); i>=0; i--)
- cumulLength[i] = cumulLength[i+1] + lengthList[i];
-
- for (i=LLIMIT-1; i>=MINMATCHLENGTH; i--) if (cumulLength[i]>=minRatio) break;
- maxLength = i;
-
- /* reduce maxLength in case of final into repetitive data */
- {
- U32 l = (U32)maxLength;
- BYTE c = b[pos + maxLength-1];
- while (b[pos+l-2]==c) l--;
- maxLength = l;
- }
- if (maxLength < MINMATCHLENGTH) return solution; /* skip : no long-enough solution */
-
- /* calculate savings */
- savings[5] = 0;
- for (i=MINMATCHLENGTH; i<=(int)maxLength; i++)
- savings[i] = savings[i-1] + (lengthList[i] * (i-3));
-
- DISPLAYLEVEL(4, "Selected ref at position %u, of length %u : saves %u (ratio: %.2f) \n",
- (U32)pos, (U32)maxLength, savings[maxLength], (double)savings[maxLength] / maxLength);
-
- solution.pos = (U32)pos;
- solution.length = (U32)maxLength;
- solution.savings = savings[maxLength];
-
- /* mark positions done */
- {
- U32 id;
- U32 testedPos;
- for (id=start; id<end; id++) {
- U32 p, pEnd;
- testedPos = suffix[id];
- if (testedPos == pos)
- length = solution.length;
- else {
- length = ZDICT_count(b+pos, b+testedPos);
- if (length > solution.length) length = solution.length;
- }
- pEnd = (U32)(testedPos + length);
- for (p=testedPos; p<pEnd; p++)
- doneMarks[p] = 1;
- } } }
-
- return solution;
-}
-
-
-/*! ZDICT_checkMerge
- check if dictItem can be merged, do it if possible
- @return : id of destination elt, 0 if not merged
-*/
-static U32 ZDICT_checkMerge(dictItem* table, dictItem elt, U32 eltNbToSkip)
-{
- const U32 tableSize = table->pos;
- const U32 max = elt.pos + (elt.length-1);
-
- /* tail overlap */
- U32 u; for (u=1; u<tableSize; u++) {
- if (u==eltNbToSkip) continue;
- if ((table[u].pos > elt.pos) && (table[u].pos < max)) { /* overlap */
- /* append */
- U32 addedLength = table[u].pos - elt.pos;
- table[u].length += addedLength;
- table[u].pos = elt.pos;
- table[u].savings += elt.savings * addedLength / elt.length; /* rough approx */
- table[u].savings += elt.length / 8; /* rough approx */
- elt = table[u];
- while ((u>1) && (table[u-1].savings < elt.savings))
- table[u] = table[u-1], u--;
- table[u] = elt;
- return u;
- } }
-
- /* front overlap */
- for (u=1; u<tableSize; u++) {
- if (u==eltNbToSkip) continue;
- if ((table[u].pos + table[u].length > elt.pos) && (table[u].pos < elt.pos)) { /* overlap */
- /* append */
- int addedLength = (elt.pos + elt.length) - (table[u].pos + table[u].length);
- table[u].savings += elt.length / 8; /* rough approx */
- if (addedLength > 0) { /* otherwise, already included */
- table[u].length += addedLength;
- table[u].savings += elt.savings * addedLength / elt.length; /* rough approx */
- }
- elt = table[u];
- while ((u>1) && (table[u-1].savings < elt.savings))
- table[u] = table[u-1], u--;
- table[u] = elt;
- return u;
- } }
-
- return 0;
-}
-
-
-static void ZDICT_removeDictItem(dictItem* table, U32 id)
-{
- /* convention : first element is nb of elts */
- U32 max = table->pos;
- U32 u;
- if (!id) return; /* protection, should never happen */
- for (u=id; u<max-1; u++)
- table[u] = table[u+1];
- table->pos--;
-}
-
-
-static void ZDICT_insertDictItem(dictItem* table, U32 maxSize, dictItem elt)
-{
- /* merge if possible */
- U32 mergeId = ZDICT_checkMerge(table, elt, 0);
- if (mergeId) {
- U32 newMerge = 1;
- while (newMerge) {
- newMerge = ZDICT_checkMerge(table, table[mergeId], mergeId);
- if (newMerge) ZDICT_removeDictItem(table, mergeId);
- mergeId = newMerge;
- }
- return;
- }
-
- /* insert */
- {
- U32 current;
- U32 nextElt = table->pos;
- if (nextElt >= maxSize) nextElt = maxSize-1;
- current = nextElt-1;
- while (table[current].savings < elt.savings) {
- table[current+1] = table[current];
- current--;
- }
- table[current+1] = elt;
- table->pos = nextElt+1;
- }
-}
-
-
-static U32 ZDICT_dictSize(const dictItem* dictList)
-{
- U32 u, dictSize = 0;
- for (u=1; u<dictList[0].pos; u++)
- dictSize += dictList[u].length;
- return dictSize;
-}
-
-
-static size_t ZDICT_trainBuffer(dictItem* dictList, U32 dictListSize,
- const void* const buffer, const size_t bufferSize, /* buffer must end with noisy guard band */
- const size_t* fileSizes, unsigned nbFiles,
- U32 shiftRatio, unsigned maxDictSize)
-{
- int* const suffix0 = (int*)malloc((bufferSize+2)*sizeof(*suffix0));
- int* const suffix = suffix0+1;
- U32* reverseSuffix = (U32*)malloc((bufferSize)*sizeof(*reverseSuffix));
- BYTE* doneMarks = (BYTE*)malloc((bufferSize+16)*sizeof(*doneMarks)); /* +16 for overflow security */
- U32* filePos = (U32*)malloc(nbFiles * sizeof(*filePos));
- U32 minRatio = nbFiles >> shiftRatio;
- int divSuftSortResult;
- size_t result = 0;
-
- /* init */
- DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */
- if (!suffix0 || !reverseSuffix || !doneMarks || !filePos) {
- result = ERROR(memory_allocation);
- goto _cleanup;
- }
- if (minRatio < MINRATIO) minRatio = MINRATIO;
- memset(doneMarks, 0, bufferSize+16);
-
- /* sort */
- DISPLAYLEVEL(2, "sorting %u files of total size %u MB ...\n", nbFiles, (U32)(bufferSize>>20));
- divSuftSortResult = divsufsort((const unsigned char*)buffer, suffix, (int)bufferSize, 0);
- if (divSuftSortResult != 0) { result = ERROR(GENERIC); goto _cleanup; }
- suffix[bufferSize] = (int)bufferSize; /* leads into noise */
- suffix0[0] = (int)bufferSize; /* leads into noise */
- {
- /* build reverse suffix sort */
- size_t pos;
- for (pos=0; pos < bufferSize; pos++)
- reverseSuffix[suffix[pos]] = (U32)pos;
- /* build file pos */
- filePos[0] = 0;
- for (pos=1; pos<nbFiles; pos++)
- filePos[pos] = (U32)(filePos[pos-1] + fileSizes[pos-1]);
- }
-
- DISPLAYLEVEL(2, "finding patterns ... \n");
- DISPLAYLEVEL(3, "minimum ratio : %u \n", minRatio);
-
- {
- U32 cursor; for (cursor=0; cursor < bufferSize; ) {
- dictItem solution;
- if (doneMarks[cursor]) { cursor++; continue; }
- solution = ZDICT_analyzePos(doneMarks, suffix, reverseSuffix[cursor], buffer, minRatio);
- if (solution.length==0) { cursor++; continue; }
- ZDICT_insertDictItem(dictList, dictListSize, solution);
- cursor += solution.length;
- DISPLAYUPDATE(2, "\r%4.2f %% \r", (double)cursor / bufferSize * 100);
- } }
-
- /* limit dictionary size */
- {
- U32 max = dictList->pos; /* convention : nb of useful elts within dictList */
- U32 currentSize = 0;
- U32 n; for (n=1; n<max; n++) {
- currentSize += dictList[n].length;
- if (currentSize > maxDictSize) break;
- }
- dictList->pos = n;
- }
-
-_cleanup:
- free(suffix0);
- free(reverseSuffix);
- free(doneMarks);
- free(filePos);
- return result;
-}
-
-
-static void ZDICT_fillNoise(void* buffer, size_t length)
-{
- unsigned acc = PRIME1;
- size_t p=0;;
-
- for (p=0; p<length; p++) {
- acc *= PRIME2;
- ((unsigned char*)buffer)[p] = (unsigned char)(acc >> 21);
- }
-}
-
-
-typedef struct
-{
- ZSTD_CCtx* ref;
- ZSTD_CCtx* zc;
- void* workPlace; /* must be BLOCKSIZE allocated */
-} EStats_ress_t;
-
-
-static void ZDICT_countEStats(EStats_ress_t esr,
- U32* countLit, U32* offsetcodeCount, U32* matchlengthCount, U32* litlengthCount,
- const void* src, size_t srcSize)
-{
- const BYTE* bytePtr;
- const U32* u32Ptr;
- seqStore_t seqStore;
-
- if (srcSize > BLOCKSIZE) srcSize = BLOCKSIZE; /* protection vs large samples */
- ZSTD_copyCCtx(esr.zc, esr.ref);
- ZSTD_compressBlock(esr.zc, esr.workPlace, BLOCKSIZE, src, srcSize);
- seqStore = ZSTD_copySeqStore(esr.zc);
-
- /* count stats */
- for(bytePtr = seqStore.litStart; bytePtr < seqStore.lit; bytePtr++)
- countLit[*bytePtr]++;
- for(u32Ptr = seqStore.offsetStart; u32Ptr < seqStore.offset; u32Ptr++) {
- BYTE offcode = (BYTE)ZSTD_highbit(*u32Ptr) + 1;
- if (*u32Ptr==0) offcode=0;
- offsetcodeCount[offcode]++;
- }
- for(bytePtr = seqStore.matchLengthStart; bytePtr < seqStore.matchLength; bytePtr++)
- matchlengthCount[*bytePtr]++;
- for(bytePtr = seqStore.litLengthStart; bytePtr < seqStore.litLength; bytePtr++)
- litlengthCount[*bytePtr]++;
-}
-
-
-#define OFFCODE_MAX 18 /* only applicable to first block */
-static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
- unsigned compressionLevel,
- const void* srcBuffer, const size_t* fileSizes, unsigned nbFiles,
- const void* dictBuffer, size_t dictBufferSize)
-{
- U32 countLit[256];
- U32 offcodeCount[MaxOff+1];
- HUF_CREATE_STATIC_CTABLE(hufTable, 255);
- short offcodeNCount[MaxOff+1];
- U32 matchLengthCount[MaxML+1];
- short matchLengthNCount[MaxML+1];
- U32 litlengthCount[MaxLL+1];
- short litlengthNCount[MaxLL+1];
- EStats_ress_t esr;
- ZSTD_parameters params;
- U32 u, huffLog = 12, Offlog = OffFSELog, mlLog = MLFSELog, llLog = LLFSELog, total;
- size_t pos = 0, errorCode;
- size_t eSize = 0;
-
- /* init */
- for (u=0; u<256; u++) countLit[u]=1; /* any character must be described */
- for (u=0; u<=OFFCODE_MAX; u++) offcodeCount[u]=1;
- for (u=0; u<=MaxML; u++) matchLengthCount[u]=1;
- for (u=0; u<=MaxLL; u++) litlengthCount[u]=1;
- esr.ref = ZSTD_createCCtx();
- esr.zc = ZSTD_createCCtx();
- esr.workPlace = malloc(BLOCKSIZE);
- if (!esr.ref || !esr.zc || !esr.workPlace) {
- eSize = ERROR(memory_allocation);
- DISPLAYLEVEL(1, "Not enough memory");
- goto _cleanup;
- }
- if (compressionLevel==0) compressionLevel=g_compressionLevel_default;
- params = ZSTD_getParams(compressionLevel, dictBufferSize + 15 KB);
- params.strategy = ZSTD_greedy;
- ZSTD_compressBegin_advanced(esr.ref, dictBuffer, dictBufferSize, params);
-
- /* collect stats on all files */
- for (u=0; u<nbFiles; u++) {
- ZDICT_countEStats(esr,
- countLit, offcodeCount, matchLengthCount, litlengthCount,
- (const char*)srcBuffer + pos, fileSizes[u]);
- pos += fileSizes[u];
- }
-
- /* analyze */
- errorCode = HUF_buildCTable (hufTable, countLit, 255, huffLog);
- if (HUF_isError(errorCode)) {
- eSize = ERROR(GENERIC);
- DISPLAYLEVEL(1, "HUF_buildCTable error");
- goto _cleanup;
- }
- huffLog = (U32)errorCode;
-
- total=0; for (u=0; u<=OFFCODE_MAX; u++) total+=offcodeCount[u];
- errorCode = FSE_normalizeCount(offcodeNCount, Offlog, offcodeCount, total, OFFCODE_MAX);
- if (FSE_isError(errorCode)) {
- eSize = ERROR(GENERIC);
- DISPLAYLEVEL(1, "FSE_normalizeCount error with offcodeCount");
- goto _cleanup;
- }
- Offlog = (U32)errorCode;
-
- total=0; for (u=0; u<=MaxML; u++) total+=matchLengthCount[u];
- errorCode = FSE_normalizeCount(matchLengthNCount, mlLog, matchLengthCount, total, MaxML);
- if (FSE_isError(errorCode)) {
- eSize = ERROR(GENERIC);
- DISPLAYLEVEL(1, "FSE_normalizeCount error with matchLengthCount");
- goto _cleanup;
- }
- mlLog = (U32)errorCode;
-
- total=0; for (u=0; u<=MaxLL; u++) total+=litlengthCount[u];
- errorCode = FSE_normalizeCount(litlengthNCount, llLog, litlengthCount, total, MaxLL);
- if (FSE_isError(errorCode)) {
- eSize = ERROR(GENERIC);
- DISPLAYLEVEL(1, "FSE_normalizeCount error with litlengthCount");
- goto _cleanup;
- }
- llLog = (U32)errorCode;
-
- /* write result to buffer */
- errorCode = HUF_writeCTable(dstBuffer, maxDstSize, hufTable, 255, huffLog);
- if (HUF_isError(errorCode)) {
- eSize = ERROR(GENERIC);
- DISPLAYLEVEL(1, "HUF_writeCTable error");
- goto _cleanup;
- }
- dstBuffer = (char*)dstBuffer + errorCode;
- maxDstSize -= errorCode;
- eSize += errorCode;
-
- errorCode = FSE_writeNCount(dstBuffer, maxDstSize, offcodeNCount, OFFCODE_MAX, Offlog);
- if (FSE_isError(errorCode)) {
- eSize = ERROR(GENERIC);
- DISPLAYLEVEL(1, "FSE_writeNCount error with offcodeNCount");
- goto _cleanup;
- }
- dstBuffer = (char*)dstBuffer + errorCode;
- maxDstSize -= errorCode;
- eSize += errorCode;
-
- errorCode = FSE_writeNCount(dstBuffer, maxDstSize, matchLengthNCount, MaxML, mlLog);
- if (FSE_isError(errorCode)) {
- eSize = ERROR(GENERIC);
- DISPLAYLEVEL(1, "FSE_writeNCount error with matchLengthNCount");
- goto _cleanup;
- }
- dstBuffer = (char*)dstBuffer + errorCode;
- maxDstSize -= errorCode;
- eSize += errorCode;
-
- errorCode = FSE_writeNCount(dstBuffer, maxDstSize, litlengthNCount, MaxLL, llLog);
- if (FSE_isError(errorCode)) {
- eSize = ERROR(GENERIC);
- DISPLAYLEVEL(1, "FSE_writeNCount error with litlengthNCount");
- goto _cleanup;
- }
- dstBuffer = (char*)dstBuffer + errorCode;
- maxDstSize -= errorCode;
- eSize += errorCode;
-
-_cleanup:
- ZSTD_freeCCtx(esr.ref);
- ZSTD_freeCCtx(esr.zc);
- free(esr.workPlace);
-
- return eSize;
-}
-
-
-#define DIB_FASTSEGMENTSIZE 64
-/*! ZDICT_fastSampling() (based on an idea proposed by Giuseppe Ottaviano) :
- Fill `dictBuffer` with stripes of size DIB_FASTSEGMENTSIZE from `samplesBuffer`,
- up to `dictSize`.
- Filling starts from the end of `dictBuffer`, down to maximum possible.
- if `dictSize` is not a multiply of DIB_FASTSEGMENTSIZE, some bytes at beginning of `dictBuffer` won't be used.
- @return : amount of data written into `dictBuffer`,
- or an error code
-*/
-static size_t ZDICT_fastSampling(void* dictBuffer, size_t dictSize,
- const void* samplesBuffer, size_t samplesSize)
-{
- char* dstPtr = (char*)dictBuffer + dictSize;
- const char* srcPtr = (const char*)samplesBuffer;
- size_t nbSegments = dictSize / DIB_FASTSEGMENTSIZE;
- size_t segNb, interSize;
-
- if (nbSegments <= 2) return ERROR(srcSize_wrong);
- if (samplesSize < dictSize) return ERROR(srcSize_wrong);
-
- /* first and last segments are part of dictionary, in case they contain interesting header/footer */
- dstPtr -= DIB_FASTSEGMENTSIZE;
- memcpy(dstPtr, srcPtr, DIB_FASTSEGMENTSIZE);
- dstPtr -= DIB_FASTSEGMENTSIZE;
- memcpy(dstPtr, srcPtr+samplesSize-DIB_FASTSEGMENTSIZE, DIB_FASTSEGMENTSIZE);
-
- /* regularly copy a segment */
- interSize = (samplesSize - nbSegments*DIB_FASTSEGMENTSIZE) / (nbSegments-1);
- srcPtr += DIB_FASTSEGMENTSIZE;
- for (segNb=2; segNb < nbSegments; segNb++) {
- srcPtr += interSize;
- dstPtr -= DIB_FASTSEGMENTSIZE;
- memcpy(dstPtr, srcPtr, DIB_FASTSEGMENTSIZE);
- srcPtr += DIB_FASTSEGMENTSIZE;
- }
-
- return nbSegments * DIB_FASTSEGMENTSIZE;
-}
-
-
-size_t ZDICT_trainFromBuffer_unsafe(
- void* dictBuffer, size_t maxDictSize,
- const void* samplesBuffer, const size_t* sampleSizes, unsigned nbSamples,
- ZDICT_params_t params)
-{
- const U32 dictListSize = MAX( MAX(DICTLISTSIZE, nbSamples), (U32)(maxDictSize/16));
- dictItem* dictList = (dictItem*)malloc(dictListSize * sizeof(*dictList));
- unsigned selectivity = params.selectivityLevel;
- unsigned compressionLevel = params.compressionLevel;
- size_t targetDictSize = maxDictSize - g_provision_entropySize;
- size_t sBuffSize;
- size_t dictSize = 0;
-
- /* checks */
- if (maxDictSize <= g_provision_entropySize + g_min_fast_dictContent) return ERROR(dstSize_tooSmall);
-
- /* init */
- { unsigned u; for (u=0, sBuffSize=0; u<nbSamples; u++) sBuffSize += sampleSizes[u]; }
- if (!dictList) return ERROR(memory_allocation);
- ZDICT_initDictItem(dictList);
- g_displayLevel = params.notificationLevel;
- if (selectivity==0) selectivity = g_selectivity_default;
- if (compressionLevel==0) compressionLevel = g_compressionLevel_default;
-
- /* build dictionary */
- if (selectivity>1) { /* selectivity == 1 => fast mode */
- ZDICT_trainBuffer(dictList, dictListSize,
- samplesBuffer, sBuffSize,
- sampleSizes, nbSamples,
- selectivity, (U32)targetDictSize);
-
- /* display best matches */
- if (g_displayLevel>= 3) {
- const U32 nb = 25;
- U32 u;
- U32 dictContentSize = ZDICT_dictSize(dictList);
- DISPLAYLEVEL(3, "\n %u segments found, of total size %u \n", dictList[0].pos, dictContentSize);
- DISPLAYLEVEL(3, "list %u best segments \n", nb);
- for (u=1; u<=nb; u++) {
- U32 p = dictList[u].pos;
- U32 l = dictList[u].length;
- U32 d = MIN(40, l);
- DISPLAYLEVEL(3, "%3u:%3u bytes at pos %8u, savings %7u bytes |",
- u, l, p, dictList[u].savings);
- ZDICT_printHex(3, (const char*)samplesBuffer+p, d);
- DISPLAYLEVEL(3, "| \n");
- } } }
-
- /* create dictionary */
- {
- U32 dictContentSize = ZDICT_dictSize(dictList);
- size_t hSize;
- BYTE* ptr;
- U32 u;
-
- /* build dict content */
- ptr = (BYTE*)dictBuffer + maxDictSize;
- for (u=1; u<dictList->pos; u++) {
- U32 l = dictList[u].length;
- ptr -= l;
- if (ptr<(BYTE*)dictBuffer) return ERROR(GENERIC); /* should not happen */
- memcpy(ptr, (const char*)samplesBuffer+dictList[u].pos, l);
- }
-
- /* fast mode dict content */
- if (selectivity==1) { /* note could also be used to complete a dictionary, but not necessarily better */
- DISPLAYLEVEL(3, "\r%70s\r", ""); /* clean display line */
- DISPLAYLEVEL(3, "Adding %u KB with fast sampling \n", (U32)(targetDictSize>>10));
- dictContentSize = (U32)ZDICT_fastSampling((char*)dictBuffer + g_provision_entropySize,
- targetDictSize, samplesBuffer, sBuffSize);
- }
-
- /* dictionary header */
- MEM_writeLE32(dictBuffer, ZSTD_DICT_MAGIC);
- hSize = 4;
-
- /* entropic tables */
- DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */
- DISPLAYLEVEL(2, "statistics ... \n");
- hSize += ZDICT_analyzeEntropy((char*)dictBuffer+4, maxDictSize-4,
- compressionLevel,
- samplesBuffer, sampleSizes, nbSamples,
- (char*)dictBuffer + maxDictSize - dictContentSize, dictContentSize);
-
- if (hSize + dictContentSize < maxDictSize)
- memmove((char*)dictBuffer + hSize, (char*)dictBuffer + maxDictSize - dictContentSize, dictContentSize);
- dictSize = MIN(maxDictSize, hSize+dictContentSize);
- }
-
- /* clean up */
- free(dictList);
- return dictSize;
-}
-
-
-size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dictBufferCapacity,
- const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
- ZDICT_params_t params)
-{
- size_t sBuffSize;
- void* newBuff;
- size_t result;
-
- { unsigned u; for (u=0, sBuffSize=0; u<nbSamples; u++) sBuffSize += samplesSizes[u]; }
- newBuff = malloc(sBuffSize + NOISELENGTH);
- if (!newBuff) return ERROR(memory_allocation);
-
- memcpy(newBuff, samplesBuffer, sBuffSize);
- ZDICT_fillNoise((char*)newBuff + sBuffSize, NOISELENGTH); /* guard band, for end of buffer condition */
-
- result = ZDICT_trainFromBuffer_unsafe(dictBuffer, dictBufferCapacity,
- newBuff, samplesSizes, nbSamples,
- params);
- free(newBuff);
- return result;
-}
-
-
-/* issue : samplesBuffer need to be followed by a noisy guard band.
-* work around : duplicate the buffer, and add the noise ? */
-size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,
- const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples)
-{
- ZDICT_params_t params;
- memset(¶ms, 0, sizeof(params));
- return ZDICT_trainFromBuffer_advanced(dictBuffer, dictBufferCapacity,
- samplesBuffer, samplesSizes, nbSamples,
- params);
-}
-
diff --git a/lib/zdict.h b/lib/zdict.h
deleted file mode 100644
index 2ca190c..0000000
--- a/lib/zdict.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- dictBuilder header file
- Copyright (C) Yann Collet 2016
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
- distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- You can contact the author at :
- - Zstd source repository : https://www.zstd.net
-*/
-
-#ifndef DICTBUILDER_H_001
-#define DICTBUILDER_H_001
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-/*-*************************************
-* Public functions
-***************************************/
-/*! ZDICT_trainFromBuffer() :
- Train a dictionary from a memory buffer `samplesBuffer`,
- where `nbSamples` samples have been stored concatenated.
- Each sample size is provided into an orderly table `samplesSizes`.
- Resulting dictionary will be saved into `dictBuffer`.
- @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
- or an error code, which can be tested by ZDICT_isError().
-*/
-size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,
- const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples);
-
-
-/*-*************************************
-* Helper functions
-***************************************/
-unsigned ZDICT_isError(size_t errorCode);
-const char* ZDICT_getErrorName(size_t errorCode);
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif
diff --git a/lib/zdict_static.h b/lib/zdict_static.h
deleted file mode 100644
index e5f909a..0000000
--- a/lib/zdict_static.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- dictBuilder header file
- for static linking only
- Copyright (C) Yann Collet 2016
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
- distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- You can contact the author at :
- - Zstd source repository : https://www.zstd.net
-*/
-
-/* This library is EXPERIMENTAL, below API is not yet stable */
-
-#ifndef DICTBUILDER_STATIC_H_002
-#define DICTBUILDER_STATIC_H_002
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-/*-*************************************
-* Dependencies
-***************************************/
-#include "zdict.h"
-
-
-/*-*************************************
-* Public type
-***************************************/
-typedef struct {
- unsigned selectivityLevel; /* 0 means default; larger => bigger selection => larger dictionary */
- unsigned compressionLevel; /* 0 means default; target a specific zstd compression level */
- unsigned notificationLevel; /* Write to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */
- unsigned reserved[3]; /* space for future parameters */
-} ZDICT_params_t;
-
-
-/*-*************************************
-* Public functions
-***************************************/
-/*! ZDICT_trainFromBuffer_advanced() :
- Same as ZDICT_trainFromBuffer() with control over more parameters.
- `parameters` is optional and can be provided with values set to 0 to mean "default".
- @return : size of dictionary stored into `dictBuffer` (<= `dictBufferSize`)
- or an error code, which can be tested by DiB_isError().
- note : ZDICT_trainFromBuffer_advanced() will send notifications into stderr if instructed to, using ZDICT_setNotificationLevel()
-*/
-size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dictBufferCapacity,
- const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
- ZDICT_params_t parameters);
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* DICTBUILDER_STATIC_H_002 */
diff --git a/lib/zstd_opt.h b/lib/zstd_opt.h
deleted file mode 100644
index ec9a2a1..0000000
--- a/lib/zstd_opt.h
+++ /dev/null
@@ -1,1125 +0,0 @@
-/*
- ZSTD Optimal mode
- Copyright (C) 2016, Przemyslaw Skibinski, Yann Collet.
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
- distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- You can contact the author at :
- - Zstd source repository : https://www.zstd.net
-*/
-
-/* Note : this file is intended to be included within zstd_compress.c */
-
-/*- Dependencies -*/
-#include <stdio.h> /* for debug */
-
-
-/*- Local types -*/
-typedef struct {
- U32 off;
- U32 len;
- U32 back;
-} ZSTD_match_t;
-
-typedef struct {
- U32 price;
- U32 off;
- U32 mlen;
- U32 litlen;
- U32 rep;
- U32 rep2;
-} ZSTD_optimal_t;
-
-
-/*- Constants -*/
-#define ZSTD_OPT_NUM (1<<12)
-#define ZSTD_FREQ_THRESHOLD (256)
-
-/*- Debug -*/
-#define ZSTD_OPT_DEBUG 0 // 1 = tableID=0; 5 = check encoded sequences
-
-#if defined(ZSTD_OPT_DEBUG) && ZSTD_OPT_DEBUG>=1
- #define ZSTD_LOG_PARSER(...) printf(__VA_ARGS__)
- #define ZSTD_LOG_ENCODE(...) printf(__VA_ARGS__)
- #define ZSTD_LOG_TRY_PRICE(...) printf(__VA_ARGS__)
-#else
- #define ZSTD_LOG_PARSER(...)
- #define ZSTD_LOG_ENCODE(...)
- #define ZSTD_LOG_TRY_PRICE(...)
-#endif
-
-
-FORCE_INLINE U32 ZSTD_getLiteralPriceReal(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals)
-{
- U32 price, freq, u;
-
- if (!litLength) return 1; /* special case */
-
- /* literals */
- price = litLength * ZSTD_highbit(seqStorePtr->litSum);
- for (u=0; u < litLength; u++)
- price -= ZSTD_highbit(seqStorePtr->litFreq[literals[u]]);
-
- /* literal Length */
- price += ((litLength >= MaxLL)*8) + ((litLength >= 255+MaxLL)*16) + ((litLength>=(1<<15))*8);
- if (litLength >= MaxLL) litLength = MaxLL;
- freq = seqStorePtr->litLengthFreq[litLength];
- price += ZSTD_highbit(seqStorePtr->litLengthSum) - ZSTD_highbit(freq);
-
- return price;
-}
-
-
-FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals)
-{
- if (seqStorePtr->litSum > ZSTD_FREQ_THRESHOLD)
- return ZSTD_getLiteralPriceReal(seqStorePtr, litLength, literals);
- /* backup eval */
- return 1 + (litLength<<3);
-}
-
-
-FORCE_INLINE U32 ZSTD_getMatchPriceReal(seqStore_t* seqStorePtr, U32 offset, U32 matchLength)
-{
- /* offset */
- BYTE offCode = offset ? (BYTE)ZSTD_highbit(offset) + 1 : 0;
- U32 price = ZSTD_highbit(seqStorePtr->offCodeSum) - ZSTD_highbit(seqStorePtr->offCodeFreq[offCode]);
- price += offCode;
-
- /* match Length */
- price += ((matchLength >= MaxML)*8) + ((matchLength >= 255+MaxML)*16) + ((matchLength>=(1<<15))*8);
- if (matchLength >= MaxML) matchLength = MaxML;
- price += ZSTD_highbit(seqStorePtr->matchLengthSum) - ZSTD_highbit(seqStorePtr->matchLengthFreq[matchLength]);
-
- return price;
-}
-
-
-FORCE_INLINE U32 ZSTD_getPrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
-{
- if (seqStorePtr->litSum > ZSTD_FREQ_THRESHOLD)
- return ZSTD_getLiteralPriceReal(seqStorePtr, litLength, literals) + ZSTD_getMatchPriceReal(seqStorePtr, offset, matchLength);
- /* backup eval */
- return (litLength<<3) + ZSTD_highbit((U32)matchLength+1) + Offbits + ZSTD_highbit((U32)offset+1);
-}
-
-
-MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
-{
- U32 u;
-
- /* literals */
- seqStorePtr->litSum += litLength;
- for (u=0; u < litLength; u++)
- seqStorePtr->litFreq[literals[u]]++;
-
- /* literal Length */
- seqStorePtr->litLengthSum++;
- if (litLength >= MaxLL)
- seqStorePtr->litLengthFreq[MaxLL]++;
- else
- seqStorePtr->litLengthFreq[litLength]++;
-
- /* match offset */
- seqStorePtr->offCodeSum++;
- BYTE offCode = (BYTE)ZSTD_highbit(offset) + 1;
- if (offset==0) offCode=0;
- seqStorePtr->offCodeFreq[offCode]++;
-
- /* match Length */
- seqStorePtr->matchLengthSum++;
- if (matchLength >= MaxML)
- seqStorePtr->matchLengthFreq[MaxML]++;
- else
- seqStorePtr->matchLengthFreq[matchLength]++;
-}
-
-
-#define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \
- { \
- while (last_pos < pos) { opt[last_pos+1].price = 1<<30; last_pos++; } \
- opt[pos].mlen = mlen_; \
- opt[pos].off = offset_; \
- opt[pos].litlen = litlen_; \
- opt[pos].price = price_; \
- ZSTD_LOG_PARSER("%d: SET price[%d/%d]=%d litlen=%d len=%d off=%d\n", (int)(inr-base), (int)pos, (int)last_pos, opt[pos].price, opt[pos].litlen, opt[pos].mlen, opt[pos].off); \
- }
-
-
-
-/*-*************************************
-* Binary Tree search
-***************************************/
-static U32 ZSTD_insertBtAndGetAllMatches (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iend,
- U32 nbCompares, const U32 mls,
- U32 extDict, ZSTD_match_t* matches, size_t bestLength)
-{
- const BYTE* const base = zc->base;
- const U32 current = (U32)(ip-base);
- const U32 hashLog = zc->params.hashLog;
- const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
- U32* const hashTable = zc->hashTable;
- U32 matchIndex = hashTable[h];
- U32* const bt = zc->contentTable;
- const U32 btLog = zc->params.contentLog - 1;
- const U32 btMask= (1U << btLog) - 1;
- size_t commonLengthSmaller=0, commonLengthLarger=0;
- const BYTE* const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const U32 btLow = btMask >= current ? 0 : current - btMask;
- const U32 windowLow = zc->lowLimit;
- U32* smallerPtr = bt + 2*(current&btMask);
- U32* largerPtr = bt + 2*(current&btMask) + 1;
- U32 matchEndIdx = current+8;
- U32 dummy32; /* to be nullified at the end */
- U32 mnum = 0;
-
- bestLength = MINMATCH-1;
- hashTable[h] = current; /* Update Hash Table */
-
- while (nbCompares-- && (matchIndex > windowLow)) {
- U32* nextPtr = bt + 2*(matchIndex & btMask);
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
- const BYTE* match;
-
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
- match = base + matchIndex;
- if (match[matchLength] == ip[matchLength])
- matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
- } else {
- match = dictBase + matchIndex;
- matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
- if (matchIndex+matchLength >= dictLimit)
- match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
- }
-
- if (matchLength > bestLength) {
- if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength;
- bestLength = matchLength;
- matches[mnum].off = current - matchIndex;
- matches[mnum].len = (U32)matchLength;
- matches[mnum].back = 0;
- mnum++;
- if (matchLength > ZSTD_OPT_NUM) break;
- if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
- break; /* drop, to guarantee consistency (miss a little bit of compression) */
- }
-
- if (match[matchLength] < ip[matchLength]) {
- /* match is smaller than current */
- *smallerPtr = matchIndex; /* update smaller idx */
- commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
- } else {
- /* match is larger than current */
- *largerPtr = matchIndex;
- commonLengthLarger = matchLength;
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- largerPtr = nextPtr;
- matchIndex = nextPtr[0];
- } }
-
- *smallerPtr = *largerPtr = 0;
-
- zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
- return mnum;
-}
-
-
-/** Tree updater, providing best match */
-static U32 ZSTD_BtGetAllMatches (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iLimit,
- const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, U32 minml)
-{
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minml);
-}
-
-
-static U32 ZSTD_BtGetAllMatches_selectMLS (
- ZSTD_CCtx* zc, /* Index table will be updated */
- const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
- const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml)
-{
- (void)iLowLimit; /* unused */
- switch(matchLengthSearch)
- {
- default :
- case 4 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minml);
- case 5 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minml);
- case 6 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minml);
- }
-}
-
-/** Tree updater, providing best match */
-static U32 ZSTD_BtGetAllMatches_extDict (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iLimit,
- const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, U32 minml)
-{
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minml);
-}
-
-
-static U32 ZSTD_BtGetAllMatches_selectMLS_extDict (
- ZSTD_CCtx* zc, /* Index table will be updated */
- const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
- const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml)
-{
- (void)iLowLimit;
- switch(matchLengthSearch)
- {
- default :
- case 4 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minml);
- case 5 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minml);
- case 6 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minml);
- }
-}
-
-
-/* ***********************
-* Hash Chain
-*************************/
-FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
-U32 ZSTD_HcGetAllMatches_generic (
- ZSTD_CCtx* zc, /* Index table will be updated */
- const BYTE* const ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
- const U32 maxNbAttempts, const U32 mls, const U32 extDict, ZSTD_match_t* matches, size_t minml)
-{
- U32* const chainTable = zc->contentTable;
- const U32 chainSize = (1U << zc->params.contentLog);
- const U32 chainMask = chainSize-1;
- const BYTE* const base = zc->base;
- const BYTE* const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const dictStart = dictBase + zc->lowLimit;
- const U32 lowLimit = zc->lowLimit;
- const U32 current = (U32)(ip-base);
- const U32 minChain = current > chainSize ? current - chainSize : 0;
- U32 matchIndex;
- U32 mnum = 0;
- const BYTE* match;
- U32 nbAttempts=maxNbAttempts;
- minml=MINMATCH-1;
-
- /* HC4 match finder */
- matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
-
- while ((matchIndex>lowLimit) && (nbAttempts)) {
- size_t currentMl=0;
- int back = 0;
- nbAttempts--;
- if ((!extDict) || matchIndex >= dictLimit) {
- match = base + matchIndex;
- if (match[minml] == ip[minml]) currentMl = ZSTD_count(ip, match, iHighLimit); if (currentMl>0) { // faster
- //if (MEM_read32(match) == MEM_read32(ip)) { currentMl = ZSTD_count(ip+MINMATCH, match+MINMATCH, iHighLimit)+MINMATCH; // stronger
- while ((match-back > prefixStart) && (ip-back > iLowLimit) && (ip[-back-1] == match[-back-1])) back++;
- currentMl += back;
- }
- } else {
- match = dictBase + matchIndex;
- if (MEM_read32(match) == MEM_read32(ip)) { /* assumption : matchIndex <= dictLimit-4 (by table construction) */
- currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, prefixStart) + MINMATCH;
- while ((match-back > dictStart) && (ip-back > iLowLimit) && (ip[-back-1] == match[-back-1])) back++; /* backward match extension */
- currentMl += back;
- } }
-
- /* save best solution */
- if (currentMl > minml) {
- minml = currentMl;
- matches[mnum].off = current - matchIndex;
- matches[mnum].len = (U32)currentMl;
- matches[mnum].back = back;
- mnum++;
- if (currentMl > ZSTD_OPT_NUM) break;
- if (ip+currentMl == iHighLimit) break; /* best possible, and avoid read overflow*/
- }
-
- if (matchIndex <= minChain) break;
- matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
- }
-
- return mnum;
-}
-
-
-static U32 ZSTD_HcGetAllMatches_selectMLS (
- ZSTD_CCtx* zc,
- const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
- const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml)
-{
- switch(matchLengthSearch)
- {
- default :
- case 4 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 4, 0, matches, minml);
- case 5 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 5, 0, matches, minml);
- case 6 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 6, 0, matches, minml);
- }
-}
-
-static U32 ZSTD_HcGetAllMatches_selectMLS_extDict (
- ZSTD_CCtx* zc,
- const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
- const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml)
-{
- switch(matchLengthSearch)
- {
- default :
- case 4 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 4, 1, matches, minml);
- case 5 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 5, 1, matches, minml);
- case 6 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 6, 1, matches, minml);
- }
-}
-
-
-/*-*******************************
-* Optimal parser
-*********************************/
-FORCE_INLINE
-void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 searchMethod, const U32 depth)
-{
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ctx->base + ctx->dictLimit;
-
- U32 rep_2=REPCODE_STARTVALUE, rep_1=REPCODE_STARTVALUE;
- const U32 maxSearches = 1U << ctx->params.searchLog;
- const U32 mls = ctx->params.searchLength;
-
- typedef U32 (*getAllMatches_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLowLimit, const BYTE* iHighLimit,
- U32 maxNbAttempts, U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml);
- getAllMatches_f getAllMatches = searchMethod ? ZSTD_BtGetAllMatches_selectMLS : ZSTD_HcGetAllMatches_selectMLS;
-
- ZSTD_optimal_t opt[ZSTD_OPT_NUM+4];
- ZSTD_match_t matches[ZSTD_OPT_NUM+1];
- const BYTE* inr;
- U32 skip_num, cur, cur2, match_num, last_pos, litlen, price;
-
- const U32 sufficient_len = ctx->params.targetLength;
- const U32 faster_get_matches = (ctx->params.strategy == ZSTD_opt);
-
-
- /* init */
- ZSTD_resetSeqStore(seqStorePtr);
- ZSTD_resetFreqs(seqStorePtr);
- if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE;
-
- /* Match Loop */
- while (ip < ilimit) {
- U32 u;
- U32 mlen=0;
- U32 best_mlen=0;
- U32 best_off=0;
- memset(opt, 0, sizeof(ZSTD_optimal_t));
- last_pos = 0;
- inr = ip;
- opt[0].litlen = (U32)(ip - anchor);
-
- /* check repCode */
- if (MEM_read32(ip+1) == MEM_read32(ip+1 - rep_1)) {
- /* repcode : we take it */
- mlen = (U32)ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-rep_1, iend) + MINMATCH;
-
- ZSTD_LOG_PARSER("%d: start try REP rep=%d mlen=%d\n", (int)(ip-base), (int)rep_1, (int)mlen);
- if (depth==0 || mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
- ip+=1; best_mlen = mlen; best_off = 0; cur = 0; last_pos = 1;
- goto _storeSequence;
- }
-
- litlen = opt[0].litlen + 1;
- do {
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, 0, mlen - MINMATCH);
- if (mlen + 1 > last_pos || price < opt[mlen + 1].price)
- SET_PRICE(mlen + 1, mlen, 0, litlen, price); /* note : macro modifies last_pos */
- mlen--;
- } while (mlen >= MINMATCH);
- }
-
- best_mlen = (last_pos) ? last_pos : MINMATCH;
-
- if (faster_get_matches && last_pos)
- match_num = 0;
- else
- match_num = getAllMatches(ctx, ip, ip, iend, maxSearches, mls, matches, best_mlen); /* first search (depth 0) */
-
- ZSTD_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-base), match_num, last_pos);
- if (!last_pos && !match_num) { ip++; continue; }
-
- opt[0].rep = rep_1;
- opt[0].rep2 = rep_2;
- opt[0].mlen = 1;
-
- if (match_num && matches[match_num-1].len > sufficient_len) {
- best_mlen = matches[match_num-1].len;
- best_off = matches[match_num-1].off;
- cur = 0;
- last_pos = 1;
- goto _storeSequence;
- }
-
- // set prices using matches at position = 0
- for (u = 0; u < match_num; u++) {
- mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
- best_mlen = (matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM;
- ZSTD_LOG_PARSER("%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(ip-base), matches[u].len, matches[u].off, (int)best_mlen, (int)last_pos);
- litlen = opt[0].litlen;
- while (mlen <= best_mlen) {
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off, mlen - MINMATCH);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
- mlen++;
- } }
-
- if (last_pos < MINMATCH) { ip++; continue; }
-
- /* check further positions */
- for (skip_num = 0, cur = 1; cur <= last_pos; cur++) {
- size_t cur_rep;
- inr = ip + cur;
-
- if (opt[cur-1].mlen == 1) {
- litlen = opt[cur-1].litlen + 1;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-litlen);
- ZSTD_LOG_TRY_PRICE("%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-base), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
- } else
- price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
- } else {
- litlen = 1;
- price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1);
- ZSTD_LOG_TRY_PRICE("%d: TRY3 price=%d cur=%d litlen=%d litonly=%d\n", (int)(inr-base), price, cur, litlen, (int)ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1));
- }
-
- ZSTD_LOG_TRY_PRICE("%d: TRY4 price=%d opt[%d].price=%d\n", (int)(inr-base), price, cur, opt[cur].price);
-
- if (cur > last_pos || price <= opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen)))
- SET_PRICE(cur, 1, 0, litlen, price);
-
- if (cur == last_pos) break;
-
- if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
- continue;
-
- mlen = opt[cur].mlen;
-
- if (opt[cur-mlen].off) {
- opt[cur].rep2 = opt[cur-mlen].rep;
- opt[cur].rep = opt[cur-mlen].off;
- ZSTD_LOG_PARSER("%d: COPYREP1 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
- } else {
- if (cur!=mlen && opt[cur-mlen].litlen == 0) {
- opt[cur].rep2 = opt[cur-mlen].rep;
- opt[cur].rep = opt[cur-mlen].rep2;
- ZSTD_LOG_PARSER("%d: COPYREP2 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
- } else {
- opt[cur].rep2 = opt[cur-mlen].rep2;
- opt[cur].rep = opt[cur-mlen].rep;
- ZSTD_LOG_PARSER("%d: COPYREP3 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
- } }
-
- ZSTD_LOG_PARSER("%d: CURRENT price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2);
-
- best_mlen = 0;
-
- if (!opt[cur].off && opt[cur].mlen != 1) {
- cur_rep = opt[cur].rep2;
- ZSTD_LOG_PARSER("%d: try REP2 rep2=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
- } else {
- cur_rep = opt[cur].rep;
- ZSTD_LOG_PARSER("%d: try REP1 rep=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
- }
-
- if (MEM_read32(inr) == MEM_read32(inr - cur_rep)) { // check rep
- mlen = (U32)ZSTD_count(inr+MINMATCH, inr+MINMATCH - cur_rep, iend) + MINMATCH;
- ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-base), mlen, 0, opt[cur].rep, cur, opt[cur].off);
-
- if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen;
- best_off = 0;
- ZSTD_LOG_PARSER("%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\n", (int)(inr-base), sufficient_len, best_mlen, best_off, last_pos);
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr-litlen, 0, mlen - MINMATCH);
- ZSTD_LOG_TRY_PRICE("%d: TRY5 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-base), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
- } else
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, 0, mlen - MINMATCH);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, 0, mlen - MINMATCH);
- ZSTD_LOG_TRY_PRICE("%d: TRY7 price=%d cur=%d litlen=0 getprice=%d\n", (int)(inr-base), price, cur, (int)ZSTD_getPrice(seqStorePtr, 0, NULL, 0, mlen - MINMATCH));
- }
-
- best_mlen = mlen;
- if (faster_get_matches) skip_num = best_mlen;
- ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-base), mlen, 0, price, litlen, cur - litlen, opt[cur - litlen].price);
-
- do {
- if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
- SET_PRICE(cur + mlen, mlen, 0, litlen, price);
- mlen--;
- } while (mlen >= MINMATCH);
- }
-
- if (faster_get_matches && skip_num > 0) { skip_num--; continue; }
-
- best_mlen = (best_mlen > MINMATCH) ? best_mlen : MINMATCH;
-
- match_num = getAllMatches(ctx, inr, ip, iend, maxSearches, mls, matches, best_mlen);
- ZSTD_LOG_PARSER("%d: ZSTD_GetAllMatches match_num=%d\n", (int)(inr-base), match_num);
-
- if (match_num > 0 && matches[match_num-1].len > sufficient_len) {
- cur -= matches[match_num-1].back;
- best_mlen = matches[match_num-1].len;
- best_off = matches[match_num-1].off;
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- /* set prices using matches at position = cur */
- for (u = 0; u < match_num; u++) {
- mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
- cur2 = cur - matches[u].back;
- best_mlen = (cur2 + matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM - cur2;
-
- ZSTD_LOG_PARSER("%d: Found1 cur=%d cur2=%d mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(inr-base), cur, cur2, matches[u].len, matches[u].off, best_mlen, last_pos);
- if (mlen < matches[u].back + 1)
- mlen = matches[u].back + 1;
-
- while (mlen <= best_mlen) {
- if (opt[cur2].mlen == 1) {
- litlen = opt[cur2].litlen;
- if (cur2 > litlen)
- price = opt[cur2 - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip+cur2-litlen, matches[u].off, mlen - MINMATCH);
- else
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off, mlen - MINMATCH);
- } else {
- litlen = 0;
- price = opt[cur2].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off, mlen - MINMATCH);
- }
-
- ZSTD_LOG_PARSER("%d: Found2 pred=%d mlen=%d best_mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-base), matches[u].back, mlen, best_mlen, matches[u].off, price, litlen, cur - litlen, opt[cur - litlen].price);
- ZSTD_LOG_TRY_PRICE("%d: TRY8 price=%d opt[%d].price=%d\n", (int)(inr-base), price, cur2 + mlen, opt[cur2 + mlen].price);
-
- if (cur2 + mlen > last_pos || (price < opt[cur2 + mlen].price))
- SET_PRICE(cur2 + mlen, mlen, matches[u].off, litlen, price);
-
- mlen++;
- } } } // for (skip_num = 0, cur = 1; cur <= last_pos; cur++)
-
- best_mlen = opt[last_pos].mlen;
- best_off = opt[last_pos].off;
- cur = last_pos - best_mlen;
- // printf("%d: start=%d best_mlen=%d best_off=%d cur=%d\n", (int)(ip - base), (int)(start - ip), (int)best_mlen, (int)best_off, cur);
-
- /* store sequence */
-_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
- for (u = 1; u <= last_pos; u++)
- ZSTD_LOG_PARSER("%d: price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(ip-base+u), u, last_pos, opt[u].price, opt[u].off, opt[u].mlen, opt[u].litlen, opt[u].rep, opt[u].rep2);
- ZSTD_LOG_PARSER("%d: cur=%d/%d best_mlen=%d best_off=%d rep=%d\n", (int)(ip-base+cur), (int)cur, (int)last_pos, (int)best_mlen, (int)best_off, opt[cur].rep);
-
- opt[0].mlen = 1;
- U32 offset;
-
- while (1) {
- mlen = opt[cur].mlen;
- ZSTD_LOG_PARSER("%d: cur=%d mlen=%d\n", (int)(ip-base), cur, mlen);
- offset = opt[cur].off;
- opt[cur].mlen = best_mlen;
- opt[cur].off = best_off;
- best_mlen = mlen;
- best_off = offset;
- if (mlen > cur) break;
- cur -= mlen;
- }
-
- for (u = 0; u <= last_pos;) {
- ZSTD_LOG_PARSER("%d: price2[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(ip-base+u), u, last_pos, opt[u].price, opt[u].off, opt[u].mlen, opt[u].litlen, opt[u].rep, opt[u].rep2);
- u += opt[u].mlen;
- }
-
- for (cur=0; cur < last_pos; ) {
- ZSTD_LOG_PARSER("%d: price3[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(ip-base+cur), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2);
- mlen = opt[cur].mlen;
- if (mlen == 1) { ip++; cur++; continue; }
- offset = opt[cur].off;
- cur += mlen;
-
- U32 litLength = (U32)(ip - anchor);
- ZSTD_LOG_ENCODE("%d/%d: ENCODE1 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2);
-
- if (offset) {
- rep_2 = rep_1;
- rep_1 = offset;
- } else {
- if (litLength == 0) {
- best_off = rep_2;
- rep_2 = rep_1;
- rep_1 = best_off;
- } }
-
- ZSTD_LOG_ENCODE("%d/%d: ENCODE2 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2);
-
-#if ZSTD_OPT_DEBUG >= 5
- int ml2;
- if (offset)
- ml2 = ZSTD_count(ip, ip-offset, iend);
- else
- ml2 = ZSTD_count(ip, ip-rep_1, iend);
- if (ml2 < mlen && ml2 < MINMATCH) {
- printf("%d: ERROR iend=%d mlen=%d offset=%d ml2=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset, (int)ml2); exit(0); }
- if (ip < anchor) {
- printf("%d: ERROR ip < anchor iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
- if (ip - offset < ctx->base) {
- printf("%d: ERROR ip - offset < base iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
- if ((int)offset >= (1 << ctx->params.windowLog)) {
- printf("%d: offset >= (1 << params.windowLog) iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
- if (mlen < MINMATCH) {
- printf("%d: ERROR mlen < MINMATCH iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
- if (ip + mlen > iend) {
- printf("%d: ERROR ip + mlen >= iend iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
-#endif
-
- ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
- anchor = ip = ip + mlen;
- } /* for (cur=0; cur < last_pos; ) */
-
- /* check immediate repcode */
- while ( (anchor <= ilimit)
- && (MEM_read32(anchor) == MEM_read32(anchor - rep_2)) ) {
- /* store sequence */
- best_mlen = (U32)ZSTD_count(anchor+MINMATCH, anchor+MINMATCH-rep_2, iend);
- best_off = rep_2;
- rep_2 = rep_1;
- rep_1 = best_off;
- ZSTD_LOG_ENCODE("%d/%d: ENCODE REP literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(anchor-base), (int)(iend-base), (int)(0), (int)best_mlen, (int)(0), (int)rep_1, (int)rep_2);
- ZSTD_updatePrice(seqStorePtr, 0, anchor, 0, best_mlen);
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, best_mlen);
- anchor += best_mlen+MINMATCH;
- continue; /* faster when present ... (?) */
- }
- if (anchor > ip) ip = anchor;
- }
-
- { /* Last Literals */
- size_t lastLLSize = iend - anchor;
- ZSTD_LOG_ENCODE("%d: lastLLSize literals=%u\n", (int)(ip-base), (U32)lastLLSize);
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-
-FORCE_INLINE
-void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 searchMethod, const U32 depth)
-{
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ctx->base;
- const U32 dictLimit = ctx->dictLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const BYTE* const dictBase = ctx->dictBase;
- const BYTE* const dictEnd = dictBase + dictLimit;
-
- U32 rep_2=REPCODE_STARTVALUE, rep_1=REPCODE_STARTVALUE;
- const U32 maxSearches = 1U << ctx->params.searchLog;
- const U32 mls = ctx->params.searchLength;
-
- typedef U32 (*getAllMatches_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLowLimit, const BYTE* iHighLimit,
- U32 maxNbAttempts, U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml);
- getAllMatches_f getAllMatches = searchMethod ? ZSTD_BtGetAllMatches_selectMLS_extDict : ZSTD_HcGetAllMatches_selectMLS_extDict;
-
- ZSTD_optimal_t opt[ZSTD_OPT_NUM+4];
- ZSTD_match_t matches[ZSTD_OPT_NUM+1];
- const BYTE* inr;
- U32 skip_num, cur, cur2, match_num, last_pos, litlen, price;
-
- const U32 sufficient_len = ctx->params.targetLength;
- const U32 faster_get_matches = (ctx->params.strategy == ZSTD_opt);
-
- /* init */
- ZSTD_resetSeqStore(seqStorePtr);
- ZSTD_resetFreqs(seqStorePtr);
- if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
-
- /* Match Loop */
- while (ip < ilimit) {
- U32 u, offset, best_off=0;
- U32 mlen=0, best_mlen=0;
- U32 current = (U32)(ip-base);
- memset(opt, 0, sizeof(ZSTD_optimal_t));
- last_pos = 0;
- inr = ip;
- opt[0].litlen = (U32)(ip - anchor);
-
- /* check repCode */
- {
- const U32 repIndex = (U32)(current+1 - rep_1);
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* const repMatch = repBase + repIndex;
- if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
- && (MEM_read32(ip+1) == MEM_read32(repMatch)) ) {
- /* repcode detected we should take it */
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
- mlen = (U32)ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
-
- ZSTD_LOG_PARSER("%d: start try REP rep=%d mlen=%d\n", (int)(ip-base), (int)rep_1, (int)mlen);
- if (depth==0 || mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
- ip+=1; best_mlen = mlen; best_off = 0; cur = 0; last_pos = 1;
- goto _storeSequence;
- }
-
- litlen = opt[0].litlen + 1;
- do {
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, 0, mlen - MINMATCH);
- if (mlen + 1 > last_pos || price < opt[mlen + 1].price)
- SET_PRICE(mlen + 1, mlen, 0, litlen, price);
- mlen--;
- } while (mlen >= MINMATCH);
- } }
-
- best_mlen = (last_pos) ? last_pos : MINMATCH;
-
- if (faster_get_matches && last_pos)
- match_num = 0;
- else
- match_num = getAllMatches(ctx, ip, ip, iend, maxSearches, mls, matches, best_mlen); /* first search (depth 0) */
-
- ZSTD_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-base), match_num, last_pos);
- if (!last_pos && !match_num) { ip++; continue; }
-
- opt[0].rep = rep_1;
- opt[0].rep2 = rep_2;
- opt[0].mlen = 1;
-
- if (match_num && matches[match_num-1].len > sufficient_len) {
- best_mlen = matches[match_num-1].len;
- best_off = matches[match_num-1].off;
- cur = 0;
- last_pos = 1;
- goto _storeSequence;
- }
-
- // set prices using matches at position = 0
- for (u = 0; u < match_num; u++) {
- mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
- best_mlen = (matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM;
- ZSTD_LOG_PARSER("%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(ip-base), matches[u].len, matches[u].off, (int)best_mlen, (int)last_pos);
- litlen = opt[0].litlen;
- while (mlen <= best_mlen) {
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off, mlen - MINMATCH);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
- mlen++;
- } }
-
- if (last_pos < MINMATCH) {
- // ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
- ip++; continue;
- }
-
- /* check further positions */
- for (skip_num = 0, cur = 1; cur <= last_pos; cur++) {
- size_t cur_rep;
- inr = ip + cur;
-
- if (opt[cur-1].mlen == 1) {
- litlen = opt[cur-1].litlen + 1;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-litlen);
- ZSTD_LOG_TRY_PRICE("%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-base), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
- } else
- price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
- } else {
- litlen = 1;
- price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1);
- ZSTD_LOG_TRY_PRICE("%d: TRY3 price=%d cur=%d litlen=%d litonly=%d\n", (int)(inr-base), price, cur, litlen, (int)ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1));
- }
-
- ZSTD_LOG_TRY_PRICE("%d: TRY4 price=%d opt[%d].price=%d\n", (int)(inr-base), price, cur, opt[cur].price);
-
- if (cur > last_pos || price <= opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen)))
- SET_PRICE(cur, 1, 0, litlen, price);
-
- if (cur == last_pos) break;
-
- if (inr > ilimit) // last match must start at a minimum distance of 8 from oend
- continue;
-
- mlen = opt[cur].mlen;
-
- if (opt[cur-mlen].off) {
- opt[cur].rep2 = opt[cur-mlen].rep;
- opt[cur].rep = opt[cur-mlen].off;
- ZSTD_LOG_PARSER("%d: COPYREP1 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
- } else {
- if (cur!=mlen && opt[cur-mlen].litlen == 0) {
- opt[cur].rep2 = opt[cur-mlen].rep;
- opt[cur].rep = opt[cur-mlen].rep2;
- ZSTD_LOG_PARSER("%d: COPYREP2 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
- } else {
- opt[cur].rep2 = opt[cur-mlen].rep2;
- opt[cur].rep = opt[cur-mlen].rep;
- ZSTD_LOG_PARSER("%d: COPYREP3 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
- } }
-
- ZSTD_LOG_PARSER("%d: CURRENT price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2);
-
- best_mlen = 0;
-
- if (!opt[cur].off && opt[cur].mlen != 1) {
- cur_rep = opt[cur].rep2;
- ZSTD_LOG_PARSER("%d: try REP2 rep2=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
- } else {
- cur_rep = opt[cur].rep;
- ZSTD_LOG_PARSER("%d: try REP1 rep=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
- }
-
- const U32 repIndex = (U32)(current+cur - cur_rep);
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* const repMatch = repBase + repIndex;
- if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
- &&(MEM_read32(inr) == MEM_read32(repMatch)) ) {
- /* repcode detected */
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
- mlen = (U32)ZSTD_count_2segments(inr+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
- ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-base), mlen, 0, opt[cur].rep, cur, opt[cur].off);
-
- if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen;
- best_off = 0;
- ZSTD_LOG_PARSER("%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\n", (int)(inr-base), sufficient_len, best_mlen, best_off, last_pos);
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr-litlen, 0, mlen - MINMATCH);
- ZSTD_LOG_TRY_PRICE("%d: TRY5 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-base), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
- } else
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, 0, mlen - MINMATCH);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, 0, mlen - MINMATCH);
- ZSTD_LOG_TRY_PRICE("%d: TRY7 price=%d cur=%d litlen=0 getprice=%d\n", (int)(inr-base), price, cur, (int)ZSTD_getPrice(seqStorePtr, 0, NULL, 0, mlen - MINMATCH));
- }
-
- best_mlen = mlen;
- if (faster_get_matches) skip_num = best_mlen;
-
- ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-base), mlen, 0, price, litlen, cur - litlen, opt[cur - litlen].price);
-
- do {
- if (cur + mlen > last_pos || price <= opt[cur + mlen].price) // || ((price == opt[cur + mlen].price) && (opt[cur].mlen == 1) && (cur != litlen))) // at equal price prefer REP instead of MATCH
- SET_PRICE(cur + mlen, mlen, 0, litlen, price);
- mlen--;
- } while (mlen >= MINMATCH);
- }
-
- if (faster_get_matches && skip_num > 0) { skip_num--; continue; }
-
- best_mlen = (best_mlen > MINMATCH) ? best_mlen : MINMATCH;
-
- match_num = getAllMatches(ctx, inr, ip, iend, maxSearches, mls, matches, best_mlen);
- ZSTD_LOG_PARSER("%d: ZSTD_GetAllMatches match_num=%d\n", (int)(inr-base), match_num);
-
- if (match_num > 0 && matches[match_num-1].len > sufficient_len) {
- cur -= matches[match_num-1].back;
- best_mlen = matches[match_num-1].len;
- best_off = matches[match_num-1].off;
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- // set prices using matches at position = cur
- for (u = 0; u < match_num; u++) {
- mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
- cur2 = cur - matches[u].back;
- best_mlen = (cur2 + matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM - cur2;
-
- ZSTD_LOG_PARSER("%d: Found1 cur=%d cur2=%d mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(inr-base), cur, cur2, matches[u].len, matches[u].off, best_mlen, last_pos);
- if (mlen < matches[u].back + 1)
- mlen = matches[u].back + 1;
-
- while (mlen <= best_mlen) {
- if (opt[cur2].mlen == 1) {
- litlen = opt[cur2].litlen;
- if (cur2 > litlen)
- price = opt[cur2 - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip+cur2-litlen, matches[u].off, mlen - MINMATCH);
- else
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off, mlen - MINMATCH);
- } else {
- litlen = 0;
- price = opt[cur2].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off, mlen - MINMATCH);
- }
-
- ZSTD_LOG_PARSER("%d: Found2 pred=%d mlen=%d best_mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-base), matches[u].back, mlen, best_mlen, matches[u].off, price, litlen, cur - litlen, opt[cur - litlen].price);
- ZSTD_LOG_TRY_PRICE("%d: TRY8 price=%d opt[%d].price=%d\n", (int)(inr-base), price, cur2 + mlen, opt[cur2 + mlen].price);
-
- if (cur2 + mlen > last_pos || (price < opt[cur2 + mlen].price))
- SET_PRICE(cur2 + mlen, mlen, matches[u].off, litlen, price);
-
- mlen++;
- } } } // for (skip_num = 0, cur = 1; cur <= last_pos; cur++)
-
- best_mlen = opt[last_pos].mlen;
- best_off = opt[last_pos].off;
- cur = last_pos - best_mlen;
- // printf("%d: start=%d best_mlen=%d best_off=%d cur=%d\n", (int)(ip - base), (int)(start - ip), (int)best_mlen, (int)best_off, cur);
-
- /* store sequence */
-_storeSequence: // cur, last_pos, best_mlen, best_off have to be set
- for (u = 1; u <= last_pos; u++)
- ZSTD_LOG_PARSER("%d: price[%u/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(ip-base+u), u, last_pos, opt[u].price, opt[u].off, opt[u].mlen, opt[u].litlen, opt[u].rep, opt[u].rep2);
- ZSTD_LOG_PARSER("%d: cur=%d/%d best_mlen=%d best_off=%d rep=%d\n", (int)(ip-base+cur), (int)cur, (int)last_pos, (int)best_mlen, (int)best_off, opt[cur].rep);
-
- opt[0].mlen = 1;
-
- while (1) {
- mlen = opt[cur].mlen;
- ZSTD_LOG_PARSER("%d: cur=%d mlen=%d\n", (int)(ip-base), cur, mlen);
- offset = opt[cur].off;
- opt[cur].mlen = best_mlen;
- opt[cur].off = best_off;
- best_mlen = mlen;
- best_off = offset;
- if (mlen > cur) break;
- cur -= mlen;
- }
-
- for (u = 0; u <= last_pos; ) {
- ZSTD_LOG_PARSER("%d: price2[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(ip-base+u), u, last_pos, opt[u].price, opt[u].off, opt[u].mlen, opt[u].litlen, opt[u].rep, opt[u].rep2);
- u += opt[u].mlen;
- }
-
- for (cur=0; cur < last_pos; ) {
- U32 litLength;
- ZSTD_LOG_PARSER("%d: price3[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(ip-base+cur), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2);
- mlen = opt[cur].mlen;
- if (mlen == 1) { ip++; cur++; continue; }
- offset = opt[cur].off;
- cur += mlen;
-
- litLength = (U32)(ip - anchor);
- ZSTD_LOG_ENCODE("%d/%d: ENCODE1 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2);
-
- if (offset) {
- rep_2 = rep_1;
- rep_1 = offset;
- } else {
- if (litLength == 0) {
- best_off = rep_2;
- rep_2 = rep_1;
- rep_1 = best_off;
- } }
-
- ZSTD_LOG_ENCODE("%d/%d: ENCODE2 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2);
-
-#if ZSTD_OPT_DEBUG >= 5
- int ml2;
- if (offset)
- ml2 = ZSTD_count(ip, ip-offset, iend);
- else
- ml2 = ZSTD_count(ip, ip-rep_1, iend);
- if (ml2 < mlen && ml2 < MINMATCH) {
- printf("%d: ERROR iend=%d mlen=%d offset=%d ml2=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset, (int)ml2); exit(0); }
- if (ip < anchor) {
- printf("%d: ERROR ip < anchor iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
- if (ip - offset < ctx->base) {
- printf("%d: ERROR ip - offset < base iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
- if ((int)offset >= (1 << ctx->params.windowLog)) {
- printf("%d: offset >= (1 << params.windowLog) iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
- if (mlen < MINMATCH) {
- printf("%d: ERROR mlen < MINMATCH iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
- if (ip + mlen > iend) {
- printf("%d: ERROR ip + mlen >= iend iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
-#endif
-
- ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
- anchor = ip = ip + mlen;
- }
-
- /* check immediate repcode */
- while (anchor <= ilimit) {
- const U32 repIndex = (U32)((anchor-base) - rep_2);
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* const repMatch = repBase + repIndex;
- if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
- && (MEM_read32(anchor) == MEM_read32(repMatch)) ) {
- /* repcode detected, let's take it */
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
- mlen = (U32)ZSTD_count_2segments(anchor+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
- offset = rep_2; rep_2 = rep_1; rep_1 = offset; /* swap offset history */
- ZSTD_LOG_ENCODE("%d/%d: ENCODE REP literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(anchor-base), (int)(iend-base), (int)(0), (int)best_mlen, (int)(0), (int)rep_1, (int)rep_2);
- ZSTD_updatePrice(seqStorePtr, 0, anchor, 0, mlen-MINMATCH);
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, mlen-MINMATCH);
- anchor += mlen;
- continue; /* faster when present ... (?) */
- }
- break;
- }
- if (anchor > ip) ip = anchor;
- }
-
- { /* Last Literals */
- size_t lastLLSize = iend - anchor;
- ZSTD_LOG_ENCODE("%d: lastLLSize literals=%u\n", (int)(ip-base), (U32)(lastLLSize));
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
diff --git a/programs/fileio.c b/programs/fileio.c
index befe71d..5e7b26d 100644
--- a/programs/fileio.c
+++ b/programs/fileio.c
@@ -371,27 +371,7 @@ static int FIO_compressFilename_internal(cRess_t ress,
(double)compressedfilesize/readsize*100, (unsigned long long)readsize, (unsigned long long) compressedfilesize,
dstFileName);
-
-/*! FIO_compressFilename_extRess() :
- * @return : 0 : compression completed correctly,
- * 1 : missing or pb opening srcFileName
- */
-static int FIO_compressFilename_extRess(cRess_t ress,
- const char* dstFileName, const char* srcFileName,
- int cLevel)
-{
- int result;
-
- ress.srcFile = FIO_openSrcFile(srcFileName);
- if (ress.srcFile==0) return 1;
- ress.dstFile = FIO_openDstFile(dstFileName);
- if (ress.dstFile==0) { fclose(ress.srcFile); return 1; }
-
- result = FIO_compressFilename_internal(ress, dstFileName, srcFileName, cLevel);
-
- fclose(ress.srcFile); /* no pb to expect : only reading */
- if (fclose(ress.dstFile)) EXM_THROW(28, "Write error : cannot properly close %s", dstFileName);
- return result;
+ return 0;
}
diff --git a/programs/zstd.1 b/programs/zstd.1
index 84ab946..d7760f7 100644
--- a/programs/zstd.1
+++ b/programs/zstd.1
@@ -71,23 +71,6 @@ It also features a very fast decoder, with speed > 500 MB/s per core.
.TP
.BR \-c ", " --stdout
force write to standard output, even if it is the console
-
-.SH DICTIONARY
-.PP
-\fBzstd\fR offers \fIdictionary\fR compression, useful for very small files and messages.
-It's possible to train \fBzstd\fR with some samples, the result of which is saved into a file called `dictionary`.
-Then during compression and decompression, make reference to the same dictionary.
-It will improve compression ratio of small files.
-Typical gains range from ~10% (at 64KB) to x5 better (at <1KB).
-.TP
-.B \--train FILEs
- use FILEs as training set to create a dictionary.
- The training set should contain a lot of small files (> 100).
- and weight typically 100x the target dictionary size
- (for example, 10 MB for a 100 KB dictionary)
-.TP
-.B \-o file
- dictionary saved into `file` (default: dictionary)
.TP
.BR \-C ", " --check
add integrity check computed from uncompressed data
diff --git a/programs/zstdcli.c b/programs/zstdcli.c
index 89c13b8..bf40dad 100644
--- a/programs/zstdcli.c
+++ b/programs/zstdcli.c
@@ -126,7 +126,6 @@ static int usage_advanced(const char* programName)
DISPLAY( "\n");
DISPLAY( "Advanced arguments :\n");
DISPLAY( " -V : display Version number and exit\n");
- DISPLAY( " -t : test compressed file integrity \n");
DISPLAY( " -v : verbose mode\n");
DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n");
DISPLAY( " -c : force write to standard output, even if it is the console\n");
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/libzstd.git
More information about the debian-med-commit
mailing list