1
2
3
4
5 package flate
6
7 import (
8 "math"
9 )
10
11 const (
12
13
14
15
16
17 lengthShift = 22
18 offsetMask = 1<<lengthShift - 1
19 typeMask = 3 << 30
20 matchType = 1 << 30
21 matchOffsetOnlyMask = 0xffff
22 )
23
24
25
26 var lengthCodes = [256]uint8{
27 0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
28 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
29 13, 13, 13, 13, 14, 14, 14, 14, 15, 15,
30 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
31 17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
32 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
33 19, 19, 19, 19, 20, 20, 20, 20, 20, 20,
34 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
35 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
36 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
37 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
38 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
39 23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
40 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
41 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
42 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
43 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
44 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
45 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
46 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
47 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
48 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
49 26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
50 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
51 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
52 27, 27, 27, 27, 27, 28,
53 }
54
55
56 var lengthCodes1 = [256]uint8{
57 1, 2, 3, 4, 5, 6, 7, 8, 9, 9,
58 10, 10, 11, 11, 12, 12, 13, 13, 13, 13,
59 14, 14, 14, 14, 15, 15, 15, 15, 16, 16,
60 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,
61 18, 18, 18, 18, 18, 18, 18, 18, 19, 19,
62 19, 19, 19, 19, 19, 19, 20, 20, 20, 20,
63 20, 20, 20, 20, 21, 21, 21, 21, 21, 21,
64 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
65 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
66 22, 22, 22, 22, 22, 22, 23, 23, 23, 23,
67 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
68 23, 23, 24, 24, 24, 24, 24, 24, 24, 24,
69 24, 24, 24, 24, 24, 24, 24, 24, 25, 25,
70 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
71 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
72 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
73 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
74 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
75 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
76 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
77 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
78 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
79 27, 27, 27, 27, 28, 28, 28, 28, 28, 28,
80 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
81 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
82 28, 28, 28, 28, 28, 29,
83 }
84
85 var offsetCodes = [256]uint32{
86 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
87 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
88 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
89 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
90 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
91 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
92 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
93 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
94 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
95 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
96 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
97 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
98 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
99 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
100 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
101 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
102 }
103
104
105 var offsetCodes14 = [256]uint32{
106 14, 15, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
107 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
108 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
109 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
110 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
111 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
112 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
113 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
114 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
115 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
116 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
117 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
118 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
119 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
120 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
121 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
122 }
123
124
125
126 type token uint32
127
128
129
130
131 type tokens struct {
132 extraHist [32]uint16
133 offHist [32]uint16
134 litHist [256]uint16
135 nFilled int
136 n uint16
137 tokens [65536]token
138 }
139
140
141 func (t *tokens) Reset() {
142 if t.n == 0 {
143 return
144 }
145 t.n = 0
146 t.nFilled = 0
147 clear(t.litHist[:])
148 clear(t.extraHist[:])
149 clear(t.offHist[:])
150 }
151
152
153 func indexTokens(in []token) tokens {
154 var t tokens
155 t.indexTokens(in)
156 return t
157 }
158
159
160 func (t *tokens) indexTokens(in []token) {
161 t.Reset()
162 for _, tok := range in {
163 if tok < matchType {
164 t.AddLiteral(tok.literal())
165 continue
166 }
167 t.AddMatch(uint32(tok.length()), tok.offset()&matchOffsetOnlyMask)
168 }
169 }
170
171
172 func emitLiterals(dst *tokens, lit []byte) {
173 for _, v := range lit {
174 dst.tokens[dst.n] = token(v)
175 dst.litHist[v]++
176 dst.n++
177 }
178 }
179
180
181 func (t *tokens) AddLiteral(lit byte) {
182 t.tokens[t.n] = token(lit)
183 t.litHist[lit]++
184 t.n++
185 }
186
187
188
189 func mFastLog2(val float32) float32 {
190 ux := int32(math.Float32bits(val))
191 log2 := (float32)(((ux >> 23) & 255) - 128)
192 ux &= -0x7f800001
193 ux += 127 << 23
194 uval := math.Float32frombits(uint32(ux))
195 log2 += ((-0.34484843)*uval+2.02466578)*uval - 0.67487759
196 return log2
197 }
198
199
200
201
202
203 func (t *tokens) EstimatedBits() int {
204 shannon := float32(0)
205 bits := int(0)
206 nMatches := 0
207 total := int(t.n) + t.nFilled
208 if total > 0 {
209 invTotal := 1.0 / float32(total)
210 for _, v := range t.litHist[:] {
211 if v > 0 {
212 n := float32(v)
213 shannon += min(15, max(1, -mFastLog2(n*invTotal))) * n
214 }
215 }
216
217 shannon += 15
218 for i, v := range t.extraHist[1 : literalCount-256] {
219 if v > 0 {
220 n := float32(v)
221 shannon += min(15, max(1, -mFastLog2(n*invTotal))) * n
222 bits += int(lengthExtraBits[i&31]) * int(v)
223 nMatches += int(v)
224 }
225 }
226 }
227 if nMatches > 0 {
228 invTotal := 1.0 / float32(nMatches)
229 for i, v := range t.offHist[:offsetCodeCount] {
230 if v > 0 {
231 n := float32(v)
232 shannon += min(15, max(1, -mFastLog2(n*invTotal))) * n
233 bits += int(offsetExtraBits[i&31]) * int(v)
234 }
235 }
236 }
237 return int(shannon) + bits
238 }
239
240
241
242 func (t *tokens) AddMatch(xlength uint32, xoffset uint32) {
243 oCode := offsetCode(xoffset)
244 xoffset |= oCode << 16
245
246 t.extraHist[lengthCodes1[uint8(xlength)]]++
247 t.offHist[oCode&31]++
248 t.tokens[t.n] = token(matchType | xlength<<lengthShift | xoffset)
249 t.n++
250 }
251
252
253
254 func (t *tokens) AddMatchLong(xlength int32, xoffset uint32) {
255 oc := offsetCode(xoffset)
256 xoffset |= oc << 16
257 for xlength > 0 {
258 xl := xlength
259 if xl > 258 {
260
261 if xl > 258+baseMatchLength {
262 xl = 258
263 } else {
264 xl = 258 - baseMatchLength
265 }
266 }
267 xlength -= xl
268 xl -= baseMatchLength
269 t.extraHist[lengthCodes1[uint8(xl)]]++
270 t.offHist[oc&31]++
271 t.tokens[t.n] = token(matchType | uint32(xl)<<lengthShift | xoffset)
272 t.n++
273 }
274 }
275
276
277 func (t *tokens) AddEOB() {
278 t.tokens[t.n] = token(endBlockMarker)
279 t.extraHist[0]++
280 t.n++
281 }
282
283
284 func (t *tokens) Slice() []token {
285 return t.tokens[:t.n]
286 }
287
288
289 func (t token) typ() uint32 { return uint32(t) & typeMask }
290
291
292 func (t token) literal() uint8 { return uint8(t) }
293
294
295 func (t token) offset() uint32 { return uint32(t) & offsetMask }
296
297
298 func (t token) length() uint8 { return uint8(t >> lengthShift) }
299
300
301 func lengthCode(len uint8) uint8 { return lengthCodes[len] }
302
303
304 func offsetCode(off uint32) uint32 {
305 if off < uint32(len(offsetCodes)) {
306 return offsetCodes[uint8(off)]
307 }
308 return offsetCodes14[uint8(off>>7)]
309 }
310
View as plain text