2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
47 #include "gromacs/fileio/xdr_datatype.h"
48 #include "gromacs/fileio/xdrf.h"
49 #include "gromacs/utility/futil.h"
51 /* This is just for clarity - it can never be anything but 4! */
52 #define XDR_INT_SIZE 4
54 /* same order as the definition of xdr_datatype */
55 const char* xdr_datatype_names[] = { "int", "float", "double", "large int", "char", "string" };
58 /*___________________________________________________________________________
60 | what follows are the C routine to read/write compressed coordinates together
61 | with some routines to assist in this task (those are marked
62 | static and cannot be called from user programs)
64 #define MAXABS (INT_MAX - 2)
67 # define SQR(x) ((x) * (x))
69 static const int magicints[] = {
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,
71 10, 12, 16, 20, 25, 32, 40, 50, 64, 80,
72 101, 128, 161, 203, 256, 322, 406, 512, 645, 812,
73 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501, 8192,
74 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536, 82570,
75 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561, 832255,
76 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042, 8388607,
77 10568983, 13316085, 16777216
81 /* note that magicints[FIRSTIDX-1] == 0 */
82 #define LASTIDX static_cast<int>((sizeof(magicints) / sizeof(*magicints)))
85 /*____________________________________________________________________________
87 | sendbits - encode num into buf using the specified number of bits
89 | This routines appends the value of num to the bits already present in
90 | the array buf. You need to give it the number of bits to use and you
91 | better make sure that this number of bits is enough to hold the value
92 | Also num must be positive.
96 static void sendbits(int buf[], int num_of_bits, int num)
99 unsigned int cnt, lastbyte;
103 cbuf = (reinterpret_cast<unsigned char*>(buf)) + 3 * sizeof(*buf);
104 cnt = static_cast<unsigned int>(buf[0]);
106 lastbyte = static_cast<unsigned int>(buf[2]);
107 while (num_of_bits >= 8)
109 lastbyte = (lastbyte << 8) | ((num >> (num_of_bits - 8)) /* & 0xff*/);
110 cbuf[cnt++] = lastbyte >> lastbits;
115 lastbyte = (lastbyte << num_of_bits) | num;
116 lastbits += num_of_bits;
120 cbuf[cnt++] = lastbyte >> lastbits;
128 cbuf[cnt] = lastbyte << (8 - lastbits);
132 /*_________________________________________________________________________
134 | sizeofint - calculate bitsize of an integer
136 | return the number of bits needed to store an integer with given max size
140 static int sizeofint(const int size)
145 while (size >= num && num_of_bits < 32)
153 /*___________________________________________________________________________
155 | sizeofints - calculate 'bitsize' of compressed ints
157 | given the number of small unsigned integers and the maximum value
158 | return the number of bits needed to read or write them with the
159 | routines receiveints and sendints. You need this parameter when
160 | calling these routines. Note that for many calls I can use
161 | the variable 'smallidx' which is exactly the number of bits, and
162 | So I don't need to call 'sizeofints for those calls.
165 static int sizeofints(const int num_of_ints, const unsigned int sizes[])
169 unsigned int num_of_bytes, num_of_bits, bytecnt, tmp;
173 for (i = 0; i < num_of_ints; i++)
176 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++)
178 tmp = bytes[bytecnt] * sizes[i] + tmp;
179 bytes[bytecnt] = tmp & 0xff;
184 bytes[bytecnt++] = tmp & 0xff;
187 num_of_bytes = bytecnt;
191 while (bytes[num_of_bytes] >= num)
196 return num_of_bits + num_of_bytes * 8;
199 /*____________________________________________________________________________
201 | sendints - send a small set of small integers in compressed format
203 | this routine is used internally by xdr3dfcoord, to send a set of
204 | small integers to the buffer.
205 | Multiplication with fixed (specified maximum ) sizes is used to get
206 | to one big, multibyte integer. Allthough the routine could be
207 | modified to handle sizes bigger than 16777216, or more than just
208 | a few integers, this is not done, because the gain in compression
209 | isn't worth the effort. Note that overflowing the multiplication
210 | or the byte buffer (32 bytes) is unchecked and causes bad results.
214 static void sendints(int buf[],
215 const int num_of_ints,
216 const int num_of_bits,
217 unsigned int sizes[],
221 int i, num_of_bytes, bytecnt;
222 unsigned int bytes[32], tmp;
228 bytes[num_of_bytes++] = tmp & 0xff;
232 for (i = 1; i < num_of_ints; i++)
234 if (nums[i] >= sizes[i])
237 "major breakdown in sendints num %u doesn't "
242 /* use one step multiply */
244 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++)
246 tmp = bytes[bytecnt] * sizes[i] + tmp;
247 bytes[bytecnt] = tmp & 0xff;
252 bytes[bytecnt++] = tmp & 0xff;
255 num_of_bytes = bytecnt;
257 if (num_of_bits >= num_of_bytes * 8)
259 for (i = 0; i < num_of_bytes; i++)
261 sendbits(buf, 8, bytes[i]);
263 sendbits(buf, num_of_bits - num_of_bytes * 8, 0);
267 for (i = 0; i < num_of_bytes - 1; i++)
269 sendbits(buf, 8, bytes[i]);
271 sendbits(buf, num_of_bits - (num_of_bytes - 1) * 8, bytes[i]);
276 /*___________________________________________________________________________
278 | receivebits - decode number from buf using specified number of bits
280 | extract the number of bits from the array buf and construct an integer
281 | from it. Return that value.
285 static int receivebits(int buf[], int num_of_bits)
288 int cnt, num, lastbits;
289 unsigned int lastbyte;
291 int mask = (1 << num_of_bits) - 1;
293 cbuf = reinterpret_cast<unsigned char*>(buf) + 3 * sizeof(*buf);
295 lastbits = static_cast<unsigned int>(buf[1]);
296 lastbyte = static_cast<unsigned int>(buf[2]);
299 while (num_of_bits >= 8)
301 lastbyte = (lastbyte << 8) | cbuf[cnt++];
302 num |= (lastbyte >> lastbits) << (num_of_bits - 8);
307 if (lastbits < num_of_bits)
310 lastbyte = (lastbyte << 8) | cbuf[cnt++];
312 lastbits -= num_of_bits;
313 num |= (lastbyte >> lastbits) & ((1 << num_of_bits) - 1);
322 /*____________________________________________________________________________
324 | receiveints - decode 'small' integers from the buf array
326 | this routine is the inverse from sendints() and decodes the small integers
327 | written to buf by calculating the remainder and doing divisions with
328 | the given sizes[]. You need to specify the total number of bits to be
329 | used from buf in num_of_bits.
333 static void receiveints(int buf[], const int num_of_ints, int num_of_bits, const unsigned int sizes[], int nums[])
336 int i, j, num_of_bytes, p, num;
338 bytes[0] = bytes[1] = bytes[2] = bytes[3] = 0;
340 while (num_of_bits > 8)
342 bytes[num_of_bytes++] = receivebits(buf, 8);
347 bytes[num_of_bytes++] = receivebits(buf, num_of_bits);
349 for (i = num_of_ints - 1; i > 0; i--)
352 for (j = num_of_bytes - 1; j >= 0; j--)
354 num = (num << 8) | bytes[j];
357 num = num - p * sizes[i];
361 nums[0] = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
364 /*____________________________________________________________________________
366 | xdr3dfcoord - read or write compressed 3d coordinates to xdr file.
368 | this routine reads or writes (depending on how you opened the file with
369 | xdropen() ) a large number of 3d coordinates (stored in *fp).
370 | The number of coordinates triplets to write is given by *size. On
371 | read this number may be zero, in which case it reads as many as were written
372 | or it may specify the number if triplets to read (which should match the
374 | Compression is achieved by first converting all floating numbers to integer
375 | using multiplication by *precision and rounding to the nearest integer.
376 | Then the minimum and maximum value are calculated to determine the range.
377 | The limited range of integers so found, is used to compress the coordinates.
378 | In addition the differences between succesive coordinates is calculated.
379 | If the difference happens to be 'small' then only the difference is saved,
380 | compressing the data even more. The notion of 'small' is changed dynamically
381 | and is enlarged or reduced whenever needed or possible.
382 | Extra compression is achieved in the case of GROMOS and coordinates of
383 | water molecules. GROMOS first writes out the Oxygen position, followed by
384 | the two hydrogens. In order to make the differences smaller (and thereby
385 | compression the data better) the order is changed into first one hydrogen
386 | then the oxygen, followed by the other hydrogen. This is rather special, but
387 | it shouldn't harm in the general case.
391 int xdr3dfcoord(XDR* xdrs, float* fp, int* size, float* precision)
397 /* preallocate a small buffer and ip on the stack - if we need more
398 we can always malloc(). This is faster for small values of size: */
399 unsigned prealloc_size = 3 * 16;
400 int prealloc_ip[3 * 16], prealloc_buf[3 * 20];
401 int we_should_free = 0;
403 int minint[3], maxint[3], mindiff, *lip, diff;
404 int lint1, lint2, lint3, oldlint1, oldlint2, oldlint3, smallidx;
406 unsigned sizeint[3], sizesmall[3], bitsizeint[3], size3, *luip;
408 int smallnum, smaller, larger, i, is_small, is_smaller, run, prevrun;
410 int tmp, *thiscoord, prevcoord[3];
411 unsigned int tmpcoord[30];
414 unsigned int bitsize;
419 bRead = (xdrs->x_op == XDR_DECODE);
420 bitsizeint[0] = bitsizeint[1] = bitsizeint[2] = 0;
421 prevcoord[0] = prevcoord[1] = prevcoord[2] = 0;
423 // The static analyzer warns about garbage values for thiscoord[] further
424 // down. It might be thrown off by all the reinterpret_casts, but we might
425 // as well make sure the small preallocated buffer is zero-initialized.
426 for (i = 0; i < static_cast<int>(prealloc_size); i++)
433 /* xdrs is open for writing */
435 if (xdr_int(xdrs, size) == 0)
440 /* when the number of coordinates is small, don't try to compress; just
441 * write them as floats using xdr_vector
445 return (xdr_vector(xdrs, reinterpret_cast<char*>(fp), static_cast<unsigned int>(size3),
446 static_cast<unsigned int>(sizeof(*fp)),
447 reinterpret_cast<xdrproc_t>(xdr_float)));
450 if (xdr_float(xdrs, precision) == 0)
455 if (size3 <= prealloc_size)
463 bufsize = static_cast<int>(size3 * 1.2);
464 ip = reinterpret_cast<int*>(malloc(size3 * sizeof(*ip)));
465 buf = reinterpret_cast<int*>(malloc(bufsize * sizeof(*buf)));
466 if (ip == nullptr || buf == nullptr)
468 fprintf(stderr, "malloc failed\n");
472 /* buf[0-2] are special and do not contain actual data */
473 buf[0] = buf[1] = buf[2] = 0;
474 minint[0] = minint[1] = minint[2] = INT_MAX;
475 maxint[0] = maxint[1] = maxint[2] = INT_MIN;
480 oldlint1 = oldlint2 = oldlint3 = 0;
481 while (lfp < fp + size3)
483 /* find nearest integer */
486 lf = *lfp * *precision + 0.5;
490 lf = *lfp * *precision - 0.5;
492 if (std::fabs(lf) > MAXABS)
494 /* scaling would cause overflow */
497 lint1 = static_cast<int>(lf);
498 if (lint1 < minint[0])
502 if (lint1 > maxint[0])
510 lf = *lfp * *precision + 0.5;
514 lf = *lfp * *precision - 0.5;
516 if (std::fabs(lf) > MAXABS)
518 /* scaling would cause overflow */
521 lint2 = static_cast<int>(lf);
522 if (lint2 < minint[1])
526 if (lint2 > maxint[1])
534 lf = *lfp * *precision + 0.5;
538 lf = *lfp * *precision - 0.5;
540 if (std::abs(lf) > MAXABS)
542 /* scaling would cause overflow */
545 lint3 = static_cast<int>(lf);
546 if (lint3 < minint[2])
550 if (lint3 > maxint[2])
556 diff = std::abs(oldlint1 - lint1) + std::abs(oldlint2 - lint2) + std::abs(oldlint3 - lint3);
557 if (diff < mindiff && lfp > fp + 3)
565 if ((xdr_int(xdrs, &(minint[0])) == 0) || (xdr_int(xdrs, &(minint[1])) == 0)
566 || (xdr_int(xdrs, &(minint[2])) == 0) || (xdr_int(xdrs, &(maxint[0])) == 0)
567 || (xdr_int(xdrs, &(maxint[1])) == 0) || (xdr_int(xdrs, &(maxint[2])) == 0))
577 if (static_cast<float>(maxint[0]) - static_cast<float>(minint[0]) >= MAXABS
578 || static_cast<float>(maxint[1]) - static_cast<float>(minint[1]) >= MAXABS
579 || static_cast<float>(maxint[2]) - static_cast<float>(minint[2]) >= MAXABS)
581 /* turning value in unsigned by subtracting minint
582 * would cause overflow
586 sizeint[0] = maxint[0] - minint[0] + 1;
587 sizeint[1] = maxint[1] - minint[1] + 1;
588 sizeint[2] = maxint[2] - minint[2] + 1;
590 /* check if one of the sizes is to big to be multiplied */
591 if ((sizeint[0] | sizeint[1] | sizeint[2]) > 0xffffff)
593 bitsizeint[0] = sizeofint(sizeint[0]);
594 bitsizeint[1] = sizeofint(sizeint[1]);
595 bitsizeint[2] = sizeofint(sizeint[2]);
596 bitsize = 0; /* flag the use of large sizes */
600 bitsize = sizeofints(3, sizeint);
602 luip = reinterpret_cast<unsigned int*>(ip);
604 while (smallidx < LASTIDX && magicints[smallidx] < mindiff)
608 if (xdr_int(xdrs, &smallidx) == 0)
618 maxidx = std::min(LASTIDX, smallidx + 8);
619 minidx = maxidx - 8; /* often this equal smallidx */
620 smaller = magicints[std::max(FIRSTIDX, smallidx - 1)] / 2;
621 smallnum = magicints[smallidx] / 2;
622 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
623 larger = magicints[maxidx] / 2;
628 thiscoord = reinterpret_cast<int*>(luip) + i * 3;
629 if (smallidx < maxidx && i >= 1 && std::abs(thiscoord[0] - prevcoord[0]) < larger
630 && std::abs(thiscoord[1] - prevcoord[1]) < larger
631 && std::abs(thiscoord[2] - prevcoord[2]) < larger)
635 else if (smallidx > minidx)
645 if (std::abs(thiscoord[0] - thiscoord[3]) < smallnum
646 && std::abs(thiscoord[1] - thiscoord[4]) < smallnum
647 && std::abs(thiscoord[2] - thiscoord[5]) < smallnum)
649 /* interchange first with second atom for better
650 * compression of water molecules
653 thiscoord[0] = thiscoord[3];
656 thiscoord[1] = thiscoord[4];
659 thiscoord[2] = thiscoord[5];
664 tmpcoord[0] = thiscoord[0] - minint[0];
665 tmpcoord[1] = thiscoord[1] - minint[1];
666 tmpcoord[2] = thiscoord[2] - minint[2];
669 sendbits(buf, bitsizeint[0], tmpcoord[0]);
670 sendbits(buf, bitsizeint[1], tmpcoord[1]);
671 sendbits(buf, bitsizeint[2], tmpcoord[2]);
675 sendints(buf, 3, bitsize, sizeint, tmpcoord);
677 prevcoord[0] = thiscoord[0];
678 prevcoord[1] = thiscoord[1];
679 prevcoord[2] = thiscoord[2];
680 thiscoord = thiscoord + 3;
684 if (is_small == 0 && is_smaller == -1)
688 while (is_small && run < 8 * 3)
691 && (SQR(thiscoord[0] - prevcoord[0]) + SQR(thiscoord[1] - prevcoord[1])
692 + SQR(thiscoord[2] - prevcoord[2])
693 >= smaller * smaller))
698 tmpcoord[run++] = thiscoord[0] - prevcoord[0] + smallnum;
699 tmpcoord[run++] = thiscoord[1] - prevcoord[1] + smallnum;
700 tmpcoord[run++] = thiscoord[2] - prevcoord[2] + smallnum;
702 prevcoord[0] = thiscoord[0];
703 prevcoord[1] = thiscoord[1];
704 prevcoord[2] = thiscoord[2];
707 thiscoord = thiscoord + 3;
709 if (i < *size && abs(thiscoord[0] - prevcoord[0]) < smallnum
710 && abs(thiscoord[1] - prevcoord[1]) < smallnum
711 && abs(thiscoord[2] - prevcoord[2]) < smallnum)
716 if (run != prevrun || is_smaller != 0)
719 sendbits(buf, 1, 1); /* flag the change in run-length */
720 sendbits(buf, 5, run + is_smaller + 1);
724 sendbits(buf, 1, 0); /* flag the fact that runlength did not change */
726 for (k = 0; k < run; k += 3)
728 sendints(buf, 3, smallidx, sizesmall, &tmpcoord[k]);
732 smallidx += is_smaller;
736 smaller = magicints[smallidx - 1] / 2;
741 smallnum = magicints[smallidx] / 2;
743 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
750 /* buf[0] holds the length in bytes */
751 if (xdr_int(xdrs, &(buf[0])) == 0)
763 * (xdr_opaque(xdrs, reinterpret_cast<char*>(&(buf[3])), static_cast<unsigned int>(buf[0])));
774 /* xdrs is open for reading */
776 if (xdr_int(xdrs, &lsize) == 0)
780 if (*size != 0 && lsize != *size)
783 "wrong number of coordinates in xdr3dfcoord; "
784 "%d arg vs %d in file",
792 return (xdr_vector(xdrs, reinterpret_cast<char*>(fp), static_cast<unsigned int>(size3),
793 static_cast<unsigned int>(sizeof(*fp)),
794 reinterpret_cast<xdrproc_t>(xdr_float)));
796 if (xdr_float(xdrs, precision) == 0)
801 if (size3 <= prealloc_size)
809 bufsize = static_cast<int>(size3 * 1.2);
810 ip = reinterpret_cast<int*>(malloc(size3 * sizeof(*ip)));
811 buf = reinterpret_cast<int*>(malloc(bufsize * sizeof(*buf)));
812 if (ip == nullptr || buf == nullptr)
814 fprintf(stderr, "malloc failed\n");
819 buf[0] = buf[1] = buf[2] = 0;
821 if ((xdr_int(xdrs, &(minint[0])) == 0) || (xdr_int(xdrs, &(minint[1])) == 0)
822 || (xdr_int(xdrs, &(minint[2])) == 0) || (xdr_int(xdrs, &(maxint[0])) == 0)
823 || (xdr_int(xdrs, &(maxint[1])) == 0) || (xdr_int(xdrs, &(maxint[2])) == 0))
833 sizeint[0] = maxint[0] - minint[0] + 1;
834 sizeint[1] = maxint[1] - minint[1] + 1;
835 sizeint[2] = maxint[2] - minint[2] + 1;
837 /* check if one of the sizes is to big to be multiplied */
838 if ((sizeint[0] | sizeint[1] | sizeint[2]) > 0xffffff)
840 bitsizeint[0] = sizeofint(sizeint[0]);
841 bitsizeint[1] = sizeofint(sizeint[1]);
842 bitsizeint[2] = sizeofint(sizeint[2]);
843 bitsize = 0; /* flag the use of large sizes */
847 bitsize = sizeofints(3, sizeint);
850 if (xdr_int(xdrs, &smallidx) == 0)
860 smaller = magicints[std::max(FIRSTIDX, smallidx - 1)] / 2;
861 smallnum = magicints[smallidx] / 2;
862 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
864 /* buf[0] holds the length in bytes */
866 if (xdr_int(xdrs, &(buf[0])) == 0)
877 if (xdr_opaque(xdrs, reinterpret_cast<char*>(&(buf[3])), static_cast<unsigned int>(buf[0])) == 0)
888 buf[0] = buf[1] = buf[2] = 0;
891 inv_precision = 1.0 / *precision;
897 thiscoord = reinterpret_cast<int*>(lip) + i * 3;
901 thiscoord[0] = receivebits(buf, bitsizeint[0]);
902 thiscoord[1] = receivebits(buf, bitsizeint[1]);
903 thiscoord[2] = receivebits(buf, bitsizeint[2]);
907 receiveints(buf, 3, bitsize, sizeint, thiscoord);
911 thiscoord[0] += minint[0];
912 thiscoord[1] += minint[1];
913 thiscoord[2] += minint[2];
915 prevcoord[0] = thiscoord[0];
916 prevcoord[1] = thiscoord[1];
917 prevcoord[2] = thiscoord[2];
920 flag = receivebits(buf, 1);
924 run = receivebits(buf, 5);
925 is_smaller = run % 3;
932 for (k = 0; k < run; k += 3)
934 receiveints(buf, 3, smallidx, sizesmall, thiscoord);
936 thiscoord[0] += prevcoord[0] - smallnum;
937 thiscoord[1] += prevcoord[1] - smallnum;
938 thiscoord[2] += prevcoord[2] - smallnum;
941 /* interchange first with second atom for better
942 * compression of water molecules
945 thiscoord[0] = prevcoord[0];
948 thiscoord[1] = prevcoord[1];
951 thiscoord[2] = prevcoord[2];
953 *lfp++ = prevcoord[0] * inv_precision;
954 *lfp++ = prevcoord[1] * inv_precision;
955 *lfp++ = prevcoord[2] * inv_precision;
959 prevcoord[0] = thiscoord[0];
960 prevcoord[1] = thiscoord[1];
961 prevcoord[2] = thiscoord[2];
963 *lfp++ = thiscoord[0] * inv_precision;
964 *lfp++ = thiscoord[1] * inv_precision;
965 *lfp++ = thiscoord[2] * inv_precision;
970 *lfp++ = thiscoord[0] * inv_precision;
971 *lfp++ = thiscoord[1] * inv_precision;
972 *lfp++ = thiscoord[2] * inv_precision;
974 smallidx += is_smaller;
978 if (smallidx > FIRSTIDX)
980 smaller = magicints[smallidx - 1] / 2;
987 else if (is_smaller > 0)
990 smallnum = magicints[smallidx] / 2;
992 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
1004 /******************************************************************
1006 XTC files have a relatively simple structure.
1007 They have a header of 16 bytes and the rest are
1008 the compressed coordinates of the files. Due to the
1009 compression 00 is not present in the coordinates.
1010 The first 4 bytes of the header are the magic number
1011 1995 (0x000007CB). If we find this number we are guaranteed
1012 to be in the header, due to the presence of so many zeros.
1013 The second 4 bytes are the number of atoms in the frame, and is
1014 assumed to be constant. The third 4 bytes are the frame number.
1015 The last 4 bytes are a floating point representation of the time.
1017 ********************************************************************/
1019 /* Must match definition in xtcio.c */
1021 # define XTC_MAGIC 1995
1024 static const int header_size = 16;
1026 /* Check if we are at the header start.
1027 At the same time it will also read 1 int */
1028 static int xtc_at_header_start(FILE* fp, XDR* xdrs, int natoms, int* timestep, float* time)
1036 if ((off = gmx_ftell(fp)) < 0)
1040 /* read magic natoms and timestep */
1041 for (i = 0; i < 3; i++)
1043 if (!xdr_int(xdrs, &(i_inp[i])))
1045 gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET);
1050 if (i_inp[0] != XTC_MAGIC)
1052 if (gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET))
1058 /* read time and box */
1059 for (i = 0; i < 10; i++)
1061 if (!xdr_float(xdrs, &(f_inp[i])))
1063 gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET);
1067 /* Make a rigourous check to see if we are in the beggining of a header
1068 Hopefully there are no ambiguous cases */
1069 /* This check makes use of the fact that the box matrix has 3 zeroes on the upper
1070 right triangle and that the first element must be nonzero unless the entire matrix is zero
1072 if (i_inp[1] == natoms
1073 && ((f_inp[1] != 0 && f_inp[6] == 0) || (f_inp[1] == 0 && f_inp[5] == 0 && f_inp[9] == 0)))
1075 if (gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET))
1080 *timestep = i_inp[2];
1083 if (gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET))
1090 static int xtc_get_next_frame_number(FILE* fp, XDR* xdrs, int natoms)
1097 if ((off = gmx_ftell(fp)) < 0)
1102 /* read one int just to make sure we dont read this frame but the next */
1103 xdr_int(xdrs, &step);
1106 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1109 if (gmx_fseek(fp, off, SEEK_SET))
1117 if (gmx_fseek(fp, off, SEEK_SET))
1126 static float xtc_get_next_frame_time(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1134 if ((off = gmx_ftell(fp)) < 0)
1138 /* read one int just to make sure we dont read this frame but the next */
1139 xdr_int(xdrs, &step);
1142 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1146 if (gmx_fseek(fp, off, SEEK_SET))
1155 if (gmx_fseek(fp, off, SEEK_SET))
1165 static float xtc_get_current_frame_time(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1173 if ((off = gmx_ftell(fp)) < 0)
1180 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1184 if (gmx_fseek(fp, off, SEEK_SET))
1193 if (gmx_fseek(fp, off, SEEK_SET))
1202 if (gmx_fseek(fp, -2 * XDR_INT_SIZE, SEEK_CUR))
1210 /* Currently not used, just for completeness */
1211 static int xtc_get_current_frame_number(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1219 if ((off = gmx_ftell(fp)) < 0)
1227 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1231 if (gmx_fseek(fp, off, SEEK_SET))
1240 if (gmx_fseek(fp, off, SEEK_SET))
1249 if (gmx_fseek(fp, -2 * XDR_INT_SIZE, SEEK_CUR))
1258 static gmx_off_t xtc_get_next_frame_start(FILE* fp, XDR* xdrs, int natoms)
1264 /* read one int just to make sure we dont read this frame but the next */
1265 xdr_int(xdrs, &step);
1268 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1271 if ((res = gmx_ftell(fp)) >= 0)
1273 return res - XDR_INT_SIZE;
1288 static float xdr_xtc_estimate_dt(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1295 if ((off = gmx_ftell(fp)) < 0)
1300 tinit = xtc_get_current_frame_time(fp, xdrs, natoms, bOK);
1307 res = xtc_get_next_frame_time(fp, xdrs, natoms, bOK);
1315 if (0 != gmx_fseek(fp, off, SEEK_SET))
1323 int xdr_xtc_seek_frame(int frame, FILE* fp, XDR* xdrs, int natoms)
1326 gmx_off_t high, pos;
1329 /* round to 4 bytes */
1332 if (gmx_fseek(fp, 0, SEEK_END))
1337 if ((high = gmx_ftell(fp)) < 0)
1342 /* round to 4 bytes */
1343 high /= XDR_INT_SIZE;
1344 high *= XDR_INT_SIZE;
1345 offset = ((high / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1347 if (gmx_fseek(fp, offset, SEEK_SET))
1354 fr = xtc_get_next_frame_number(fp, xdrs, natoms);
1359 if (fr != frame && llabs(low - high) > header_size)
1369 /* round to 4 bytes */
1370 offset = (((high + low) / 2) / 4) * 4;
1372 if (gmx_fseek(fp, offset, SEEK_SET))
1382 if (offset <= header_size)
1387 if (gmx_fseek(fp, offset, SEEK_SET))
1392 if ((pos = xtc_get_next_frame_start(fp, xdrs, natoms)) < 0)
1394 /* we probably hit an end of file */
1398 if (gmx_fseek(fp, pos, SEEK_SET))
1407 int xdr_xtc_seek_time(real time, FILE* fp, XDR* xdrs, int natoms, gmx_bool bSeekForwardOnly)
1411 gmx_bool bOK = FALSE;
1413 gmx_off_t high, offset, pos;
1416 if (bSeekForwardOnly)
1418 low = gmx_ftell(fp) - header_size;
1420 if (gmx_fseek(fp, 0, SEEK_END))
1425 if ((high = gmx_ftell(fp)) < 0)
1430 high /= XDR_INT_SIZE;
1431 high *= XDR_INT_SIZE;
1432 offset = (((high - low) / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1434 if (gmx_fseek(fp, offset, SEEK_SET))
1441 * No need to call xdr_xtc_estimate_dt here - since xdr_xtc_estimate_dt is called first thing in
1442 the loop dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1452 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1463 /* Found a place in the trajectory that has positive time step while
1464 other has negative time step */
1473 /* Found a place in the trajectory that has positive time step while
1474 other has negative time step */
1480 t = xtc_get_next_frame_time(fp, xdrs, natoms, &bOK);
1486 /* If we are before the target time and the time step is positive or 0, or we have
1487 after the target time and the time step is negative, or the difference between
1488 the current time and the target time is bigger than dt and above all the distance between
1489 high and low is bigger than 1 frame, then do another step of binary search. Otherwise
1490 stop and check if we reached the solution */
1491 if ((((t < time && dt_sign >= 0) || (t > time && dt_sign == -1))
1492 || ((t - time) >= dt && dt_sign >= 0) || ((time - t) >= -dt && dt_sign < 0))
1493 && (llabs(low - high) > header_size))
1495 if (dt >= 0 && dt_sign != -1)
1506 else if (dt <= 0 && dt_sign == -1)
1519 /* We should never reach here */
1522 /* round to 4 bytes and subtract header*/
1523 offset = (((high + low) / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1524 if (gmx_fseek(fp, offset, SEEK_SET))
1531 if (llabs(low - high) <= header_size)
1535 /* re-estimate dt */
1536 if (xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK) != dt)
1540 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1543 if (t >= time && t - time < dt)
1550 if (offset <= header_size)
1555 gmx_fseek(fp, offset, SEEK_SET);
1557 if ((pos = xtc_get_next_frame_start(fp, xdrs, natoms)) < 0)
1562 if (gmx_fseek(fp, pos, SEEK_SET))
1569 float xdr_xtc_get_last_frame_time(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1574 off = gmx_ftell(fp);
1581 if (gmx_fseek(fp, -3 * XDR_INT_SIZE, SEEK_END) != 0)
1587 time = xtc_get_current_frame_time(fp, xdrs, natoms, bOK);
1593 if (gmx_fseek(fp, off, SEEK_SET) != 0)
1602 int xdr_xtc_get_last_frame_number(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1608 if ((off = gmx_ftell(fp)) < 0)
1615 if (gmx_fseek(fp, -3 * XDR_INT_SIZE, SEEK_END))
1621 frame = xtc_get_current_frame_number(fp, xdrs, natoms, bOK);
1628 if (gmx_fseek(fp, off, SEEK_SET))