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
);