Moved gromacs module from mdevaluate to pygmx
This commit is contained in:
351
pygmx/gromacs/compression.c
Normal file
351
pygmx/gromacs/compression.c
Normal file
@ -0,0 +1,351 @@
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
extern void test(int *b) {
|
||||
b[0] = 1;
|
||||
b[1] = 0;
|
||||
b[2] = 2;
|
||||
}
|
||||
|
||||
static const int magicints[] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
|
||||
80, 101, 128, 161, 203, 256, 322, 406, 512, 645, 812, 1024, 1290,
|
||||
1625, 2048, 2580, 3250, 4096, 5060, 6501, 8192, 10321, 13003,
|
||||
16384, 20642, 26007, 32768, 41285, 52015, 65536,82570, 104031,
|
||||
131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,
|
||||
832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021,
|
||||
4194304, 5284491, 6658042, 8388607, 10568983, 13316085, 16777216
|
||||
};
|
||||
|
||||
#define FIRSTIDX 9
|
||||
/* note that magicints[FIRSTIDX-1] == 0 */
|
||||
#define LASTIDX (sizeof(magicints) / sizeof(*magicints))
|
||||
|
||||
/* Internal support routines for reading/writing compressed coordinates
|
||||
* sizeofint - calculate smallest number of bits necessary
|
||||
* to represent a certain integer.
|
||||
*/
|
||||
static int
|
||||
sizeofint(int size) {
|
||||
unsigned int num = 1;
|
||||
int num_of_bits = 0;
|
||||
|
||||
while (size >= num && num_of_bits < 32)
|
||||
{
|
||||
num_of_bits++;
|
||||
num <<= 1;
|
||||
}
|
||||
return num_of_bits;
|
||||
}
|
||||
|
||||
/*
|
||||
* sizeofints - calculate 'bitsize' of compressed ints
|
||||
*
|
||||
* given a number of small unsigned integers and the maximum value
|
||||
* return the number of bits needed to read or write them with the
|
||||
* routines encodeints/decodeints. You need this parameter when
|
||||
* calling those routines.
|
||||
* (However, in some cases we can just use the variable 'smallidx'
|
||||
* which is the exact number of bits, and them we dont need to call
|
||||
* this routine).
|
||||
*/
|
||||
static int
|
||||
sizeofints(int num_of_ints, unsigned int sizes[])
|
||||
{
|
||||
int i, num;
|
||||
unsigned int num_of_bytes, num_of_bits, bytes[32], bytecnt, tmp;
|
||||
num_of_bytes = 1;
|
||||
bytes[0] = 1;
|
||||
num_of_bits = 0;
|
||||
for (i=0; i < num_of_ints; i++)
|
||||
{
|
||||
tmp = 0;
|
||||
for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++)
|
||||
{
|
||||
tmp = bytes[bytecnt] * sizes[i] + tmp;
|
||||
bytes[bytecnt] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
}
|
||||
while (tmp != 0)
|
||||
{
|
||||
bytes[bytecnt++] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
}
|
||||
num_of_bytes = bytecnt;
|
||||
}
|
||||
num = 1;
|
||||
num_of_bytes--;
|
||||
while (bytes[num_of_bytes] >= num)
|
||||
{
|
||||
num_of_bits++;
|
||||
num *= 2;
|
||||
}
|
||||
return num_of_bits + num_of_bytes * 8;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* decodebits - decode number from buf using specified number of bits
|
||||
*
|
||||
* extract the number of bits from the array buf and construct an integer
|
||||
* from it. Return that value.
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
decodebits(int state[], int _buf[], int num_of_bits)
|
||||
{
|
||||
|
||||
int cnt, num;
|
||||
unsigned int lastbits, lastbyte;
|
||||
int mask = (1 << num_of_bits) -1;
|
||||
unsigned char * cbuf = (unsigned char *)_buf;
|
||||
cnt = state[0];
|
||||
lastbits = (unsigned int) state[1];
|
||||
lastbyte = (unsigned int) state[2];
|
||||
|
||||
num = 0;
|
||||
while (num_of_bits >= 8)
|
||||
{
|
||||
lastbyte = ( lastbyte << 8 ) | cbuf[cnt++];
|
||||
num |= (lastbyte >> lastbits) << (num_of_bits - 8);
|
||||
num_of_bits -=8;
|
||||
}
|
||||
if (num_of_bits > 0)
|
||||
{
|
||||
if (lastbits < num_of_bits)
|
||||
{
|
||||
lastbits += 8;
|
||||
lastbyte = (lastbyte << 8) | cbuf[cnt++];
|
||||
}
|
||||
lastbits -= num_of_bits;
|
||||
num |= (lastbyte >> lastbits) & ((1 << num_of_bits) -1);
|
||||
}
|
||||
num &= mask;
|
||||
state[0] = cnt;
|
||||
state[1] = lastbits;
|
||||
state[2] = lastbyte;
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* decodeints - decode 'small' integers from the buf array
|
||||
*
|
||||
* this routine is the inverse from encodeints() and decodes the small integers
|
||||
* written to buf by calculating the remainder and doing divisions with
|
||||
* the given sizes[]. You need to specify the total number of bits to be
|
||||
* used from buf in num_of_bits.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
decodeints(int state[], int buf[], int num_of_ints, int num_of_bits,
|
||||
unsigned int sizes[], int nums[])
|
||||
{
|
||||
|
||||
int bytes[32];
|
||||
int i, j, num_of_bytes, p, num;
|
||||
|
||||
bytes[1] = bytes[2] = bytes[3] = 0;
|
||||
num_of_bytes = 0;
|
||||
while (num_of_bits > 8)
|
||||
{
|
||||
bytes[num_of_bytes++] = decodebits(state, buf, 8);
|
||||
num_of_bits -= 8;
|
||||
}
|
||||
if (num_of_bits > 0)
|
||||
{
|
||||
bytes[num_of_bytes++] = decodebits(state, buf, num_of_bits);
|
||||
}
|
||||
for (i = num_of_ints-1; i > 0; i--)
|
||||
{
|
||||
num = 0;
|
||||
for (j = num_of_bytes-1; j >=0; j--)
|
||||
{
|
||||
num = (num << 8) | bytes[j];
|
||||
p = num / sizes[i];
|
||||
bytes[j] = p;
|
||||
num = num - p * sizes[i];
|
||||
}
|
||||
nums[i] = num;
|
||||
}
|
||||
nums[0] = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
|
||||
}
|
||||
|
||||
extern int
|
||||
xdrfile_decompress_coord_float(float *coordinates,
|
||||
int size,
|
||||
float precision,
|
||||
int minint[3],
|
||||
int maxint[3],
|
||||
int smallidx,
|
||||
char* compressed_blob_,
|
||||
size_t blob_len,
|
||||
size_t * readed_len)
|
||||
{
|
||||
int *compressed_blob = (int*)compressed_blob_;
|
||||
int *lip;
|
||||
unsigned sizeint[3], sizesmall[3], bitsizeint[3], size3;
|
||||
int k, *buf1 , flag;
|
||||
int smallnum, smaller, i, is_smaller, run;
|
||||
float *lfp, inv_precision;
|
||||
int tmp, *thiscoord, prevcoord[3];
|
||||
unsigned int bitsize;
|
||||
|
||||
bitsizeint[0] = 0;
|
||||
bitsizeint[1] = 0;
|
||||
bitsizeint[2] = 0;
|
||||
|
||||
|
||||
size3 = size * 3;
|
||||
|
||||
if((buf1=(int *)malloc(sizeof(int)*size3))==NULL)
|
||||
{
|
||||
fprintf(stderr,"Cannot allocate memory for decompressing coordinates.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Dont bother with compression for three atoms or less */
|
||||
if(size<=9)
|
||||
{
|
||||
|
||||
// TODO...
|
||||
/* return number of coords, not floats */
|
||||
}
|
||||
|
||||
|
||||
sizeint[0] = maxint[0] - minint[0]+1;
|
||||
sizeint[1] = maxint[1] - minint[1]+1;
|
||||
sizeint[2] = maxint[2] - minint[2]+1;
|
||||
|
||||
/* check if one of the sizes is to big to be multiplied */
|
||||
if ((sizeint[0] | sizeint[1] | sizeint[2] ) > 0xffffff)
|
||||
{
|
||||
bitsizeint[0] = sizeofint(sizeint[0]);
|
||||
bitsizeint[1] = sizeofint(sizeint[1]);
|
||||
bitsizeint[2] = sizeofint(sizeint[2]);
|
||||
bitsize = 0; /* flag the use of large sizes */
|
||||
}
|
||||
else
|
||||
{
|
||||
bitsize = sizeofints(3, sizeint);
|
||||
}
|
||||
|
||||
|
||||
tmp = smallidx+8;
|
||||
tmp = smallidx-1;
|
||||
tmp = (FIRSTIDX>tmp) ? FIRSTIDX : tmp;
|
||||
smaller = magicints[tmp] / 2;
|
||||
smallnum = magicints[smallidx] / 2;
|
||||
sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx] ;
|
||||
|
||||
|
||||
lfp = coordinates;
|
||||
inv_precision = 1.0 / precision;
|
||||
run = 0;
|
||||
i = 0;
|
||||
lip = buf1;
|
||||
|
||||
int state[3] = {0,0,0};
|
||||
|
||||
while ( i < size )
|
||||
{
|
||||
thiscoord = (int *)(lip) + i * 3;
|
||||
|
||||
if (bitsize == 0)
|
||||
{
|
||||
thiscoord[0] = decodebits(state, compressed_blob, bitsizeint[0]);
|
||||
thiscoord[1] = decodebits(state, compressed_blob, bitsizeint[1]);
|
||||
thiscoord[2] = decodebits(state, compressed_blob, bitsizeint[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
decodeints(state, compressed_blob, 3, bitsize, sizeint, thiscoord);
|
||||
}
|
||||
|
||||
i++;
|
||||
thiscoord[0] += minint[0];
|
||||
thiscoord[1] += minint[1];
|
||||
thiscoord[2] += minint[2];
|
||||
|
||||
prevcoord[0] = thiscoord[0];
|
||||
prevcoord[1] = thiscoord[1];
|
||||
prevcoord[2] = thiscoord[2];
|
||||
|
||||
flag = decodebits(state, compressed_blob, 1);
|
||||
is_smaller = 0;
|
||||
if (flag == 1)
|
||||
{
|
||||
run = decodebits(state, compressed_blob, 5);
|
||||
is_smaller = run % 3;
|
||||
run -= is_smaller;
|
||||
is_smaller--;
|
||||
}
|
||||
if (run > 0)
|
||||
{
|
||||
thiscoord += 3;
|
||||
for (k = 0; k < run; k+=3)
|
||||
{
|
||||
decodeints(state, compressed_blob, 3, smallidx, sizesmall, thiscoord);
|
||||
i++;
|
||||
thiscoord[0] += prevcoord[0] - smallnum;
|
||||
thiscoord[1] += prevcoord[1] - smallnum;
|
||||
thiscoord[2] += prevcoord[2] - smallnum;
|
||||
if (k == 0) {
|
||||
/* interchange first with second atom for better
|
||||
* compression of water molecules
|
||||
*/
|
||||
tmp = thiscoord[0]; thiscoord[0] = prevcoord[0];
|
||||
prevcoord[0] = tmp;
|
||||
tmp = thiscoord[1]; thiscoord[1] = prevcoord[1];
|
||||
prevcoord[1] = tmp;
|
||||
tmp = thiscoord[2]; thiscoord[2] = prevcoord[2];
|
||||
prevcoord[2] = tmp;
|
||||
*lfp++ = prevcoord[0] * inv_precision;
|
||||
*lfp++ = prevcoord[1] * inv_precision;
|
||||
*lfp++ = prevcoord[2] * inv_precision;
|
||||
} else {
|
||||
prevcoord[0] = thiscoord[0];
|
||||
prevcoord[1] = thiscoord[1];
|
||||
prevcoord[2] = thiscoord[2];
|
||||
}
|
||||
*lfp++ = thiscoord[0] * inv_precision;
|
||||
*lfp++ = thiscoord[1] * inv_precision;
|
||||
*lfp++ = thiscoord[2] * inv_precision;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*lfp++ = thiscoord[0] * inv_precision;
|
||||
*lfp++ = thiscoord[1] * inv_precision;
|
||||
*lfp++ = thiscoord[2] * inv_precision;
|
||||
}
|
||||
smallidx += is_smaller;
|
||||
if (is_smaller < 0)
|
||||
{
|
||||
smallnum = smaller;
|
||||
|
||||
if (smallidx > FIRSTIDX)
|
||||
{
|
||||
smaller = magicints[smallidx - 1] /2;
|
||||
}
|
||||
else
|
||||
{
|
||||
smaller = 0;
|
||||
}
|
||||
}
|
||||
else if (is_smaller > 0)
|
||||
{
|
||||
smaller = smallnum;
|
||||
smallnum = magicints[smallidx] / 2;
|
||||
}
|
||||
sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx] ;
|
||||
}
|
||||
|
||||
free((void*)buf1);
|
||||
*readed_len = state[0];
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user