Mercurial > repos > youngkim > ezbamqc
comparison ezBAMQC/src/htslib/cram/rANS_static.c @ 0:dfa3745e5fd8
Uploaded
author | youngkim |
---|---|
date | Thu, 24 Mar 2016 17:12:52 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:dfa3745e5fd8 |
---|---|
1 /* | |
2 * Copyright (c) 2014 Genome Research Ltd. | |
3 * Author(s): James Bonfield | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions are met: | |
7 * | |
8 * 1. Redistributions of source code must retain the above copyright notice, | |
9 * this list of conditions and the following disclaimer. | |
10 * | |
11 * 2. Redistributions in binary form must reproduce the above | |
12 * copyright notice, this list of conditions and the following | |
13 * disclaimer in the documentation and/or other materials provided | |
14 * with the distribution. | |
15 * | |
16 * 3. Neither the names Genome Research Ltd and Wellcome Trust Sanger | |
17 * Institute nor the names of its contributors may be used to endorse | |
18 * or promote products derived from this software without specific | |
19 * prior written permission. | |
20 * | |
21 * THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS | |
22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
24 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH | |
25 * LTD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 */ | |
33 | |
34 /* | |
35 * Author: James Bonfield, Wellcome Trust Sanger Institute. 2014 | |
36 */ | |
37 | |
38 #include <stdint.h> | |
39 #include <stdlib.h> | |
40 #include <stdio.h> | |
41 #include <unistd.h> | |
42 #include <assert.h> | |
43 #include <string.h> | |
44 #include <sys/time.h> | |
45 | |
46 #include "cram/rANS_static.h" | |
47 #include "cram/rANS_byte.h" | |
48 | |
49 #define TF_SHIFT 12 | |
50 #define TOTFREQ (1<<TF_SHIFT) | |
51 | |
52 #define ABS(a) ((a)>0?(a):-(a)) | |
53 #ifndef BLK_SIZE | |
54 # define BLK_SIZE 1024*1024 | |
55 #endif | |
56 | |
57 // Room to allow for expanded BLK_SIZE on worst case compression. | |
58 #define BLK_SIZE2 ((int)(1.05*BLK_SIZE)) | |
59 | |
60 /*----------------------------------------------------------------------------- | |
61 * Memory to memory compression functions. | |
62 * | |
63 * These are original versions without any manual loop unrolling. They | |
64 * are easier to understand, but can be up to 2x slower. | |
65 */ | |
66 | |
67 unsigned char *rans_compress_O0(unsigned char *in, unsigned int in_size, | |
68 unsigned int *out_size) { | |
69 unsigned char *out_buf = malloc(1.05*in_size + 257*257*3 + 9); | |
70 unsigned char *cp, *out_end; | |
71 RansEncSymbol syms[256]; | |
72 RansState rans0, rans1, rans2, rans3; | |
73 uint8_t* ptr; | |
74 int F[256] = {0}, i, j, tab_size, rle, x, fsum = 0; | |
75 int m = 0, M = 0; | |
76 uint64_t tr; | |
77 | |
78 if (!out_buf) | |
79 return NULL; | |
80 | |
81 ptr = out_end = out_buf + (int)(1.05*in_size) + 257*257*3 + 9; | |
82 | |
83 // Compute statistics | |
84 for (i = 0; i < in_size; i++) { | |
85 F[in[i]]++; | |
86 } | |
87 tr = ((uint64_t)TOTFREQ<<31)/in_size + (1<<30)/in_size; | |
88 | |
89 // Normalise so T[i] == TOTFREQ | |
90 for (m = M = j = 0; j < 256; j++) { | |
91 if (!F[j]) | |
92 continue; | |
93 | |
94 if (m < F[j]) | |
95 m = F[j], M = j; | |
96 | |
97 if ((F[j] = (F[j]*tr)>>31) == 0) | |
98 F[j] = 1; | |
99 fsum += F[j]; | |
100 } | |
101 | |
102 fsum++; | |
103 if (fsum < TOTFREQ) | |
104 F[M] += TOTFREQ-fsum; | |
105 else | |
106 F[M] -= fsum-TOTFREQ; | |
107 | |
108 //printf("F[%d]=%d\n", M, F[M]); | |
109 assert(F[M]>0); | |
110 | |
111 // Encode statistics. | |
112 cp = out_buf+9; | |
113 | |
114 for (x = rle = j = 0; j < 256; j++) { | |
115 if (F[j]) { | |
116 // j | |
117 if (rle) { | |
118 rle--; | |
119 } else { | |
120 *cp++ = j; | |
121 if (!rle && j && F[j-1]) { | |
122 for(rle=j+1; rle<256 && F[rle]; rle++) | |
123 ; | |
124 rle -= j+1; | |
125 *cp++ = rle; | |
126 } | |
127 //fprintf(stderr, "%d: %d %d\n", j, rle, N[j]); | |
128 } | |
129 | |
130 // F[j] | |
131 if (F[j]<128) { | |
132 *cp++ = F[j]; | |
133 } else { | |
134 *cp++ = 128 | (F[j]>>8); | |
135 *cp++ = F[j]&0xff; | |
136 } | |
137 RansEncSymbolInit(&syms[j], x, F[j], TF_SHIFT); | |
138 x += F[j]; | |
139 } | |
140 } | |
141 *cp++ = 0; | |
142 | |
143 //write(1, out_buf+4, cp-(out_buf+4)); | |
144 tab_size = cp-out_buf; | |
145 | |
146 RansEncInit(&rans0); | |
147 RansEncInit(&rans1); | |
148 RansEncInit(&rans2); | |
149 RansEncInit(&rans3); | |
150 | |
151 switch (i=(in_size&3)) { | |
152 case 3: RansEncPutSymbol(&rans2, &ptr, &syms[in[in_size-(i-2)]]); | |
153 case 2: RansEncPutSymbol(&rans1, &ptr, &syms[in[in_size-(i-1)]]); | |
154 case 1: RansEncPutSymbol(&rans0, &ptr, &syms[in[in_size-(i-0)]]); | |
155 case 0: | |
156 break; | |
157 } | |
158 for (i=(in_size &~3); i>0; i-=4) { | |
159 RansEncSymbol *s3 = &syms[in[i-1]]; | |
160 RansEncSymbol *s2 = &syms[in[i-2]]; | |
161 RansEncSymbol *s1 = &syms[in[i-3]]; | |
162 RansEncSymbol *s0 = &syms[in[i-4]]; | |
163 | |
164 RansEncPutSymbol(&rans3, &ptr, s3); | |
165 RansEncPutSymbol(&rans2, &ptr, s2); | |
166 RansEncPutSymbol(&rans1, &ptr, s1); | |
167 RansEncPutSymbol(&rans0, &ptr, s0); | |
168 } | |
169 | |
170 RansEncFlush(&rans3, &ptr); | |
171 RansEncFlush(&rans2, &ptr); | |
172 RansEncFlush(&rans1, &ptr); | |
173 RansEncFlush(&rans0, &ptr); | |
174 | |
175 // Finalise block size and return it | |
176 *out_size = (out_end - ptr) + tab_size; | |
177 | |
178 cp = out_buf; | |
179 | |
180 *cp++ = 0; // order | |
181 *cp++ = ((*out_size-9)>> 0) & 0xff; | |
182 *cp++ = ((*out_size-9)>> 8) & 0xff; | |
183 *cp++ = ((*out_size-9)>>16) & 0xff; | |
184 *cp++ = ((*out_size-9)>>24) & 0xff; | |
185 | |
186 *cp++ = (in_size>> 0) & 0xff; | |
187 *cp++ = (in_size>> 8) & 0xff; | |
188 *cp++ = (in_size>>16) & 0xff; | |
189 *cp++ = (in_size>>24) & 0xff; | |
190 | |
191 memmove(out_buf + tab_size, ptr, out_end-ptr); | |
192 | |
193 return out_buf; | |
194 } | |
195 | |
196 typedef struct { | |
197 struct { | |
198 int F; | |
199 int C; | |
200 } fc[256]; | |
201 unsigned char *R; | |
202 } ari_decoder; | |
203 | |
204 unsigned char *rans_uncompress_O0(unsigned char *in, unsigned int in_size, | |
205 unsigned int *out_size) { | |
206 /* Load in the static tables */ | |
207 unsigned char *cp = in + 9; | |
208 int i, j, x, out_sz, in_sz, rle; | |
209 char *out_buf; | |
210 ari_decoder D; | |
211 RansDecSymbol syms[256]; | |
212 | |
213 memset(&D, 0, sizeof(D)); | |
214 | |
215 if (*in++ != 0) // Order-0 check | |
216 return NULL; | |
217 | |
218 in_sz = ((in[0])<<0) | ((in[1])<<8) | ((in[2])<<16) | ((in[3])<<24); | |
219 out_sz = ((in[4])<<0) | ((in[5])<<8) | ((in[6])<<16) | ((in[7])<<24); | |
220 if (in_sz != in_size-9) | |
221 return NULL; | |
222 | |
223 out_buf = malloc(out_sz); | |
224 if (!out_buf) | |
225 return NULL; | |
226 | |
227 //fprintf(stderr, "out_sz=%d\n", out_sz); | |
228 | |
229 // Precompute reverse lookup of frequency. | |
230 rle = x = 0; | |
231 j = *cp++; | |
232 do { | |
233 if ((D.fc[j].F = *cp++) >= 128) { | |
234 D.fc[j].F &= ~128; | |
235 D.fc[j].F = ((D.fc[j].F & 127) << 8) | *cp++; | |
236 } | |
237 D.fc[j].C = x; | |
238 | |
239 RansDecSymbolInit(&syms[j], D.fc[j].C, D.fc[j].F); | |
240 | |
241 /* Build reverse lookup table */ | |
242 if (!D.R) D.R = (unsigned char *)malloc(TOTFREQ); | |
243 memset(&D.R[x], j, D.fc[j].F); | |
244 | |
245 x += D.fc[j].F; | |
246 | |
247 if (!rle && j+1 == *cp) { | |
248 j = *cp++; | |
249 rle = *cp++; | |
250 } else if (rle) { | |
251 rle--; | |
252 j++; | |
253 } else { | |
254 j = *cp++; | |
255 } | |
256 } while(j); | |
257 | |
258 assert(x < TOTFREQ); | |
259 | |
260 RansState rans0, rans1, rans2, rans3; | |
261 uint8_t *ptr = cp; | |
262 RansDecInit(&rans0, &ptr); | |
263 RansDecInit(&rans1, &ptr); | |
264 RansDecInit(&rans2, &ptr); | |
265 RansDecInit(&rans3, &ptr); | |
266 | |
267 int out_end = (out_sz&~3); | |
268 | |
269 RansState R[4]; | |
270 R[0] = rans0; | |
271 R[1] = rans1; | |
272 R[2] = rans2; | |
273 R[3] = rans3; | |
274 uint32_t mask = (1u << TF_SHIFT)-1; | |
275 | |
276 for (i=0; i < out_end; i+=4) { | |
277 uint32_t m[4] = {R[0] & mask, | |
278 R[1] & mask, | |
279 R[2] & mask, | |
280 R[3] & mask}; | |
281 uint8_t c[4] = {D.R[m[0]], | |
282 D.R[m[1]], | |
283 D.R[m[2]], | |
284 D.R[m[3]]}; | |
285 out_buf[i+0] = c[0]; | |
286 out_buf[i+1] = c[1]; | |
287 out_buf[i+2] = c[2]; | |
288 out_buf[i+3] = c[3]; | |
289 | |
290 // RansDecAdvanceSymbolStep(&R[0], &syms[c[0]], TF_SHIFT); | |
291 // RansDecAdvanceSymbolStep(&R[1], &syms[c[1]], TF_SHIFT); | |
292 // RansDecAdvanceSymbolStep(&R[2], &syms[c[2]], TF_SHIFT); | |
293 // RansDecAdvanceSymbolStep(&R[3], &syms[c[3]], TF_SHIFT); | |
294 R[0] = syms[c[0]].freq * (R[0]>>TF_SHIFT); | |
295 R[1] = syms[c[1]].freq * (R[1]>>TF_SHIFT); | |
296 R[2] = syms[c[2]].freq * (R[2]>>TF_SHIFT); | |
297 R[3] = syms[c[3]].freq * (R[3]>>TF_SHIFT); | |
298 | |
299 R[0] += m[0] - syms[c[0]].start; | |
300 R[1] += m[1] - syms[c[1]].start; | |
301 R[2] += m[2] - syms[c[2]].start; | |
302 R[3] += m[3] - syms[c[3]].start; | |
303 | |
304 RansDecRenorm(&R[0], &ptr); | |
305 RansDecRenorm(&R[1], &ptr); | |
306 RansDecRenorm(&R[2], &ptr); | |
307 RansDecRenorm(&R[3], &ptr); | |
308 } | |
309 | |
310 rans0 = R[0]; | |
311 rans1 = R[1]; | |
312 rans2 = R[2]; | |
313 rans3 = R[3]; | |
314 | |
315 switch(out_sz&3) { | |
316 unsigned char c; | |
317 case 0: | |
318 break; | |
319 case 1: | |
320 c = D.R[RansDecGet(&rans0, TF_SHIFT)]; | |
321 RansDecAdvanceSymbol(&rans0, &ptr, &syms[c], TF_SHIFT); | |
322 out_buf[out_end] = c; | |
323 break; | |
324 | |
325 case 2: | |
326 c = D.R[RansDecGet(&rans0, TF_SHIFT)]; | |
327 RansDecAdvanceSymbol(&rans0, &ptr, &syms[c], TF_SHIFT); | |
328 out_buf[out_end] = c; | |
329 | |
330 c = D.R[RansDecGet(&rans1, TF_SHIFT)]; | |
331 RansDecAdvanceSymbol(&rans1, &ptr, &syms[c], TF_SHIFT); | |
332 out_buf[out_end+1] = c; | |
333 break; | |
334 | |
335 case 3: | |
336 c = D.R[RansDecGet(&rans0, TF_SHIFT)]; | |
337 RansDecAdvanceSymbol(&rans0, &ptr, &syms[c], TF_SHIFT); | |
338 out_buf[out_end] = c; | |
339 | |
340 c = D.R[RansDecGet(&rans1, TF_SHIFT)]; | |
341 RansDecAdvanceSymbol(&rans1, &ptr, &syms[c], TF_SHIFT); | |
342 out_buf[out_end+1] = c; | |
343 | |
344 c = D.R[RansDecGet(&rans2, TF_SHIFT)]; | |
345 RansDecAdvanceSymbol(&rans2, &ptr, &syms[c], TF_SHIFT); | |
346 out_buf[out_end+2] = c; | |
347 break; | |
348 } | |
349 | |
350 *out_size = out_sz; | |
351 | |
352 if (D.R) free(D.R); | |
353 | |
354 return (unsigned char *)out_buf; | |
355 } | |
356 | |
357 unsigned char *rans_compress_O1(unsigned char *in, unsigned int in_size, | |
358 unsigned int *out_size) { | |
359 unsigned char *out_buf, *out_end, *cp; | |
360 unsigned int last_i, tab_size, rle_i, rle_j; | |
361 RansEncSymbol syms[256][256]; | |
362 | |
363 if (in_size < 4) | |
364 return rans_compress_O0(in, in_size, out_size); | |
365 | |
366 out_buf = malloc(1.05*in_size + 257*257*3 + 9); | |
367 if (!out_buf) | |
368 return NULL; | |
369 | |
370 out_end = out_buf + (int)(1.05*in_size) + 257*257*3 + 9; | |
371 cp = out_buf+9; | |
372 | |
373 int F[256][256], T[256], i, j; | |
374 unsigned char c; | |
375 | |
376 memset(F, 0, 256*256*sizeof(int)); | |
377 memset(T, 0, 256*sizeof(int)); | |
378 //for (last = 0, i=in_size-1; i>=0; i--) { | |
379 // F[last][c = in[i]]++; | |
380 // T[last]++; | |
381 // last = c; | |
382 //} | |
383 | |
384 for (last_i=i=0; i<in_size; i++) { | |
385 F[last_i][c = in[i]]++; | |
386 T[last_i]++; | |
387 last_i = c; | |
388 } | |
389 F[0][in[1*(in_size>>2)]]++; | |
390 F[0][in[2*(in_size>>2)]]++; | |
391 F[0][in[3*(in_size>>2)]]++; | |
392 T[0]+=3; | |
393 | |
394 // Normalise so T[i] == TOTFREQ | |
395 for (rle_i = i = 0; i < 256; i++) { | |
396 int t2, m, M; | |
397 unsigned int x; | |
398 | |
399 if (T[i] == 0) | |
400 continue; | |
401 | |
402 //uint64_t p = (TOTFREQ * TOTFREQ) / t; | |
403 double p = ((double)TOTFREQ)/T[i]; | |
404 for (t2 = m = M = j = 0; j < 256; j++) { | |
405 if (!F[i][j]) | |
406 continue; | |
407 | |
408 if (m < F[i][j]) | |
409 m = F[i][j], M = j; | |
410 | |
411 //if ((F[i][j] = (F[i][j] * p) / TOTFREQ) == 0) | |
412 if ((F[i][j] *= p) == 0) | |
413 F[i][j] = 1; | |
414 t2 += F[i][j]; | |
415 } | |
416 | |
417 t2++; | |
418 if (t2 < TOTFREQ) | |
419 F[i][M] += TOTFREQ-t2; | |
420 else | |
421 F[i][M] -= t2-TOTFREQ; | |
422 | |
423 // Store frequency table | |
424 // i | |
425 if (rle_i) { | |
426 rle_i--; | |
427 } else { | |
428 *cp++ = i; | |
429 // FIXME: could use order-0 statistics to observe which alphabet | |
430 // symbols are present and base RLE on that ordering instead. | |
431 if (i && T[i-1]) { | |
432 for(rle_i=i+1; rle_i<256 && T[rle_i]; rle_i++) | |
433 ; | |
434 rle_i -= i+1; | |
435 *cp++ = rle_i; | |
436 } | |
437 } | |
438 | |
439 int *F_i_ = F[i]; | |
440 x = 0; | |
441 rle_j = 0; | |
442 for (j = 0; j < 256; j++) { | |
443 if (F_i_[j]) { | |
444 //fprintf(stderr, "F[%d][%d]=%d, x=%d\n", i, j, F_i_[j], x); | |
445 | |
446 // j | |
447 if (rle_j) { | |
448 rle_j--; | |
449 } else { | |
450 *cp++ = j; | |
451 if (!rle_j && j && F_i_[j-1]) { | |
452 for(rle_j=j+1; rle_j<256 && F_i_[rle_j]; rle_j++) | |
453 ; | |
454 rle_j -= j+1; | |
455 *cp++ = rle_j; | |
456 } | |
457 } | |
458 | |
459 // F_i_[j] | |
460 if (F_i_[j]<128) { | |
461 *cp++ = F_i_[j]; | |
462 } else { | |
463 *cp++ = 128 | (F_i_[j]>>8); | |
464 *cp++ = F_i_[j]&0xff; | |
465 } | |
466 | |
467 RansEncSymbolInit(&syms[i][j], x, F_i_[j], TF_SHIFT); | |
468 x += F_i_[j]; | |
469 } | |
470 } | |
471 *cp++ = 0; | |
472 } | |
473 *cp++ = 0; | |
474 | |
475 //write(1, out_buf+4, cp-(out_buf+4)); | |
476 tab_size = cp - out_buf; | |
477 assert(tab_size < 257*257*3); | |
478 | |
479 RansState rans0, rans1, rans2, rans3; | |
480 RansEncInit(&rans0); | |
481 RansEncInit(&rans1); | |
482 RansEncInit(&rans2); | |
483 RansEncInit(&rans3); | |
484 | |
485 uint8_t* ptr = out_end; | |
486 | |
487 int isz4 = in_size>>2; | |
488 int i0 = 1*isz4-2; | |
489 int i1 = 2*isz4-2; | |
490 int i2 = 3*isz4-2; | |
491 int i3 = 4*isz4-2; | |
492 | |
493 unsigned char l0 = in[i0+1]; | |
494 unsigned char l1 = in[i1+1]; | |
495 unsigned char l2 = in[i2+1]; | |
496 unsigned char l3 = in[i3+1]; | |
497 | |
498 // Deal with the remainder | |
499 l3 = in[in_size-1]; | |
500 for (i3 = in_size-2; i3 > 4*isz4-2; i3--) { | |
501 unsigned char c3 = in[i3]; | |
502 RansEncPutSymbol(&rans3, &ptr, &syms[c3][l3]); | |
503 l3 = c3; | |
504 } | |
505 | |
506 for (; i0 >= 0; i0--, i1--, i2--, i3--) { | |
507 unsigned char c0, c1, c2, c3; | |
508 RansEncSymbol *s3 = &syms[c3 = in[i3]][l3]; | |
509 RansEncSymbol *s2 = &syms[c2 = in[i2]][l2]; | |
510 RansEncSymbol *s1 = &syms[c1 = in[i1]][l1]; | |
511 RansEncSymbol *s0 = &syms[c0 = in[i0]][l0]; | |
512 | |
513 RansEncPutSymbol(&rans3, &ptr, s3); | |
514 RansEncPutSymbol(&rans2, &ptr, s2); | |
515 RansEncPutSymbol(&rans1, &ptr, s1); | |
516 RansEncPutSymbol(&rans0, &ptr, s0); | |
517 | |
518 l0 = c0; | |
519 l1 = c1; | |
520 l2 = c2; | |
521 l3 = c3; | |
522 } | |
523 | |
524 RansEncPutSymbol(&rans3, &ptr, &syms[0][l3]); | |
525 RansEncPutSymbol(&rans2, &ptr, &syms[0][l2]); | |
526 RansEncPutSymbol(&rans1, &ptr, &syms[0][l1]); | |
527 RansEncPutSymbol(&rans0, &ptr, &syms[0][l0]); | |
528 | |
529 RansEncFlush(&rans3, &ptr); | |
530 RansEncFlush(&rans2, &ptr); | |
531 RansEncFlush(&rans1, &ptr); | |
532 RansEncFlush(&rans0, &ptr); | |
533 | |
534 *out_size = (out_end - ptr) + tab_size; | |
535 | |
536 cp = out_buf; | |
537 *cp++ = 1; // order | |
538 | |
539 *cp++ = ((*out_size-9)>> 0) & 0xff; | |
540 *cp++ = ((*out_size-9)>> 8) & 0xff; | |
541 *cp++ = ((*out_size-9)>>16) & 0xff; | |
542 *cp++ = ((*out_size-9)>>24) & 0xff; | |
543 | |
544 *cp++ = (in_size>> 0) & 0xff; | |
545 *cp++ = (in_size>> 8) & 0xff; | |
546 *cp++ = (in_size>>16) & 0xff; | |
547 *cp++ = (in_size>>24) & 0xff; | |
548 | |
549 memmove(out_buf + tab_size, ptr, out_end-ptr); | |
550 | |
551 return out_buf; | |
552 } | |
553 | |
554 unsigned char *rans_uncompress_O1(unsigned char *in, unsigned int in_size, | |
555 unsigned int *out_size) { | |
556 /* Load in the static tables */ | |
557 unsigned char *cp = in + 9; | |
558 int i, j = -999, x, out_sz, in_sz, rle_i, rle_j; | |
559 char *out_buf; | |
560 ari_decoder D[256]; | |
561 RansDecSymbol syms[256][256]; | |
562 | |
563 memset(D, 0, 256*sizeof(*D)); | |
564 | |
565 if (*in++ != 1) // Order-1 check | |
566 return NULL; | |
567 | |
568 in_sz = ((in[0])<<0) | ((in[1])<<8) | ((in[2])<<16) | ((in[3])<<24); | |
569 out_sz = ((in[4])<<0) | ((in[5])<<8) | ((in[6])<<16) | ((in[7])<<24); | |
570 if (in_sz != in_size-9) | |
571 return NULL; | |
572 | |
573 out_buf = malloc(out_sz); | |
574 if (!out_buf) | |
575 return NULL; | |
576 | |
577 //fprintf(stderr, "out_sz=%d\n", out_sz); | |
578 | |
579 //i = *cp++; | |
580 rle_i = 0; | |
581 i = *cp++; | |
582 do { | |
583 rle_j = x = 0; | |
584 j = *cp++; | |
585 do { | |
586 if ((D[i].fc[j].F = *cp++) >= 128) { | |
587 D[i].fc[j].F &= ~128; | |
588 D[i].fc[j].F = ((D[i].fc[j].F & 127) << 8) | *cp++; | |
589 } | |
590 D[i].fc[j].C = x; | |
591 | |
592 //fprintf(stderr, "i=%d j=%d F=%d C=%d\n", i, j, D[i].fc[j].F, D[i].fc[j].C); | |
593 | |
594 if (!D[i].fc[j].F) | |
595 D[i].fc[j].F = TOTFREQ; | |
596 | |
597 RansDecSymbolInit(&syms[i][j], D[i].fc[j].C, D[i].fc[j].F); | |
598 | |
599 /* Build reverse lookup table */ | |
600 if (!D[i].R) D[i].R = (unsigned char *)malloc(TOTFREQ); | |
601 memset(&D[i].R[x], j, D[i].fc[j].F); | |
602 | |
603 x += D[i].fc[j].F; | |
604 assert(x <= TOTFREQ); | |
605 | |
606 if (!rle_j && j+1 == *cp) { | |
607 j = *cp++; | |
608 rle_j = *cp++; | |
609 } else if (rle_j) { | |
610 rle_j--; | |
611 j++; | |
612 } else { | |
613 j = *cp++; | |
614 } | |
615 } while(j); | |
616 | |
617 if (!rle_i && i+1 == *cp) { | |
618 i = *cp++; | |
619 rle_i = *cp++; | |
620 } else if (rle_i) { | |
621 rle_i--; | |
622 i++; | |
623 } else { | |
624 i = *cp++; | |
625 } | |
626 } while (i); | |
627 | |
628 // Precompute reverse lookup of frequency. | |
629 | |
630 RansState rans0, rans1, rans2, rans3; | |
631 uint8_t *ptr = cp; | |
632 RansDecInit(&rans0, &ptr); | |
633 RansDecInit(&rans1, &ptr); | |
634 RansDecInit(&rans2, &ptr); | |
635 RansDecInit(&rans3, &ptr); | |
636 | |
637 int isz4 = out_sz>>2; | |
638 int l0 = 0; | |
639 int l1 = 0; | |
640 int l2 = 0; | |
641 int l3 = 0; | |
642 int i4[] = {0*isz4, 1*isz4, 2*isz4, 3*isz4}; | |
643 | |
644 RansState R[4]; | |
645 R[0] = rans0; | |
646 R[1] = rans1; | |
647 R[2] = rans2; | |
648 R[3] = rans3; | |
649 | |
650 for (; i4[0] < isz4; i4[0]++, i4[1]++, i4[2]++, i4[3]++) { | |
651 uint32_t m[4] = {R[0] & ((1u << TF_SHIFT)-1), | |
652 R[1] & ((1u << TF_SHIFT)-1), | |
653 R[2] & ((1u << TF_SHIFT)-1), | |
654 R[3] & ((1u << TF_SHIFT)-1)}; | |
655 | |
656 uint8_t c[4] = {D[l0].R[m[0]], | |
657 D[l1].R[m[1]], | |
658 D[l2].R[m[2]], | |
659 D[l3].R[m[3]]}; | |
660 | |
661 out_buf[i4[0]] = c[0]; | |
662 out_buf[i4[1]] = c[1]; | |
663 out_buf[i4[2]] = c[2]; | |
664 out_buf[i4[3]] = c[3]; | |
665 | |
666 //RansDecAdvanceSymbolStep(&R[0], &syms[l0][c[0]], TF_SHIFT); | |
667 //RansDecAdvanceSymbolStep(&R[1], &syms[l1][c[1]], TF_SHIFT); | |
668 //RansDecAdvanceSymbolStep(&R[2], &syms[l2][c[2]], TF_SHIFT); | |
669 //RansDecAdvanceSymbolStep(&R[3], &syms[l3][c[3]], TF_SHIFT); | |
670 | |
671 R[0] = syms[l0][c[0]].freq * (R[0]>>TF_SHIFT); | |
672 R[1] = syms[l1][c[1]].freq * (R[1]>>TF_SHIFT); | |
673 R[2] = syms[l2][c[2]].freq * (R[2]>>TF_SHIFT); | |
674 R[3] = syms[l3][c[3]].freq * (R[3]>>TF_SHIFT); | |
675 | |
676 R[0] += m[0] - syms[l0][c[0]].start; | |
677 R[1] += m[1] - syms[l1][c[1]].start; | |
678 R[2] += m[2] - syms[l2][c[2]].start; | |
679 R[3] += m[3] - syms[l3][c[3]].start; | |
680 | |
681 RansDecRenorm(&R[0], &ptr); | |
682 RansDecRenorm(&R[1], &ptr); | |
683 RansDecRenorm(&R[2], &ptr); | |
684 RansDecRenorm(&R[3], &ptr); | |
685 | |
686 l0 = c[0]; | |
687 l1 = c[1]; | |
688 l2 = c[2]; | |
689 l3 = c[3]; | |
690 } | |
691 | |
692 rans0 = R[0]; | |
693 rans1 = R[1]; | |
694 rans2 = R[2]; | |
695 rans3 = R[3]; | |
696 | |
697 // Remainder | |
698 for (; i4[3] < out_sz; i4[3]++) { | |
699 unsigned char c3 = D[l3].R[RansDecGet(&rans3, TF_SHIFT)]; | |
700 out_buf[i4[3]] = c3; | |
701 RansDecAdvanceSymbol(&rans3, &ptr, &syms[l3][c3], TF_SHIFT); | |
702 l3 = c3; | |
703 } | |
704 | |
705 *out_size = out_sz; | |
706 | |
707 for (i = 0; i < 256; i++) | |
708 if (D[i].R) free(D[i].R); | |
709 | |
710 return (unsigned char *)out_buf; | |
711 } | |
712 | |
713 /*----------------------------------------------------------------------------- | |
714 * Simple interface to the order-0 vs order-1 encoders and decoders. | |
715 */ | |
716 unsigned char *rans_compress(unsigned char *in, unsigned int in_size, | |
717 unsigned int *out_size, int order) { | |
718 return order | |
719 ? rans_compress_O1(in, in_size, out_size) | |
720 : rans_compress_O0(in, in_size, out_size); | |
721 } | |
722 | |
723 unsigned char *rans_uncompress(unsigned char *in, unsigned int in_size, | |
724 unsigned int *out_size) { | |
725 return in[0] | |
726 ? rans_uncompress_O1(in, in_size, out_size) | |
727 : rans_uncompress_O0(in, in_size, out_size); | |
728 } | |
729 | |
730 | |
731 #ifdef TEST_MAIN | |
732 /*----------------------------------------------------------------------------- | |
733 * Main. | |
734 * | |
735 * This is a simple command line tool for testing order-0 and order-1 | |
736 * compression using the rANS codec. Simply compile with | |
737 * | |
738 * gcc -DTEST_MAIN -O3 -I. cram/rANS_static.c -o cram/rANS_static | |
739 * | |
740 * Usage: cram/rANS_static -o0 < file > file.o0 | |
741 * cram/rANS_static -d < file.o0 > file2 | |
742 * | |
743 * cram/rANS_static -o1 < file > file.o1 | |
744 * cram/rANS_static -d < file.o1 > file2 | |
745 */ | |
746 int main(int argc, char **argv) { | |
747 int opt, order = 0; | |
748 unsigned char in_buf[BLK_SIZE2+257*257*3]; | |
749 int decode = 0; | |
750 FILE *infp = stdin, *outfp = stdout; | |
751 struct timeval tv1, tv2; | |
752 size_t bytes = 0; | |
753 | |
754 extern char *optarg; | |
755 extern int optind; | |
756 | |
757 while ((opt = getopt(argc, argv, "o:d")) != -1) { | |
758 switch (opt) { | |
759 case 'o': | |
760 order = atoi(optarg); | |
761 break; | |
762 | |
763 case 'd': | |
764 decode = 1; | |
765 break; | |
766 } | |
767 } | |
768 | |
769 order = order ? 1 : 0; // Only support O(0) and O(1) | |
770 | |
771 if (optind < argc) { | |
772 if (!(infp = fopen(argv[optind], "rb"))) { | |
773 perror(argv[optind]); | |
774 return 1; | |
775 } | |
776 optind++; | |
777 } | |
778 | |
779 if (optind < argc) { | |
780 if (!(outfp = fopen(argv[optind], "wb"))) { | |
781 perror(argv[optind]); | |
782 return 1; | |
783 } | |
784 optind++; | |
785 } | |
786 | |
787 gettimeofday(&tv1, NULL); | |
788 | |
789 if (decode) { | |
790 // Only used in some test implementations of RC_GetFreq() | |
791 //RC_init(); | |
792 //RC_init2(); | |
793 | |
794 for (;;) { | |
795 uint32_t in_size, out_size; | |
796 unsigned char *out; | |
797 | |
798 if (4 != fread(&in_size, 1, 4, infp)) | |
799 break; | |
800 if (in_size != fread(in_buf, 1, in_size, infp)) { | |
801 fprintf(stderr, "Truncated input\n"); | |
802 exit(1); | |
803 } | |
804 out = rans_uncompress(in_buf, in_size, &out_size); | |
805 if (!out) | |
806 abort(); | |
807 | |
808 fwrite(out, 1, out_size, outfp); | |
809 free(out); | |
810 | |
811 bytes += out_size; | |
812 } | |
813 } else { | |
814 for (;;) { | |
815 uint32_t in_size, out_size; | |
816 unsigned char *out; | |
817 | |
818 in_size = fread(in_buf, 1, BLK_SIZE, infp); | |
819 if (in_size <= 0) | |
820 break; | |
821 | |
822 out = rans_compress(in_buf, in_size, &out_size, order); | |
823 | |
824 fwrite(&out_size, 1, 4, outfp); | |
825 fwrite(out, 1, out_size, outfp); | |
826 free(out); | |
827 | |
828 bytes += in_size; | |
829 } | |
830 } | |
831 | |
832 gettimeofday(&tv2, NULL); | |
833 | |
834 fprintf(stderr, "Took %ld microseconds, %5.1f MB/s\n", | |
835 (long)(tv2.tv_sec - tv1.tv_sec)*1000000 + | |
836 tv2.tv_usec - tv1.tv_usec, | |
837 (double)bytes / ((long)(tv2.tv_sec - tv1.tv_sec)*1000000 + | |
838 tv2.tv_usec - tv1.tv_usec)); | |
839 return 0; | |
840 } | |
841 #endif |