📄 xdelta3-djw.h
字号:
/* xdelta 3 - delta compression tools and library * Copyright (C) 2002, 2006, 2007. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* TODO: This code needs a thorough round of commenting. There is * some slop in the declaration of arrays, which are maybe one element * larger than they need to be and comments would help clear it up. */#ifndef _XDELTA3_DJW_H_#define _XDELTA3_DJW_H_/* The following people deserve much credit for the algorithms and * techniques contained in this file: Julian Seward Bzip2 sources, implementation of the multi-table Huffman technique. Jean-loup Gailly and Mark Adler and L. Peter Deutsch Zlib source code, RFC 1951 Daniel S. Hirschberg and Debra A. LeLewer "Efficient Decoding of Prefix Codes" Communications of the ACM, April 1990 33(4). David J. Wheeler Program bred3.c, bexp3 and accompanying documents bred3.ps, huff.ps. This contains the idea behind the multi-table Huffman and 1-2 coding techniques. ftp://ftp.cl.cam.ac.uk/users/djw3/*//* OPT: during the multi-table iteration, pick the worst-overall * performing table and replace it with exactly the frequencies of the * worst-overall performing sector or N-worst performing sectors. *//* REF: See xdfs-0.222 and xdfs-0.226 for some old experiments with * the Bzip prefix coding strategy. xdfs-0.256 contains the last of * the other-format tests, including RFC1950 and the RFC1950+MTF * tests. */#define DJW_MAX_CODELEN 20 /* Maximum length of an alphabet code. *//* Code lengths are themselves code-length encoded, so the total number of * codes is: [RUN_0, RUN_1, 1-DJW_MAX_CODELEN] */#define DJW_TOTAL_CODES (DJW_MAX_CODELEN+2)#define RUN_0 0 /* Symbols used in MTF+1/2 coding. */#define RUN_1 1/* Number of code lengths always encoded (djw_encode_basic array) */#define DJW_BASIC_CODES 5 #define DJW_RUN_CODES 2 /* Number of run codes *//* Offset of extra codes */#define DJW_EXTRA_12OFFSET (DJW_BASIC_CODES + DJW_RUN_CODES)/* Number of optionally encoded code lengths (djw_encode_extra array) */#define DJW_EXTRA_CODES 15/* Number of bits to code [0-DJW_EXTRA_CODES] */#define DJW_EXTRA_CODE_BITS 4 #define DJW_MAX_GROUPS 8 /* Max number of group coding tables */#define DJW_GROUP_BITS 3 /* Number of bits to code [1-DJW_MAX_GROUPS] */#define DJW_SECTORSZ_MULT 5 /* Multiplier for encoded sectorsz */#define DJW_SECTORSZ_BITS 5 /* Number of bits to code group size */#define DJW_SECTORSZ_MAX ((1 << DJW_SECTORSZ_BITS) * DJW_SECTORSZ_MULT)/* Maximum number of iterations to find group tables. */#define DJW_MAX_ITER 6/* Minimum number of bits an iteration must reduce coding by. */#define DJW_MIN_IMPROVEMENT 20 /* Maximum code length of a prefix code length */#define DJW_MAX_CLCLEN 15/* Number of bits to code [0-DJW_MAX_CLCLEN] */#define DJW_CLCLEN_BITS 4 #define DJW_MAX_GBCLEN 7 /* Maximum code length of a group selector *//* Number of bits to code [0-DJW_MAX_GBCLEN] * TODO: Actually, should never have zero code lengths here, or else a group * went unused. Write a test for this: if a group goes unused, eliminate * it? */#define DJW_GBCLEN_BITS 3 /* It has to save at least this many bits... */#define EFFICIENCY_BITS 16typedef struct _djw_stream djw_stream;typedef struct _djw_heapen djw_heapen;typedef struct _djw_prefix djw_prefix;typedef uint32_t djw_weight;struct _djw_heapen{ uint32_t depth; uint32_t freq; uint32_t parent;};struct _djw_prefix{ usize_t scount; uint8_t *symbol; usize_t mcount; uint8_t *mtfsym; uint8_t *repcnt;};struct _djw_stream{ int unused;};/* Each Huffman table consists of 256 "code length" (CLEN) codes, * which are themselves Huffman coded after eliminating repeats and * move-to-front coding. The prefix consists of all the CLEN codes in * djw_encode_basic plus a 4-bit value stating how many of the * djw_encode_extra codes are actually coded (the rest are presumed * zero, or unused CLEN codes). * * These values of these two arrays were arrived at by studying the * distribution of min and max clen over a collection of DATA, INST, * and ADDR inputs. The goal is to specify the order of * djw_extra_codes that is most likely to minimize the number of extra * codes that must be encoded. * * Results: 158896 sections were counted by compressing files (window * size 512K) listed with: `find / -type f ( -user jmacd -o -perm +444 * )` * * The distribution of CLEN codes for each efficient invocation of the * secondary compressor (taking the best number of groups/sector size) * was recorded. Then we look at the distribution of min and max clen * values, counting the number of times the value C_low is less than * the min and C_high is greater than the max. Values >= C_high and * <= C_low will not have their lengths coded. The results are sorted * and the least likely 15 are placed into the djw_encode_extra[] * array in order. These values are used as the initial MTF ordering. clow[1] = 155119 clow[2] = 140325 clow[3] = 84072 --- clow[4] = 7225 clow[5] = 1093 clow[6] = 215 --- chigh[4] = 1 chigh[5] = 30 chigh[6] = 218 chigh[7] = 2060 chigh[8] = 13271 --- chigh[9] = 39463 chigh[10] = 77360 chigh[11] = 118298 chigh[12] = 141360 chigh[13] = 154086 chigh[14] = 157967 chigh[15] = 158603 chigh[16] = 158864 chigh[17] = 158893 chigh[18] = 158895 chigh[19] = 158896 chigh[20] = 158896*/static const uint8_t djw_encode_12extra[DJW_EXTRA_CODES] = { 9, 10, 3, 11, 2, 12, 13, 1, 14, 15, 16, 17, 18, 19, 20, };static const uint8_t djw_encode_12basic[DJW_BASIC_CODES] = { 4, 5, 6, 7, 8, };/*********************************************************************//* DECLS *//*********************************************************************/static djw_stream* djw_alloc (xd3_stream *stream);static void djw_init (djw_stream *h);static void djw_destroy (xd3_stream *stream, djw_stream *h);#if XD3_ENCODERstatic int xd3_encode_huff (xd3_stream *stream, djw_stream *sec_stream, xd3_output *input, xd3_output *output, xd3_sec_cfg *cfg);#endifstatic int xd3_decode_huff (xd3_stream *stream, djw_stream *sec_stream, const uint8_t **input, const uint8_t *const input_end, uint8_t **output, const uint8_t *const output_end);/*********************************************************************//* HUFFMAN *//*********************************************************************/static djw_stream*djw_alloc (xd3_stream *stream){ return xd3_alloc (stream, sizeof (djw_stream), 1);}static voiddjw_init (djw_stream *h){ /* Fields are initialized prior to use. */}static voiddjw_destroy (xd3_stream *stream, djw_stream *h){ xd3_free (stream, h);}/*********************************************************************//* HEAP *//*********************************************************************/static inline intheap_less (const djw_heapen *a, const djw_heapen *b){ return a->freq < b->freq || (a->freq == b->freq && a->depth < b->depth);}static inline voidheap_insert (usize_t *heap, const djw_heapen *ents, usize_t p, const usize_t e){ /* Insert ents[e] into next slot heap[p] */ usize_t pp = p/2; /* P's parent */ while (heap_less (& ents[e], & ents[heap[pp]])) { heap[p] = heap[pp]; p = pp; pp = p/2; } heap[p] = e;}static inline djw_heapen*heap_extract (usize_t *heap, const djw_heapen *ents, usize_t heap_last){ usize_t smallest = heap[1]; usize_t p, pc, t; /* Caller decrements heap_last, so heap_last+1 is the replacement elt. */ heap[1] = heap[heap_last+1]; /* Re-heapify */ for (p = 1; ; p = pc) { pc = p*2; /* Reached bottom of heap */ if (pc > heap_last) { break; } /* See if second child is smaller. */ if (pc < heap_last && heap_less (& ents[heap[pc+1]], & ents[heap[pc]])) { pc += 1; } /* If pc is not smaller than p, heap property re-established. */ if (! heap_less (& ents[heap[pc]], & ents[heap[p]])) { break; } t = heap[pc]; heap[pc] = heap[p]; heap[p] = t; } return (djw_heapen*) & ents[smallest];}#if XD3_DEBUGstatic voidheap_check (usize_t *heap, djw_heapen *ents, usize_t heap_last){ usize_t i; for (i = 1; i <= heap_last; i += 1) { /* Heap property: child not less than parent */ XD3_ASSERT (! heap_less (& ents[heap[i]], & ents[heap[i/2]])); IF_DEBUG1 (DP(RINT "heap[%d] = %u\n", i, ents[heap[i]].freq)); }}#endif/*********************************************************************//* MTF, 1/2 *//*********************************************************************/static inline usize_tdjw_update_mtf (uint8_t *mtf, usize_t mtf_i){ int k; usize_t sym = mtf[mtf_i]; for (k = mtf_i; k != 0; k -= 1) { mtf[k] = mtf[k-1]; } mtf[0] = sym; return sym;}static inline voiddjw_update_1_2 (int *mtf_run, usize_t *mtf_i, uint8_t *mtfsym, djw_weight *freq){ int code; do { /* Offset by 1, since any number of RUN_ symbols implies run>0... */ *mtf_run -= 1; code = (*mtf_run & 1) ? RUN_1 : RUN_0; mtfsym[(*mtf_i)++] = code; freq[code] += 1; *mtf_run >>= 1; } while (*mtf_run >= 1); *mtf_run = 0;}static voiddjw_init_clen_mtf_1_2 (uint8_t *clmtf){ int i, cl_i = 0; clmtf[cl_i++] = 0; for (i = 0; i < DJW_BASIC_CODES; i += 1) { clmtf[cl_i++] = djw_encode_12basic[i]; } for (i = 0; i < DJW_EXTRA_CODES; i += 1) { clmtf[cl_i++] = djw_encode_12extra[i]; }}/*********************************************************************//* PREFIX CODES *//*********************************************************************/#if XD3_ENCODERstatic usize_tdjw_build_prefix (const djw_weight *freq, uint8_t *clen, int asize, int maxlen){ /* Heap with 0th entry unused, prefix tree with up to ALPHABET_SIZE-1 * internal nodes, never more than ALPHABET_SIZE entries actually in the * heap (minimum weight subtrees during prefix construction). First * ALPHABET_SIZE entries are the actual symbols, next ALPHABET_SIZE-1 are * internal nodes. */ djw_heapen ents[ALPHABET_SIZE * 2]; usize_t heap[ALPHABET_SIZE + 1]; usize_t heap_last; /* Index of the last _valid_ heap entry. */ usize_t ents_size; /* Number of entries, including 0th fake entry */ int overflow; /* Number of code lengths that overflow */ uint32_t total_bits; int i; IF_DEBUG (uint32_t first_bits = 0); /* Insert real symbol frequences. */ for (i = 0; i < asize; i += 1) { ents[i+1].freq = freq[i]; IF_DEBUG1 (DP(RINT "ents[%d] = freq[%d] = %d\n", i+1, i, freq[i])); } again: /* The loop is re-entered each time an overflow occurs. Re-initialize... */ heap_last = 0; ents_size = 1; overflow = 0; total_bits = 0; /* 0th entry terminates the while loop in heap_insert (it's the parent of * the smallest element, always less-than) */ heap[0] = 0; ents[0].depth = 0; ents[0].freq = 0; /* Initial heap. */ for (i = 0; i < asize; i += 1, ents_size += 1) { ents[ents_size].depth = 0; ents[ents_size].parent = 0; if (ents[ents_size].freq != 0) { heap_insert (heap, ents, ++heap_last, ents_size); } } IF_DEBUG (heap_check (heap, ents, heap_last)); /* Must be at least one symbol, or else we can't get here. */ XD3_ASSERT (heap_last != 0); /* If there is only one symbol, fake a second to prevent zero-length * codes. */ if (heap_last == 1) { /* Pick either the first or last symbol. */ int s = freq[0] ? asize-1 : 0; ents[s+1].freq = 1; goto again; } /* Build prefix tree. */ while (heap_last > 1) { djw_heapen *h1 = heap_extract (heap, ents, --heap_last); djw_heapen *h2 = heap_extract (heap, ents, --heap_last); ents[ents_size].freq = h1->freq + h2->freq; ents[ents_size].depth = 1 + max (h1->depth, h2->depth); ents[ents_size].parent = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -