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 |
