1 /* This code is part of the tng compression routines.
3 * Written by Daniel Spangberg and Magnus Lundborg
4 * Copyright (c) 2010, 2013-2014 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 while (coder_inst->pack_temporary_bits>=8)
51 coder_inst->pack_temporary_bits-=8;
52 mask=~(0xFFU<<(coder_inst->pack_temporary_bits));
53 out=(unsigned char)(coder_inst->pack_temporary>>(coder_inst->pack_temporary_bits));
56 coder_inst->pack_temporary&=mask;
60 void DECLSPECDLLEXPORT Ptngc_write_pattern(struct coder *coder_inst, unsigned int pattern,
61 int nbits, unsigned char **output)
63 unsigned int mask1,mask2;
66 coder_inst->pack_temporary<<=nbits; /* Make room for new data. */
67 coder_inst->pack_temporary_bits+=nbits;
71 coder_inst->pack_temporary|=mask2;
76 Ptngc_out8bits(coder_inst,output);
79 /* Write up to 24 bits */
80 TNG_INLINE void DECLSPECDLLEXPORT Ptngc_writebits(struct coder *coder_inst,
81 unsigned int value, const int nbits,
82 unsigned char **output_ptr)
84 /* Make room for the bits. */
85 coder_inst->pack_temporary<<=nbits;
86 coder_inst->pack_temporary_bits+=nbits;
87 coder_inst->pack_temporary|=value;
88 Ptngc_out8bits(coder_inst,output_ptr);
91 /* Write up to 32 bits */
92 void DECLSPECDLLEXPORT Ptngc_write32bits(struct coder *coder_inst, unsigned int value,
93 int nbits, unsigned char **output_ptr)
97 mask=0xFFU<<(nbits-8);
99 mask=0xFFU>>(8-nbits);
102 /* Make room for the bits. */
104 coder_inst->pack_temporary<<=8;
105 coder_inst->pack_temporary_bits+=8;
106 coder_inst->pack_temporary|=(value&mask)>>(nbits);
107 Ptngc_out8bits(coder_inst,output_ptr);
111 Ptngc_writebits(coder_inst,value&mask,nbits,output_ptr);
114 /* Write "arbitrary" number of bits */
115 void DECLSPECDLLEXPORT Ptngc_writemanybits(struct coder *coder_inst, unsigned char *value,
116 int nbits, unsigned char **output_ptr)
121 unsigned int v=((((unsigned int)value[vptr])<<16)|
122 (((unsigned int)value[vptr+1])<<8)|
123 (((unsigned int)value[vptr+2])));
124 Ptngc_writebits(coder_inst,v,24,output_ptr);
130 Ptngc_writebits(coder_inst,(unsigned int)value[vptr],8,output_ptr);
136 Ptngc_writebits(coder_inst,(unsigned int)value[vptr],nbits,output_ptr);
140 static int write_stop_bit_code(struct coder *coder_inst, unsigned int s,
141 unsigned int coding_parameter,
142 unsigned char **output)
145 unsigned int extract=~(0xffffffffU<<coding_parameter);
146 unsigned int this=(s&extract)<<1;
147 s>>=coding_parameter;
151 coder_inst->stat_overflow++;
153 coder_inst->pack_temporary<<=(coding_parameter+1);
154 coder_inst->pack_temporary_bits+=coding_parameter+1;
155 coder_inst->pack_temporary|=this;
156 Ptngc_out8bits(coder_inst,output);
159 coding_parameter>>=1;
160 if (coding_parameter<1)
164 coder_inst->stat_numval++;
168 static int pack_stopbits_item(struct coder *coder_inst, const int item,
169 unsigned char **output, const int coding_parameter)
171 /* Find this symbol in table. */
177 return write_stop_bit_code(coder_inst,s,coding_parameter,output);
180 static int pack_triplet(struct coder *coder_inst, unsigned int *s,
181 unsigned char **output, const int coding_parameter,
182 const unsigned int max_base, const int maxbits)
184 /* Determine base for this triplet. */
185 unsigned int min_base=1U<<coding_parameter;
186 unsigned int this_base=min_base;
188 unsigned int jbase=0;
189 unsigned int bits_per_value;
191 while (s[i]>=this_base)
196 bits_per_value=coding_parameter+jbase;
199 if (this_base>max_base)
201 bits_per_value=maxbits;
204 /* 2 bits selects the base */
205 coder_inst->pack_temporary<<=2;
206 coder_inst->pack_temporary_bits+=2;
207 coder_inst->pack_temporary|=jbase;
208 Ptngc_out8bits(coder_inst,output);
210 Ptngc_write32bits(coder_inst,s[i],bits_per_value,output);
214 void DECLSPECDLLEXPORT Ptngc_pack_flush(struct coder *coder_inst, unsigned char **output)
216 /* Zero-fill just enough. */
217 if (coder_inst->pack_temporary_bits>0)
218 Ptngc_write_pattern(coder_inst,0,8-coder_inst->pack_temporary_bits,output);
221 unsigned char DECLSPECDLLEXPORT *Ptngc_pack_array(struct coder *coder_inst,
222 int *input, int *length, const int coding,
223 const int coding_parameter, const int natoms, const int speed)
225 if ((coding==TNG_COMPRESS_ALGO_BWLZH1) || (coding==TNG_COMPRESS_ALGO_BWLZH2))
227 unsigned char *output=warnmalloc(4+bwlzh_get_buflen(*length));
229 unsigned int *pval=warnmalloc(n*sizeof *pval);
230 int nframes=n/natoms/3;
232 int most_negative=2147483647;
234 if (input[i]<most_negative)
235 most_negative=input[i];
236 most_negative=-most_negative;
237 output[0]=((unsigned int)most_negative)&0xFFU;
238 output[1]=(((unsigned int)most_negative)>>8)&0xFFU;
239 output[2]=(((unsigned int)most_negative)>>16)&0xFFU;
240 output[3]=(((unsigned int)most_negative)>>24)&0xFFU;
241 for (i=0; i<natoms; i++)
243 for (k=0; k<nframes; k++)
245 int item=input[k*3*natoms+i*3+j];
246 pval[cnt++]=(unsigned int)(item+most_negative);
249 bwlzh_compress(pval,n,output+4,length);
251 bwlzh_compress_no_lz77(pval,n,output+4,length);
256 else if (coding==TNG_COMPRESS_ALGO_POS_XTC3)
257 return Ptngc_pack_array_xtc3(input,length,natoms,speed);
258 else if (coding==TNG_COMPRESS_ALGO_POS_XTC2)
259 return Ptngc_pack_array_xtc2(coder_inst,input,length);
262 unsigned char *output=NULL;
263 unsigned char *output_ptr=NULL;
267 coder_inst->stat_numval=0;
268 coder_inst->stat_overflow=0;
269 /* Allocate enough memory for output */
270 output=warnmalloc(8* *length*sizeof *output);
272 if ((coding==TNG_COMPRESS_ALGO_TRIPLET) ||
273 (coding==TNG_COMPRESS_ALGO_POS_TRIPLET_INTRA) ||
274 (coding==TNG_COMPRESS_ALGO_POS_TRIPLET_ONETOONE))
277 int ntriplets=*length/3;
278 /* Determine max base and maxbits */
279 unsigned int max_base=1U<<coding_parameter;
280 unsigned int maxbits=coding_parameter;
281 unsigned int intmax=0;
282 for (i=0; i<*length; i++)
294 coder_inst->pack_temporary_bits=32;
295 coder_inst->pack_temporary=intmax;
296 Ptngc_out8bits(coder_inst,&output_ptr);
297 while (intmax>=max_base)
302 for (i=0; i<ntriplets; i++)
308 int item=input[i*3+j];
309 /* Find this symbol in table. */
316 if (pack_triplet(coder_inst, s, &output_ptr,
317 coding_parameter, max_base,maxbits))
325 for (i=0; i<*length; i++)
326 if (pack_stopbits_item(coder_inst,input[i],&output_ptr,coding_parameter))
331 Ptngc_pack_flush(coder_inst,&output_ptr);
332 output_length=(int)(output_ptr-output);
333 *length=output_length;
338 static int unpack_array_stop_bits(struct coder *coder_inst,
339 unsigned char *packed,int *output,
340 const int length, const int coding_parameter)
343 unsigned int extract_mask=0x80;
344 unsigned char *ptr=packed;
346 for (i=0; i<length; i++)
348 unsigned int pattern=0;
349 int numbits=coding_parameter;
352 unsigned int insert_mask=1U<<(numbits-1);
353 int inserted_bits=numbits;
355 for (j=0; j<numbits; j++)
357 bit=*ptr & extract_mask;
359 pattern|=insert_mask;
369 bit=*ptr & extract_mask;
381 inserted_bits+=numbits;
382 insert_mask=1U<<(inserted_bits-1);
393 static int unpack_array_triplet(struct coder *coder_inst,
394 unsigned char *packed, int *output,
395 int length, const int coding_parameter)
398 unsigned int extract_mask=0x80;
399 unsigned char *ptr=packed;
400 /* Determine max base and maxbits */
401 unsigned int max_base=1U<<coding_parameter;
402 unsigned int maxbits=coding_parameter;
406 intmax=((unsigned int)ptr[0])<<24|
407 ((unsigned int)ptr[1])<<16|
408 ((unsigned int)ptr[2])<<8|
409 ((unsigned int)ptr[3]);
411 while (intmax>=max_base)
417 for (i=0; i<length; i++)
420 unsigned int jbase=0;
421 unsigned int numbits;
425 bit=*ptr & extract_mask;
439 numbits=coding_parameter+jbase;
444 unsigned int pattern=0;
445 for (jbit=0; jbit<numbits; jbit++)
447 bit=*ptr & extract_mask;
467 static int unpack_array_bwlzh(struct coder *coder_inst,
468 unsigned char *packed, int *output,
469 const int length, const int natoms)
472 unsigned int *pval=warnmalloc(n*sizeof *pval);
473 int nframes=n/natoms/3;
475 int most_negative=(int)(((unsigned int)packed[0]) |
476 (((unsigned int)packed[1])<<8) |
477 (((unsigned int)packed[2])<<16) |
478 (((unsigned int)packed[3])<<24));
480 bwlzh_decompress(packed+4,length,pval);
481 for (i=0; i<natoms; i++)
483 for (k=0; k<nframes; k++)
485 unsigned int s=pval[cnt++];
486 output[k*3*natoms+i*3+j]=(int)s-most_negative;
492 int DECLSPECDLLEXPORT Ptngc_unpack_array(struct coder *coder_inst,
493 unsigned char *packed, int *output,
494 const int length, const int coding, const int coding_parameter,
497 if ((coding==TNG_COMPRESS_ALGO_STOPBIT) ||
498 (coding==TNG_COMPRESS_ALGO_VEL_STOPBIT_INTER))
499 return unpack_array_stop_bits(coder_inst, packed, output, length, coding_parameter);
500 else if ((coding==TNG_COMPRESS_ALGO_TRIPLET) ||
501 (coding==TNG_COMPRESS_ALGO_POS_TRIPLET_INTRA) ||
502 (coding==TNG_COMPRESS_ALGO_POS_TRIPLET_ONETOONE))
503 return unpack_array_triplet(coder_inst, packed, output, length, coding_parameter);
504 else if (coding==TNG_COMPRESS_ALGO_POS_XTC2)
505 return Ptngc_unpack_array_xtc2(coder_inst, packed, output, length);
506 else if ((coding==TNG_COMPRESS_ALGO_BWLZH1) || (coding==TNG_COMPRESS_ALGO_BWLZH2))
507 return unpack_array_bwlzh(coder_inst, packed, output, length,natoms);
508 else if (coding==TNG_COMPRESS_ALGO_POS_XTC3)
509 return Ptngc_unpack_array_xtc3(packed, output, length,natoms);