1 /* This code is part of the tng compression routines.
3 * Written by Daniel Spangberg
4 * Copyright (c) 2010, 2013, The GROMACS development team.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the Revised BSD License.
14 #include "../../include/compression/tng_compress.h"
15 #include "../../include/compression/bwlzh.h"
16 #include "../../include/compression/coder.h"
17 #include "../../include/compression/warnmalloc.h"
20 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
23 #endif /* not defined USE_WINDOWS */
26 #define TNG_INLINE __inline
27 #define TNG_SNPRINTF _snprintf
29 #define TNG_INLINE inline
30 #define TNG_SNPRINTF snprintf
33 struct coder DECLSPECDLLEXPORT *Ptngc_coder_init(void)
35 struct coder *coder_inst=warnmalloc(sizeof *coder_inst);
36 coder_inst->pack_temporary_bits=0;
40 void DECLSPECDLLEXPORT Ptngc_coder_deinit(struct coder *coder_inst)
45 TNG_INLINE void DECLSPECDLLEXPORT Ptngc_out8bits(struct coder *coder_inst, unsigned char **output)
47 int pack_temporary_bits=coder_inst->pack_temporary_bits;
48 unsigned int pack_temporary=coder_inst->pack_temporary;
49 while (pack_temporary_bits>=8)
51 unsigned int mask=~(0xFFU<<(pack_temporary_bits-8));
52 unsigned char out=(unsigned char)(pack_temporary>>(pack_temporary_bits-8));
55 pack_temporary_bits-=8;
58 coder_inst->pack_temporary_bits=pack_temporary_bits;
59 coder_inst->pack_temporary=pack_temporary;
62 void DECLSPECDLLEXPORT Ptngc_write_pattern(struct coder *coder_inst, unsigned int pattern,
63 int nbits, unsigned char **output)
65 unsigned int mask1,mask2;
68 coder_inst->pack_temporary<<=nbits; /* Make room for new data. */
69 coder_inst->pack_temporary_bits+=nbits;
73 coder_inst->pack_temporary|=mask2;
78 Ptngc_out8bits(coder_inst,output);
81 /* Write up to 24 bits */
82 TNG_INLINE void DECLSPECDLLEXPORT Ptngc_writebits(struct coder *coder_inst,
83 unsigned int value, int nbits,
84 unsigned char **output_ptr)
86 /* Make room for the bits. */
87 coder_inst->pack_temporary<<=nbits;
88 coder_inst->pack_temporary_bits+=nbits;
89 coder_inst->pack_temporary|=value;
90 Ptngc_out8bits(coder_inst,output_ptr);
93 /* Write up to 32 bits */
94 void DECLSPECDLLEXPORT Ptngc_write32bits(struct coder *coder_inst,unsigned int value,
95 int nbits, unsigned char **output_ptr)
99 mask=0xFFU<<(nbits-8);
101 mask=0xFFU>>(8-nbits);
104 /* Make room for the bits. */
105 coder_inst->pack_temporary<<=8;
106 coder_inst->pack_temporary_bits+=8;
107 coder_inst->pack_temporary|=(value&mask)>>(nbits-8);
108 Ptngc_out8bits(coder_inst,output_ptr);
113 Ptngc_writebits(coder_inst,value&mask,nbits,output_ptr);
116 /* Write "arbitrary" number of bits */
117 void DECLSPECDLLEXPORT Ptngc_writemanybits(struct coder *coder_inst, unsigned char *value,
118 int nbits, unsigned char **output_ptr)
123 unsigned int v=((((unsigned int)value[vptr])<<16)|
124 (((unsigned int)value[vptr+1])<<8)|
125 (((unsigned int)value[vptr+2])));
126 Ptngc_writebits(coder_inst,v,24,output_ptr);
132 Ptngc_writebits(coder_inst,(unsigned int)value[vptr],8,output_ptr);
138 Ptngc_writebits(coder_inst,(unsigned int)value[vptr],nbits,output_ptr);
142 static int write_stop_bit_code(struct coder *coder_inst, unsigned int s,
143 unsigned int coding_parameter,
144 unsigned char **output)
147 unsigned int extract=~(0xffffffffU<<coding_parameter);
148 unsigned int this=(s&extract)<<1;
149 s>>=coding_parameter;
153 coder_inst->stat_overflow++;
155 coder_inst->pack_temporary<<=(coding_parameter+1);
156 coder_inst->pack_temporary_bits+=coding_parameter+1;
157 coder_inst->pack_temporary|=this;
158 Ptngc_out8bits(coder_inst,output);
161 coding_parameter>>=1;
162 if (coding_parameter<1)
166 coder_inst->stat_numval++;
170 static int pack_stopbits_item(struct coder *coder_inst,int item,
171 unsigned char **output, int coding_parameter)
173 /* Find this symbol in table. */
179 return write_stop_bit_code(coder_inst,s,coding_parameter,output);
182 static int pack_triplet(struct coder *coder_inst, unsigned int *s,
183 unsigned char **output, int coding_parameter,
184 unsigned int max_base, int maxbits)
186 /* Determine base for this triplet. */
187 unsigned int min_base=1U<<coding_parameter;
188 unsigned int this_base=min_base;
190 unsigned int jbase=0;
191 unsigned int bits_per_value;
193 while (s[i]>=this_base)
198 bits_per_value=coding_parameter+jbase;
201 if (this_base>max_base)
203 bits_per_value=maxbits;
206 /* 2 bits selects the base */
207 coder_inst->pack_temporary<<=2;
208 coder_inst->pack_temporary_bits+=2;
209 coder_inst->pack_temporary|=jbase;
210 Ptngc_out8bits(coder_inst,output);
212 Ptngc_write32bits(coder_inst,s[i],bits_per_value,output);
216 void DECLSPECDLLEXPORT Ptngc_pack_flush(struct coder *coder_inst,unsigned char **output)
218 /* Zero-fill just enough. */
219 if (coder_inst->pack_temporary_bits>0)
220 Ptngc_write_pattern(coder_inst,0,8-coder_inst->pack_temporary_bits,output);
223 unsigned char DECLSPECDLLEXPORT *Ptngc_pack_array(struct coder *coder_inst,
224 int *input, int *length, int coding,
225 int coding_parameter, int natoms, int speed)
227 if ((coding==TNG_COMPRESS_ALGO_BWLZH1) || (coding==TNG_COMPRESS_ALGO_BWLZH2))
229 unsigned char *output=warnmalloc(4+bwlzh_get_buflen(*length));
231 unsigned int *pval=warnmalloc(n*sizeof *pval);
232 int nframes=n/natoms/3;
234 int most_negative=2147483647;
236 if (input[i]<most_negative)
237 most_negative=input[i];
238 most_negative=-most_negative;
239 output[0]=((unsigned int)most_negative)&0xFFU;
240 output[1]=(((unsigned int)most_negative)>>8)&0xFFU;
241 output[2]=(((unsigned int)most_negative)>>16)&0xFFU;
242 output[3]=(((unsigned int)most_negative)>>24)&0xFFU;
243 for (i=0; i<natoms; i++)
245 for (k=0; k<nframes; k++)
247 int item=input[k*3*natoms+i*3+j];
248 pval[cnt++]=(unsigned int)(item+most_negative);
252 bwlzh_compress(pval,n,output+4,length);
254 bwlzh_compress_no_lz77(pval,n,output+4,length);
259 else if (coding==TNG_COMPRESS_ALGO_POS_XTC3)
260 return Ptngc_pack_array_xtc3(input,length,natoms,speed);
261 else if (coding==TNG_COMPRESS_ALGO_POS_XTC2)
262 return Ptngc_pack_array_xtc2(coder_inst,input,length);
265 unsigned char *output=NULL;
266 unsigned char *output_ptr=NULL;
270 coder_inst->stat_numval=0;
271 coder_inst->stat_overflow=0;
272 /* Allocate enough memory for output */
273 output=warnmalloc(8* *length*sizeof *output);
275 if ((coding==TNG_COMPRESS_ALGO_TRIPLET) ||
276 (coding==TNG_COMPRESS_ALGO_POS_TRIPLET_INTRA) ||
277 (coding==TNG_COMPRESS_ALGO_POS_TRIPLET_ONETOONE))
280 int ntriplets=*length/3;
281 /* Determine max base and maxbits */
282 unsigned int max_base=1U<<coding_parameter;
283 unsigned int maxbits=coding_parameter;
284 unsigned int intmax=0;
285 for (i=0; i<*length; i++)
297 coder_inst->pack_temporary_bits=32;
298 coder_inst->pack_temporary=intmax;
299 Ptngc_out8bits(coder_inst,&output_ptr);
300 while (intmax>=max_base)
305 for (i=0; i<ntriplets; i++)
311 int item=input[i*3+j];
312 /* Find this symbol in table. */
319 if (pack_triplet(coder_inst, s, &output_ptr,
320 coding_parameter, max_base,maxbits))
328 for (i=0; i<*length; i++)
329 if (pack_stopbits_item(coder_inst,input[i],&output_ptr,coding_parameter))
334 Ptngc_pack_flush(coder_inst,&output_ptr);
335 output_length=(int)(output_ptr-output);
336 *length=output_length;
341 static int unpack_array_stop_bits(struct coder *coder_inst,
342 unsigned char *packed,int *output,
343 int length, int coding_parameter)
346 unsigned int extract_mask=0x80;
347 unsigned char *ptr=packed;
349 for (i=0; i<length; i++)
351 unsigned int pattern=0;
352 int numbits=coding_parameter;
355 unsigned int insert_mask=1U<<(numbits-1);
356 int inserted_bits=numbits;
358 for (j=0; j<numbits; j++)
360 bit=*ptr & extract_mask;
362 pattern|=insert_mask;
372 bit=*ptr & extract_mask;
384 inserted_bits+=numbits;
385 insert_mask=1U<<(inserted_bits-1);
396 static int unpack_array_triplet(struct coder *coder_inst,
397 unsigned char *packed, int *output,
398 int length, int coding_parameter)
401 unsigned int extract_mask=0x80;
402 unsigned char *ptr=packed;
403 /* Determine max base and maxbits */
404 unsigned int max_base=1U<<coding_parameter;
405 unsigned int maxbits=coding_parameter;
409 intmax=((unsigned int)ptr[0])<<24|
410 ((unsigned int)ptr[1])<<16|
411 ((unsigned int)ptr[2])<<8|
412 ((unsigned int)ptr[3]);
414 while (intmax>=max_base)
420 for (i=0; i<length; i++)
423 unsigned int jbase=0;
424 unsigned int numbits;
428 bit=*ptr & extract_mask;
442 numbits=coding_parameter+jbase;
447 unsigned int pattern=0;
448 for (jbit=0; jbit<numbits; jbit++)
450 bit=*ptr & extract_mask;
470 static int unpack_array_bwlzh(struct coder *coder_inst,
471 unsigned char *packed, int *output,
472 int length, int natoms)
475 unsigned int *pval=warnmalloc(n*sizeof *pval);
476 int nframes=n/natoms/3;
478 int most_negative=(int)(((unsigned int)packed[0]) |
479 (((unsigned int)packed[1])<<8) |
480 (((unsigned int)packed[2])<<16) |
481 (((unsigned int)packed[3])<<24));
483 bwlzh_decompress(packed+4,length,pval);
484 for (i=0; i<natoms; i++)
486 for (k=0; k<nframes; k++)
488 unsigned int s=pval[cnt++];
489 output[k*3*natoms+i*3+j]=(int)s-most_negative;
495 int DECLSPECDLLEXPORT Ptngc_unpack_array(struct coder *coder_inst,
496 unsigned char *packed, int *output,
497 int length, int coding, int coding_parameter,
500 if ((coding==TNG_COMPRESS_ALGO_STOPBIT) ||
501 (coding==TNG_COMPRESS_ALGO_VEL_STOPBIT_INTER))
502 return unpack_array_stop_bits(coder_inst, packed, output, length, coding_parameter);
503 else if ((coding==TNG_COMPRESS_ALGO_TRIPLET) ||
504 (coding==TNG_COMPRESS_ALGO_POS_TRIPLET_INTRA) ||
505 (coding==TNG_COMPRESS_ALGO_POS_TRIPLET_ONETOONE))
506 return unpack_array_triplet(coder_inst, packed, output, length, coding_parameter);
507 else if (coding==TNG_COMPRESS_ALGO_POS_XTC2)
508 return Ptngc_unpack_array_xtc2(coder_inst, packed, output, length);
509 else if ((coding==TNG_COMPRESS_ALGO_BWLZH1) || (coding==TNG_COMPRESS_ALGO_BWLZH2))
510 return unpack_array_bwlzh(coder_inst, packed, output, length,natoms);
511 else if (coding==TNG_COMPRESS_ALGO_POS_XTC3)
512 return Ptngc_unpack_array_xtc3(packed, output, length,natoms);