3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * GROningen Mixture of Alchemy and Childrens' Stories
48 #include "gmx_fatal.h"
53 # define gmx_fseek(A,B,C) fseeko(A,B,C)
54 # define gmx_ftell(A) ftello(A)
55 # define gmx_off_t off_t
57 # define gmx_fseek(A,B,C) fseek(A,B,C)
58 # define gmx_ftell(A) ftell(A)
59 # define gmx_off_t int
64 /* This is just for clarity - it can never be anything but 4! */
65 #define XDR_INT_SIZE 4
67 /* same order as the definition of xdr_datatype */
68 const char *xdr_datatype_names[] =
79 /*___________________________________________________________________________
81 | what follows are the C routine to read/write compressed coordinates together
82 | with some routines to assist in this task (those are marked
83 | static and cannot be called from user programs)
85 #define MAXABS INT_MAX-2
88 #define MIN(x,y) ((x) < (y) ? (x):(y))
91 #define MAX(x,y) ((x) > (y) ? (x):(y))
94 #define SQR(x) ((x)*(x))
96 static const int magicints[] = {
97 0, 0, 0, 0, 0, 0, 0, 0, 0,
98 8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
99 80, 101, 128, 161, 203, 256, 322, 406, 512, 645,
100 812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501,
101 8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536,
102 82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,
103 832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042,
104 8388607, 10568983, 13316085, 16777216 };
107 /* note that magicints[FIRSTIDX-1] == 0 */
108 #define LASTIDX (sizeof(magicints) / sizeof(*magicints))
111 /*____________________________________________________________________________
113 | sendbits - encode num into buf using the specified number of bits
115 | This routines appends the value of num to the bits already present in
116 | the array buf. You need to give it the number of bits to use and you
117 | better make sure that this number of bits is enough to hold the value
118 | Also num must be positive.
122 static void sendbits(int buf[], int num_of_bits, int num) {
124 unsigned int cnt, lastbyte;
126 unsigned char * cbuf;
128 cbuf = ((unsigned char *)buf) + 3 * sizeof(*buf);
129 cnt = (unsigned int) buf[0];
131 lastbyte =(unsigned int) buf[2];
132 while (num_of_bits >= 8) {
133 lastbyte = (lastbyte << 8) | ((num >> (num_of_bits -8)) /* & 0xff*/);
134 cbuf[cnt++] = lastbyte >> lastbits;
137 if (num_of_bits > 0) {
138 lastbyte = (lastbyte << num_of_bits) | num;
139 lastbits += num_of_bits;
142 cbuf[cnt++] = lastbyte >> lastbits;
149 cbuf[cnt] = lastbyte << (8 - lastbits);
153 /*_________________________________________________________________________
155 | sizeofint - calculate bitsize of an integer
157 | return the number of bits needed to store an integer with given max size
161 static int sizeofint(const int size) {
165 while (size >= num && num_of_bits < 32) {
172 /*___________________________________________________________________________
174 | sizeofints - calculate 'bitsize' of compressed ints
176 | given the number of small unsigned integers and the maximum value
177 | return the number of bits needed to read or write them with the
178 | routines receiveints and sendints. You need this parameter when
179 | calling these routines. Note that for many calls I can use
180 | the variable 'smallidx' which is exactly the number of bits, and
181 | So I don't need to call 'sizeofints for those calls.
184 static int sizeofints( const int num_of_ints, unsigned int sizes[]) {
187 unsigned int num_of_bytes, num_of_bits, bytecnt, tmp;
191 for (i=0; i < num_of_ints; i++) {
193 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++) {
194 tmp = bytes[bytecnt] * sizes[i] + tmp;
195 bytes[bytecnt] = tmp & 0xff;
199 bytes[bytecnt++] = tmp & 0xff;
202 num_of_bytes = bytecnt;
206 while (bytes[num_of_bytes] >= num) {
210 return num_of_bits + num_of_bytes * 8;
214 /*____________________________________________________________________________
216 | sendints - send a small set of small integers in compressed format
218 | this routine is used internally by xdr3dfcoord, to send a set of
219 | small integers to the buffer.
220 | Multiplication with fixed (specified maximum ) sizes is used to get
221 | to one big, multibyte integer. Allthough the routine could be
222 | modified to handle sizes bigger than 16777216, or more than just
223 | a few integers, this is not done, because the gain in compression
224 | isn't worth the effort. Note that overflowing the multiplication
225 | or the byte buffer (32 bytes) is unchecked and causes bad results.
229 static void sendints(int buf[], const int num_of_ints, const int num_of_bits,
230 unsigned int sizes[], unsigned int nums[]) {
232 int i, num_of_bytes, bytecnt;
233 unsigned int bytes[32], tmp;
238 bytes[num_of_bytes++] = tmp & 0xff;
242 for (i = 1; i < num_of_ints; i++) {
243 if (nums[i] >= sizes[i]) {
244 fprintf(stderr,"major breakdown in sendints num %u doesn't "
245 "match size %u\n", nums[i], sizes[i]);
248 /* use one step multiply */
250 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++) {
251 tmp = bytes[bytecnt] * sizes[i] + tmp;
252 bytes[bytecnt] = tmp & 0xff;
256 bytes[bytecnt++] = tmp & 0xff;
259 num_of_bytes = bytecnt;
261 if (num_of_bits >= num_of_bytes * 8) {
262 for (i = 0; i < num_of_bytes; i++) {
263 sendbits(buf, 8, bytes[i]);
265 sendbits(buf, num_of_bits - num_of_bytes * 8, 0);
267 for (i = 0; i < num_of_bytes-1; i++) {
268 sendbits(buf, 8, bytes[i]);
270 sendbits(buf, num_of_bits- (num_of_bytes -1) * 8, bytes[i]);
275 /*___________________________________________________________________________
277 | receivebits - decode number from buf using specified number of bits
279 | extract the number of bits from the array buf and construct an integer
280 | from it. Return that value.
284 static int receivebits(int buf[], int num_of_bits) {
286 int cnt, num, lastbits;
287 unsigned int lastbyte;
288 unsigned char * cbuf;
289 int mask = (1 << num_of_bits) -1;
291 cbuf = ((unsigned char *)buf) + 3 * sizeof(*buf);
293 lastbits = (unsigned int) buf[1];
294 lastbyte = (unsigned int) buf[2];
297 while (num_of_bits >= 8) {
298 lastbyte = ( lastbyte << 8 ) | cbuf[cnt++];
299 num |= (lastbyte >> lastbits) << (num_of_bits - 8);
302 if (num_of_bits > 0) {
303 if (lastbits < num_of_bits) {
305 lastbyte = (lastbyte << 8) | cbuf[cnt++];
307 lastbits -= num_of_bits;
308 num |= (lastbyte >> lastbits) & ((1 << num_of_bits) -1);
317 /*____________________________________________________________________________
319 | receiveints - decode 'small' integers from the buf array
321 | this routine is the inverse from sendints() and decodes the small integers
322 | written to buf by calculating the remainder and doing divisions with
323 | the given sizes[]. You need to specify the total number of bits to be
324 | used from buf in num_of_bits.
328 static void receiveints(int buf[], const int num_of_ints, int num_of_bits,
329 unsigned int sizes[], int nums[]) {
331 int i, j, num_of_bytes, p, num;
333 bytes[0] = bytes[1] = bytes[2] = bytes[3] = 0;
335 while (num_of_bits > 8) {
336 bytes[num_of_bytes++] = receivebits(buf, 8);
339 if (num_of_bits > 0) {
340 bytes[num_of_bytes++] = receivebits(buf, num_of_bits);
342 for (i = num_of_ints-1; i > 0; i--) {
344 for (j = num_of_bytes-1; j >=0; j--) {
345 num = (num << 8) | bytes[j];
348 num = num - p * sizes[i];
352 nums[0] = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
355 /*____________________________________________________________________________
357 | xdr3dfcoord - read or write compressed 3d coordinates to xdr file.
359 | this routine reads or writes (depending on how you opened the file with
360 | xdropen() ) a large number of 3d coordinates (stored in *fp).
361 | The number of coordinates triplets to write is given by *size. On
362 | read this number may be zero, in which case it reads as many as were written
363 | or it may specify the number if triplets to read (which should match the
365 | Compression is achieved by first converting all floating numbers to integer
366 | using multiplication by *precision and rounding to the nearest integer.
367 | Then the minimum and maximum value are calculated to determine the range.
368 | The limited range of integers so found, is used to compress the coordinates.
369 | In addition the differences between succesive coordinates is calculated.
370 | If the difference happens to be 'small' then only the difference is saved,
371 | compressing the data even more. The notion of 'small' is changed dynamically
372 | and is enlarged or reduced whenever needed or possible.
373 | Extra compression is achieved in the case of GROMOS and coordinates of
374 | water molecules. GROMOS first writes out the Oxygen position, followed by
375 | the two hydrogens. In order to make the differences smaller (and thereby
376 | compression the data better) the order is changed into first one hydrogen
377 | then the oxygen, followed by the other hydrogen. This is rather special, but
378 | it shouldn't harm in the general case.
382 int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision)
388 /* preallocate a small buffer and ip on the stack - if we need more
389 we can always malloc(). This is faster for small values of size: */
390 unsigned prealloc_size=3*16;
391 int prealloc_ip[3*16], prealloc_buf[3*20];
392 int we_should_free=0;
394 int minint[3], maxint[3], mindiff, *lip, diff;
395 int lint1, lint2, lint3, oldlint1, oldlint2, oldlint3, smallidx;
397 unsigned sizeint[3], sizesmall[3], bitsizeint[3], size3, *luip;
399 int smallnum, smaller, larger, i, is_small, is_smaller, run, prevrun;
401 int tmp, *thiscoord, prevcoord[3];
402 unsigned int tmpcoord[30];
404 int bufsize, xdrid, lsize;
405 unsigned int bitsize;
410 bRead = (xdrs->x_op == XDR_DECODE);
411 bitsizeint[0] = bitsizeint[1] = bitsizeint[2] = 0;
412 prevcoord[0] = prevcoord[1] = prevcoord[2] = 0;
416 /* xdrs is open for writing */
418 if (xdr_int(xdrs, size) == 0)
421 /* when the number of coordinates is small, don't try to compress; just
422 * write them as floats using xdr_vector
425 return (xdr_vector(xdrs, (char *) fp, (unsigned int)size3,
426 (unsigned int)sizeof(*fp), (xdrproc_t)xdr_float));
429 if(xdr_float(xdrs, precision) == 0)
432 if (size3 <= prealloc_size)
440 bufsize = size3 * 1.2;
441 ip = (int *)malloc((size_t)(size3 * sizeof(*ip)));
442 buf = (int *)malloc((size_t)(bufsize * sizeof(*buf)));
443 if (ip == NULL || buf==NULL)
445 fprintf(stderr,"malloc failed\n");
449 /* buf[0-2] are special and do not contain actual data */
450 buf[0] = buf[1] = buf[2] = 0;
451 minint[0] = minint[1] = minint[2] = INT_MAX;
452 maxint[0] = maxint[1] = maxint[2] = INT_MIN;
457 oldlint1 = oldlint2 = oldlint3 = 0;
458 while(lfp < fp + size3 ) {
459 /* find nearest integer */
461 lf = *lfp * *precision + 0.5;
463 lf = *lfp * *precision - 0.5;
464 if (fabs(lf) > MAXABS) {
465 /* scaling would cause overflow */
469 if (lint1 < minint[0]) minint[0] = lint1;
470 if (lint1 > maxint[0]) maxint[0] = lint1;
474 lf = *lfp * *precision + 0.5;
476 lf = *lfp * *precision - 0.5;
477 if (fabs(lf) > MAXABS) {
478 /* scaling would cause overflow */
482 if (lint2 < minint[1]) minint[1] = lint2;
483 if (lint2 > maxint[1]) maxint[1] = lint2;
487 lf = *lfp * *precision + 0.5;
489 lf = *lfp * *precision - 0.5;
490 if (fabs(lf) > MAXABS) {
491 /* scaling would cause overflow */
495 if (lint3 < minint[2]) minint[2] = lint3;
496 if (lint3 > maxint[2]) maxint[2] = lint3;
499 diff = abs(oldlint1-lint1)+abs(oldlint2-lint2)+abs(oldlint3-lint3);
500 if (diff < mindiff && lfp > fp + 3)
506 if ( (xdr_int(xdrs, &(minint[0])) == 0) ||
507 (xdr_int(xdrs, &(minint[1])) == 0) ||
508 (xdr_int(xdrs, &(minint[2])) == 0) ||
509 (xdr_int(xdrs, &(maxint[0])) == 0) ||
510 (xdr_int(xdrs, &(maxint[1])) == 0) ||
511 (xdr_int(xdrs, &(maxint[2])) == 0))
521 if ((float)maxint[0] - (float)minint[0] >= MAXABS ||
522 (float)maxint[1] - (float)minint[1] >= MAXABS ||
523 (float)maxint[2] - (float)minint[2] >= MAXABS) {
524 /* turning value in unsigned by subtracting minint
525 * would cause overflow
529 sizeint[0] = maxint[0] - minint[0]+1;
530 sizeint[1] = maxint[1] - minint[1]+1;
531 sizeint[2] = maxint[2] - minint[2]+1;
533 /* check if one of the sizes is to big to be multiplied */
534 if ((sizeint[0] | sizeint[1] | sizeint[2] ) > 0xffffff) {
535 bitsizeint[0] = sizeofint(sizeint[0]);
536 bitsizeint[1] = sizeofint(sizeint[1]);
537 bitsizeint[2] = sizeofint(sizeint[2]);
538 bitsize = 0; /* flag the use of large sizes */
540 bitsize = sizeofints(3, sizeint);
543 luip = (unsigned int *) ip;
545 while (smallidx < LASTIDX && magicints[smallidx] < mindiff) {
548 if(xdr_int(xdrs, &smallidx) == 0)
558 maxidx = MIN(LASTIDX, smallidx + 8) ;
559 minidx = maxidx - 8; /* often this equal smallidx */
560 smaller = magicints[MAX(FIRSTIDX, smallidx-1)] / 2;
561 smallnum = magicints[smallidx] / 2;
562 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
563 larger = magicints[maxidx] / 2;
567 thiscoord = (int *)(luip) + i * 3;
568 if (smallidx < maxidx && i >= 1 &&
569 abs(thiscoord[0] - prevcoord[0]) < larger &&
570 abs(thiscoord[1] - prevcoord[1]) < larger &&
571 abs(thiscoord[2] - prevcoord[2]) < larger) {
573 } else if (smallidx > minidx) {
579 if (abs(thiscoord[0] - thiscoord[3]) < smallnum &&
580 abs(thiscoord[1] - thiscoord[4]) < smallnum &&
581 abs(thiscoord[2] - thiscoord[5]) < smallnum) {
582 /* interchange first with second atom for better
583 * compression of water molecules
585 tmp = thiscoord[0]; thiscoord[0] = thiscoord[3];
587 tmp = thiscoord[1]; thiscoord[1] = thiscoord[4];
589 tmp = thiscoord[2]; thiscoord[2] = thiscoord[5];
595 tmpcoord[0] = thiscoord[0] - minint[0];
596 tmpcoord[1] = thiscoord[1] - minint[1];
597 tmpcoord[2] = thiscoord[2] - minint[2];
599 sendbits(buf, bitsizeint[0], tmpcoord[0]);
600 sendbits(buf, bitsizeint[1], tmpcoord[1]);
601 sendbits(buf, bitsizeint[2], tmpcoord[2]);
603 sendints(buf, 3, bitsize, sizeint, tmpcoord);
605 prevcoord[0] = thiscoord[0];
606 prevcoord[1] = thiscoord[1];
607 prevcoord[2] = thiscoord[2];
608 thiscoord = thiscoord + 3;
612 if (is_small == 0 && is_smaller == -1)
614 while (is_small && run < 8*3) {
615 if (is_smaller == -1 && (
616 SQR(thiscoord[0] - prevcoord[0]) +
617 SQR(thiscoord[1] - prevcoord[1]) +
618 SQR(thiscoord[2] - prevcoord[2]) >= smaller * smaller)) {
622 tmpcoord[run++] = thiscoord[0] - prevcoord[0] + smallnum;
623 tmpcoord[run++] = thiscoord[1] - prevcoord[1] + smallnum;
624 tmpcoord[run++] = thiscoord[2] - prevcoord[2] + smallnum;
626 prevcoord[0] = thiscoord[0];
627 prevcoord[1] = thiscoord[1];
628 prevcoord[2] = thiscoord[2];
631 thiscoord = thiscoord + 3;
634 abs(thiscoord[0] - prevcoord[0]) < smallnum &&
635 abs(thiscoord[1] - prevcoord[1]) < smallnum &&
636 abs(thiscoord[2] - prevcoord[2]) < smallnum) {
640 if (run != prevrun || is_smaller != 0) {
642 sendbits(buf, 1, 1); /* flag the change in run-length */
643 sendbits(buf, 5, run+is_smaller+1);
645 sendbits(buf, 1, 0); /* flag the fact that runlength did not change */
647 for (k=0; k < run; k+=3) {
648 sendints(buf, 3, smallidx, sizesmall, &tmpcoord[k]);
650 if (is_smaller != 0) {
651 smallidx += is_smaller;
652 if (is_smaller < 0) {
654 smaller = magicints[smallidx-1] / 2;
657 smallnum = magicints[smallidx] / 2;
659 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
662 if (buf[1] != 0) buf[0]++;
663 /* buf[0] holds the length in bytes */
664 if(xdr_int(xdrs, &(buf[0])) == 0)
675 rc=errval * (xdr_opaque(xdrs, (char *)&(buf[3]), (unsigned int)buf[0]));
685 /* xdrs is open for reading */
687 if (xdr_int(xdrs, &lsize) == 0)
689 if (*size != 0 && lsize != *size) {
690 fprintf(stderr, "wrong number of coordinates in xdr3dfcoord; "
691 "%d arg vs %d in file", *size, lsize);
697 return (xdr_vector(xdrs, (char *) fp, (unsigned int)size3,
698 (unsigned int)sizeof(*fp), (xdrproc_t)xdr_float));
700 if(xdr_float(xdrs, precision) == 0)
703 if (size3 <= prealloc_size)
711 bufsize = size3 * 1.2;
712 ip = (int *)malloc((size_t)(size3 * sizeof(*ip)));
713 buf = (int *)malloc((size_t)(bufsize * sizeof(*buf)));
714 if (ip == NULL || buf==NULL)
716 fprintf(stderr,"malloc failed\n");
721 buf[0] = buf[1] = buf[2] = 0;
723 if ( (xdr_int(xdrs, &(minint[0])) == 0) ||
724 (xdr_int(xdrs, &(minint[1])) == 0) ||
725 (xdr_int(xdrs, &(minint[2])) == 0) ||
726 (xdr_int(xdrs, &(maxint[0])) == 0) ||
727 (xdr_int(xdrs, &(maxint[1])) == 0) ||
728 (xdr_int(xdrs, &(maxint[2])) == 0))
738 sizeint[0] = maxint[0] - minint[0]+1;
739 sizeint[1] = maxint[1] - minint[1]+1;
740 sizeint[2] = maxint[2] - minint[2]+1;
742 /* check if one of the sizes is to big to be multiplied */
743 if ((sizeint[0] | sizeint[1] | sizeint[2] ) > 0xffffff) {
744 bitsizeint[0] = sizeofint(sizeint[0]);
745 bitsizeint[1] = sizeofint(sizeint[1]);
746 bitsizeint[2] = sizeofint(sizeint[2]);
747 bitsize = 0; /* flag the use of large sizes */
749 bitsize = sizeofints(3, sizeint);
752 if (xdr_int(xdrs, &smallidx) == 0)
762 maxidx = MIN(LASTIDX, smallidx + 8) ;
763 minidx = maxidx - 8; /* often this equal smallidx */
764 smaller = magicints[MAX(FIRSTIDX, smallidx-1)] / 2;
765 smallnum = magicints[smallidx] / 2;
766 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx] ;
767 larger = magicints[maxidx];
769 /* buf[0] holds the length in bytes */
771 if (xdr_int(xdrs, &(buf[0])) == 0)
782 if (xdr_opaque(xdrs, (char *)&(buf[3]), (unsigned int)buf[0]) == 0)
794 buf[0] = buf[1] = buf[2] = 0;
797 inv_precision = 1.0 / * precision;
801 while ( i < lsize ) {
802 thiscoord = (int *)(lip) + i * 3;
805 thiscoord[0] = receivebits(buf, bitsizeint[0]);
806 thiscoord[1] = receivebits(buf, bitsizeint[1]);
807 thiscoord[2] = receivebits(buf, bitsizeint[2]);
809 receiveints(buf, 3, bitsize, sizeint, thiscoord);
813 thiscoord[0] += minint[0];
814 thiscoord[1] += minint[1];
815 thiscoord[2] += minint[2];
817 prevcoord[0] = thiscoord[0];
818 prevcoord[1] = thiscoord[1];
819 prevcoord[2] = thiscoord[2];
822 flag = receivebits(buf, 1);
825 run = receivebits(buf, 5);
826 is_smaller = run % 3;
832 for (k = 0; k < run; k+=3) {
833 receiveints(buf, 3, smallidx, sizesmall, thiscoord);
835 thiscoord[0] += prevcoord[0] - smallnum;
836 thiscoord[1] += prevcoord[1] - smallnum;
837 thiscoord[2] += prevcoord[2] - smallnum;
839 /* interchange first with second atom for better
840 * compression of water molecules
842 tmp = thiscoord[0]; thiscoord[0] = prevcoord[0];
844 tmp = thiscoord[1]; thiscoord[1] = prevcoord[1];
846 tmp = thiscoord[2]; thiscoord[2] = prevcoord[2];
848 *lfp++ = prevcoord[0] * inv_precision;
849 *lfp++ = prevcoord[1] * inv_precision;
850 *lfp++ = prevcoord[2] * inv_precision;
852 prevcoord[0] = thiscoord[0];
853 prevcoord[1] = thiscoord[1];
854 prevcoord[2] = thiscoord[2];
856 *lfp++ = thiscoord[0] * inv_precision;
857 *lfp++ = thiscoord[1] * inv_precision;
858 *lfp++ = thiscoord[2] * inv_precision;
861 *lfp++ = thiscoord[0] * inv_precision;
862 *lfp++ = thiscoord[1] * inv_precision;
863 *lfp++ = thiscoord[2] * inv_precision;
865 smallidx += is_smaller;
866 if (is_smaller < 0) {
868 if (smallidx > FIRSTIDX) {
869 smaller = magicints[smallidx - 1] /2;
873 } else if (is_smaller > 0) {
875 smallnum = magicints[smallidx] / 2;
877 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx] ;
890 /******************************************************************
892 XTC files have a relatively simple structure.
893 They have a header of 16 bytes and the rest are
894 the compressed coordinates of the files. Due to the
895 compression 00 is not present in the coordinates.
896 The first 4 bytes of the header are the magic number
897 1995 (0x000007CB). If we find this number we are guaranteed
898 to be in the header, due to the presence of so many zeros.
899 The second 4 bytes are the number of atoms in the frame, and is
900 assumed to be constant. The third 4 bytes are the frame number.
901 The last 4 bytes are a floating point representation of the time.
903 ********************************************************************/
905 /* Must match definition in xtcio.c */
907 #define XTC_MAGIC 1995
910 static const int header_size = 16;
912 /* Check if we are at the header start.
913 At the same time it will also read 1 int */
914 static int xtc_at_header_start(FILE *fp, XDR *xdrs,
915 int natoms, int * timestep, float * time){
922 if((off = gmx_ftell(fp)) < 0){
925 /* read magic natoms and timestep */
927 if(!xdr_int(xdrs, &(i_inp[i]))){
928 gmx_fseek(fp,off+XDR_INT_SIZE,SEEK_SET);
933 if(i_inp[0] != XTC_MAGIC){
934 if(gmx_fseek(fp,off+XDR_INT_SIZE,SEEK_SET)){
939 /* read time and box */
941 if(!xdr_float(xdrs, &(f_inp[i]))){
942 gmx_fseek(fp,off+XDR_INT_SIZE,SEEK_SET);
946 /* Make a rigourous check to see if we are in the beggining of a header
947 Hopefully there are no ambiguous cases */
948 /* This check makes use of the fact that the box matrix has 3 zeroes on the upper
949 right triangle and that the first element must be nonzero unless the entire matrix is zero
951 if(i_inp[1] == natoms &&
952 ((f_inp[1] != 0 && f_inp[6] == 0) ||
953 (f_inp[1] == 0 && f_inp[5] == 0 && f_inp[9] == 0))){
954 if(gmx_fseek(fp,off+XDR_INT_SIZE,SEEK_SET)){
958 *timestep = i_inp[2];
961 if(gmx_fseek(fp,off+XDR_INT_SIZE,SEEK_SET)){
968 xtc_get_next_frame_number(FILE *fp, XDR *xdrs, int natoms)
975 if((off = gmx_ftell(fp)) < 0){
979 /* read one int just to make sure we dont read this frame but the next */
982 ret = xtc_at_header_start(fp,xdrs,natoms,&step,&time);
984 if(gmx_fseek(fp,off,SEEK_SET)){
989 if(gmx_fseek(fp,off,SEEK_SET)){
998 static float xtc_get_next_frame_time(FILE *fp, XDR *xdrs, int natoms,
1007 if ((off = gmx_ftell(fp)) < 0)
1011 /* read one int just to make sure we dont read this frame but the next */
1012 xdr_int(xdrs, &step);
1015 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1019 if (gmx_fseek(fp,off,SEEK_SET))
1028 if (gmx_fseek(fp,off,SEEK_SET))
1040 xtc_get_current_frame_time(FILE *fp, XDR *xdrs, int natoms, gmx_bool * bOK)
1048 if ((off = gmx_ftell(fp)) < 0)
1055 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1059 if (gmx_fseek(fp,off,SEEK_SET))
1068 if (gmx_fseek(fp,off,SEEK_SET))
1077 if (gmx_fseek(fp,-2*XDR_INT_SIZE,SEEK_CUR))
1086 /* Currently not used, just for completeness */
1088 xtc_get_current_frame_number(FILE *fp,XDR *xdrs,int natoms, gmx_bool * bOK)
1096 if((off = gmx_ftell(fp)) < 0){
1102 ret = xtc_at_header_start(fp,xdrs,natoms,&step,&time);
1105 if(gmx_fseek(fp,off,SEEK_SET)){
1110 }else if(ret == -1){
1111 if(gmx_fseek(fp,off,SEEK_SET)){
1118 if(gmx_fseek(fp,-2*XDR_INT_SIZE,SEEK_CUR)){
1128 static gmx_off_t xtc_get_next_frame_start(FILE *fp, XDR *xdrs, int natoms)
1135 /* read one int just to make sure we dont read this frame but the next */
1136 xdr_int(xdrs,&step);
1139 ret = xtc_at_header_start(fp,xdrs,natoms,&step,&time);
1141 if((res = gmx_ftell(fp)) >= 0){
1142 return res - XDR_INT_SIZE;
1146 }else if(ret == -1){
1156 xdr_xtc_estimate_dt(FILE *fp, XDR *xdrs, int natoms, gmx_bool * bOK)
1163 if((off = gmx_ftell(fp)) < 0){
1167 tinit = xtc_get_current_frame_time(fp,xdrs,natoms,bOK);
1174 res = xtc_get_next_frame_time(fp,xdrs,natoms,bOK);
1182 if (0 != gmx_fseek(fp,off,SEEK_SET)) {
1191 xdr_xtc_seek_frame(int frame, FILE *fp, XDR *xdrs, int natoms)
1197 /* round to 4 bytes */
1200 if(gmx_fseek(fp,0,SEEK_END)){
1204 if((high = gmx_ftell(fp)) < 0){
1208 /* round to 4 bytes */
1209 high /= XDR_INT_SIZE;
1210 high *= XDR_INT_SIZE;
1211 offset = ((high/2)/XDR_INT_SIZE)*XDR_INT_SIZE;
1213 if(gmx_fseek(fp,offset,SEEK_SET)){
1219 fr = xtc_get_next_frame_number(fp,xdrs,natoms);
1224 if(fr != frame && abs(low-high) > header_size)
1234 /* round to 4 bytes */
1235 offset = (((high+low)/2)/4)*4;
1237 if(gmx_fseek(fp,offset,SEEK_SET)){
1246 if(offset <= header_size)
1251 if(gmx_fseek(fp,offset,SEEK_SET)){
1255 if((pos = xtc_get_next_frame_start(fp,xdrs,natoms))< 0){
1256 /* we probably hit an end of file */
1260 if(gmx_fseek(fp,pos,SEEK_SET)){
1269 int xdr_xtc_seek_time(real time, FILE *fp, XDR *xdrs, int natoms,gmx_bool bSeekForwardOnly)
1273 gmx_bool bOK = FALSE;
1275 gmx_off_t high, offset, pos;
1279 if (bSeekForwardOnly)
1281 low = gmx_ftell(fp);
1283 if (gmx_fseek(fp,0,SEEK_END))
1288 if ((high = gmx_ftell(fp)) < 0)
1293 high /= XDR_INT_SIZE;
1294 high *= XDR_INT_SIZE;
1295 offset = (((high-low) / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1297 if (gmx_fseek(fp,offset,SEEK_SET))
1304 * No need to call xdr_xtc_estimate_dt here - since xdr_xtc_estimate_dt is called first thing in the loop
1305 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1315 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1326 /* Found a place in the trajectory that has positive time step while
1327 other has negative time step */
1336 /* Found a place in the trajectory that has positive time step while
1337 other has negative time step */
1343 t = xtc_get_next_frame_time(fp, xdrs, natoms, &bOK);
1349 /* If we are before the target time and the time step is positive or 0, or we have
1350 after the target time and the time step is negative, or the difference between
1351 the current time and the target time is bigger than dt and above all the distance between high
1352 and low is bigger than 1 frame, then do another step of binary search. Otherwise stop and check
1353 if we reached the solution */
1354 if ((((t < time && dt_sign >= 0) || (t > time && dt_sign == -1)) || ((t
1355 - time) >= dt && dt_sign >= 0)
1356 || ((time - t) >= -dt && dt_sign < 0)) && (abs(low - high)
1359 if (dt >= 0 && dt_sign != -1)
1370 else if (dt <= 0 && dt_sign == -1)
1383 /* We should never reach here */
1386 /* round to 4 bytes and subtract header*/
1387 offset = (((high + low) / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1388 if (gmx_fseek(fp,offset,SEEK_SET))
1395 if (abs(low - high) <= header_size)
1399 /* re-estimate dt */
1400 if (xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK) != dt)
1404 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1407 if (t >= time && t - time < dt)
1414 if (offset <= header_size)
1419 gmx_fseek(fp,offset,SEEK_SET);
1421 if ((pos = xtc_get_next_frame_start(fp, xdrs, natoms)) < 0)
1426 if (gmx_fseek(fp,pos,SEEK_SET))
1434 xdr_xtc_get_last_frame_time(FILE *fp, XDR *xdrs, int natoms, gmx_bool * bOK)
1440 off = gmx_ftell(fp);
1446 if( (res = gmx_fseek(fp,-3*XDR_INT_SIZE,SEEK_END)) != 0){
1451 time = xtc_get_current_frame_time(fp, xdrs, natoms, bOK);
1456 if( (res = gmx_fseek(fp,off,SEEK_SET)) != 0){
1465 xdr_xtc_get_last_frame_number(FILE *fp, XDR *xdrs, int natoms, gmx_bool * bOK)
1472 if((off = gmx_ftell(fp)) < 0){
1478 if(gmx_fseek(fp,-3*XDR_INT_SIZE,SEEK_END)){
1483 frame = xtc_get_current_frame_number(fp, xdrs, natoms, bOK);
1489 if(gmx_fseek(fp,off,SEEK_SET)){