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 by the GROMACS development team.
7 * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
8 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9 * and including many others, as listed in the AUTHORS file in the
10 * top-level source directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
48 #include "gromacs/fileio/xdr_datatype.h"
49 #include "gromacs/fileio/xdrf.h"
50 #include "gromacs/utility/futil.h"
52 /* This is just for clarity - it can never be anything but 4! */
53 #define XDR_INT_SIZE 4
55 /* same order as the definition of xdr_datatype */
56 const char* xdr_datatype_names[] = { "int", "float", "double", "large int", "char", "string" };
59 /*___________________________________________________________________________
61 | what follows are the C routine to read/write compressed coordinates together
62 | with some routines to assist in this task (those are marked
63 | static and cannot be called from user programs)
66 // Integers above 2^24 do not have unique representations in
67 // 32-bit floats ie with 24 bits of precision. We use maxAbsoluteInt
68 // to check that float values can be transformed into an in-range
69 // 32-bit integer. There is no need to ensure we are within the range
70 // of ints with exact floating-point representations. However, we should
71 // reject all floats above that which converts to an in-range 32-bit integer.
72 const float maxAbsoluteInt = nextafterf(float(INT_MAX), 0.F); // NOLINT(cert-err58-cpp)
75 # define SQR(x) ((x) * (x))
77 static const int magicints[] = {
78 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,
79 10, 12, 16, 20, 25, 32, 40, 50, 64, 80,
80 101, 128, 161, 203, 256, 322, 406, 512, 645, 812,
81 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501, 8192,
82 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536, 82570,
83 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561, 832255,
84 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042, 8388607,
85 10568983, 13316085, 16777216
89 /* note that magicints[FIRSTIDX-1] == 0 */
90 #define LASTIDX static_cast<int>((sizeof(magicints) / sizeof(*magicints)))
93 /*____________________________________________________________________________
95 | sendbits - encode num into buf using the specified number of bits
97 | This routines appends the value of num to the bits already present in
98 | the array buf. You need to give it the number of bits to use and you
99 | better make sure that this number of bits is enough to hold the value
100 | Also num must be positive.
104 static void sendbits(int buf[], int num_of_bits, int num)
107 unsigned int cnt, lastbyte;
111 cbuf = (reinterpret_cast<unsigned char*>(buf)) + 3 * sizeof(*buf);
112 cnt = static_cast<unsigned int>(buf[0]);
114 lastbyte = static_cast<unsigned int>(buf[2]);
115 while (num_of_bits >= 8)
117 lastbyte = (lastbyte << 8) | ((num >> (num_of_bits - 8)) /* & 0xff*/);
118 cbuf[cnt++] = lastbyte >> lastbits;
123 lastbyte = (lastbyte << num_of_bits) | num;
124 lastbits += num_of_bits;
128 cbuf[cnt++] = lastbyte >> lastbits;
136 cbuf[cnt] = lastbyte << (8 - lastbits);
140 /*_________________________________________________________________________
142 | sizeofint - calculate bitsize of an integer
144 | return the number of bits needed to store an integer with given max size
148 static int sizeofint(const int size)
153 while (size >= num && num_of_bits < 32)
161 /*___________________________________________________________________________
163 | sizeofints - calculate 'bitsize' of compressed ints
165 | given the number of small unsigned integers and the maximum value
166 | return the number of bits needed to read or write them with the
167 | routines receiveints and sendints. You need this parameter when
168 | calling these routines. Note that for many calls I can use
169 | the variable 'smallidx' which is exactly the number of bits, and
170 | So I don't need to call 'sizeofints for those calls.
173 static int sizeofints(const int num_of_ints, const unsigned int sizes[])
177 unsigned int num_of_bytes, num_of_bits, bytecnt, tmp;
181 for (i = 0; i < num_of_ints; i++)
184 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++)
186 tmp = bytes[bytecnt] * sizes[i] + tmp;
187 bytes[bytecnt] = tmp & 0xff;
192 bytes[bytecnt++] = tmp & 0xff;
195 num_of_bytes = bytecnt;
199 while (bytes[num_of_bytes] >= num)
204 return num_of_bits + num_of_bytes * 8;
207 /*____________________________________________________________________________
209 | sendints - send a small set of small integers in compressed format
211 | this routine is used internally by xdr3dfcoord, to send a set of
212 | small integers to the buffer.
213 | Multiplication with fixed (specified maximum ) sizes is used to get
214 | to one big, multibyte integer. Allthough the routine could be
215 | modified to handle sizes bigger than 16777216, or more than just
216 | a few integers, this is not done, because the gain in compression
217 | isn't worth the effort. Note that overflowing the multiplication
218 | or the byte buffer (32 bytes) is unchecked and causes bad results.
222 static void sendints(int buf[],
223 const int num_of_ints,
224 const int num_of_bits,
225 unsigned int sizes[],
229 int i, num_of_bytes, bytecnt;
230 unsigned int bytes[32], tmp;
236 bytes[num_of_bytes++] = tmp & 0xff;
240 for (i = 1; i < num_of_ints; i++)
242 if (nums[i] >= sizes[i])
245 "major breakdown in sendints num %u doesn't "
251 /* use one step multiply */
253 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++)
255 tmp = bytes[bytecnt] * sizes[i] + tmp;
256 bytes[bytecnt] = tmp & 0xff;
261 bytes[bytecnt++] = tmp & 0xff;
264 num_of_bytes = bytecnt;
266 if (num_of_bits >= num_of_bytes * 8)
268 for (i = 0; i < num_of_bytes; i++)
270 sendbits(buf, 8, bytes[i]);
272 sendbits(buf, num_of_bits - num_of_bytes * 8, 0);
276 for (i = 0; i < num_of_bytes - 1; i++)
278 sendbits(buf, 8, bytes[i]);
280 sendbits(buf, num_of_bits - (num_of_bytes - 1) * 8, bytes[i]);
285 /*___________________________________________________________________________
287 | receivebits - decode number from buf using specified number of bits
289 | extract the number of bits from the array buf and construct an integer
290 | from it. Return that value.
294 static int receivebits(int buf[], int num_of_bits)
297 int cnt, num, lastbits;
298 unsigned int lastbyte;
300 int mask = (1 << num_of_bits) - 1;
302 cbuf = reinterpret_cast<unsigned char*>(buf) + 3 * sizeof(*buf);
304 lastbits = static_cast<unsigned int>(buf[1]);
305 lastbyte = static_cast<unsigned int>(buf[2]);
308 while (num_of_bits >= 8)
310 lastbyte = (lastbyte << 8) | cbuf[cnt++];
311 num |= (lastbyte >> lastbits) << (num_of_bits - 8);
316 if (lastbits < num_of_bits)
319 lastbyte = (lastbyte << 8) | cbuf[cnt++];
321 lastbits -= num_of_bits;
322 num |= (lastbyte >> lastbits) & ((1 << num_of_bits) - 1);
331 /*____________________________________________________________________________
333 | receiveints - decode 'small' integers from the buf array
335 | this routine is the inverse from sendints() and decodes the small integers
336 | written to buf by calculating the remainder and doing divisions with
337 | the given sizes[]. You need to specify the total number of bits to be
338 | used from buf in num_of_bits.
342 static void receiveints(int buf[], const int num_of_ints, int num_of_bits, const unsigned int sizes[], int nums[])
345 int i, j, num_of_bytes, p, num;
347 bytes[0] = bytes[1] = bytes[2] = bytes[3] = 0;
349 while (num_of_bits > 8)
351 bytes[num_of_bytes++] = receivebits(buf, 8);
356 bytes[num_of_bytes++] = receivebits(buf, num_of_bits);
358 for (i = num_of_ints - 1; i > 0; i--)
361 for (j = num_of_bytes - 1; j >= 0; j--)
363 num = (num << 8) | bytes[j];
366 num = num - p * sizes[i];
370 nums[0] = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
373 /*____________________________________________________________________________
375 | xdr3dfcoord - read or write compressed 3d coordinates to xdr file.
377 | this routine reads or writes (depending on how you opened the file with
378 | xdropen() ) a large number of 3d coordinates (stored in *fp).
379 | The number of coordinates triplets to write is given by *size. On
380 | read this number may be zero, in which case it reads as many as were written
381 | or it may specify the number if triplets to read (which should match the
383 | Compression is achieved by first converting all floating numbers to integer
384 | using multiplication by *precision and rounding to the nearest integer.
385 | Then the minimum and maximum value are calculated to determine the range.
386 | The limited range of integers so found, is used to compress the coordinates.
387 | In addition the differences between succesive coordinates is calculated.
388 | If the difference happens to be 'small' then only the difference is saved,
389 | compressing the data even more. The notion of 'small' is changed dynamically
390 | and is enlarged or reduced whenever needed or possible.
391 | Extra compression is achieved in the case of GROMOS and coordinates of
392 | water molecules. GROMOS first writes out the Oxygen position, followed by
393 | the two hydrogens. In order to make the differences smaller (and thereby
394 | compression the data better) the order is changed into first one hydrogen
395 | then the oxygen, followed by the other hydrogen. This is rather special, but
396 | it shouldn't harm in the general case.
400 int xdr3dfcoord(XDR* xdrs, float* fp, int* size, float* precision)
406 /* preallocate a small buffer and ip on the stack - if we need more
407 we can always malloc(). This is faster for small values of size: */
408 unsigned prealloc_size = 3 * 16;
409 int prealloc_ip[3 * 16], prealloc_buf[3 * 20];
410 int we_should_free = 0;
412 int minint[3], maxint[3], mindiff, *lip, diff;
413 int lint1, lint2, lint3, oldlint1, oldlint2, oldlint3, smallidx;
415 unsigned sizeint[3], sizesmall[3], bitsizeint[3], size3, *luip;
417 int smallnum, smaller, larger, i, is_small, is_smaller, run, prevrun;
419 int tmp, *thiscoord, prevcoord[3];
420 unsigned int tmpcoord[30];
423 unsigned int bitsize;
428 bRead = (xdrs->x_op == XDR_DECODE);
429 bitsizeint[0] = bitsizeint[1] = bitsizeint[2] = 0;
430 prevcoord[0] = prevcoord[1] = prevcoord[2] = 0;
432 // The static analyzer warns about garbage values for thiscoord[] further
433 // down. It might be thrown off by all the reinterpret_casts, but we might
434 // as well make sure the small preallocated buffer is zero-initialized.
435 for (i = 0; i < static_cast<int>(prealloc_size); i++)
442 /* xdrs is open for writing */
444 if (xdr_int(xdrs, size) == 0)
449 /* when the number of coordinates is small, don't try to compress; just
450 * write them as floats using xdr_vector
454 return (xdr_vector(xdrs,
455 reinterpret_cast<char*>(fp),
456 static_cast<unsigned int>(size3),
457 static_cast<unsigned int>(sizeof(*fp)),
458 reinterpret_cast<xdrproc_t>(xdr_float)));
461 if (xdr_float(xdrs, precision) == 0)
466 if (size3 <= prealloc_size)
474 bufsize = static_cast<int>(size3 * 1.2);
475 ip = reinterpret_cast<int*>(malloc(size3 * sizeof(*ip)));
476 buf = reinterpret_cast<int*>(malloc(bufsize * sizeof(*buf)));
477 if (ip == nullptr || buf == nullptr)
479 fprintf(stderr, "malloc failed\n");
483 /* buf[0-2] are special and do not contain actual data */
484 buf[0] = buf[1] = buf[2] = 0;
485 minint[0] = minint[1] = minint[2] = INT_MAX;
486 maxint[0] = maxint[1] = maxint[2] = INT_MIN;
491 oldlint1 = oldlint2 = oldlint3 = 0;
492 while (lfp < fp + size3)
494 /* find nearest integer */
497 lf = *lfp * *precision + 0.5;
501 lf = *lfp * *precision - 0.5;
503 if (std::fabs(lf) > maxAbsoluteInt)
505 /* scaling would cause overflow */
508 lint1 = static_cast<int>(lf);
509 if (lint1 < minint[0])
513 if (lint1 > maxint[0])
521 lf = *lfp * *precision + 0.5;
525 lf = *lfp * *precision - 0.5;
527 if (std::fabs(lf) > maxAbsoluteInt)
529 /* scaling would cause overflow */
532 lint2 = static_cast<int>(lf);
533 if (lint2 < minint[1])
537 if (lint2 > maxint[1])
545 lf = *lfp * *precision + 0.5;
549 lf = *lfp * *precision - 0.5;
551 if (std::abs(lf) > maxAbsoluteInt)
553 /* scaling would cause overflow */
556 lint3 = static_cast<int>(lf);
557 if (lint3 < minint[2])
561 if (lint3 > maxint[2])
567 diff = std::abs(oldlint1 - lint1) + std::abs(oldlint2 - lint2) + std::abs(oldlint3 - lint3);
568 if (diff < mindiff && lfp > fp + 3)
576 if ((xdr_int(xdrs, &(minint[0])) == 0) || (xdr_int(xdrs, &(minint[1])) == 0)
577 || (xdr_int(xdrs, &(minint[2])) == 0) || (xdr_int(xdrs, &(maxint[0])) == 0)
578 || (xdr_int(xdrs, &(maxint[1])) == 0) || (xdr_int(xdrs, &(maxint[2])) == 0))
588 if (static_cast<float>(maxint[0]) - static_cast<float>(minint[0]) >= maxAbsoluteInt
589 || static_cast<float>(maxint[1]) - static_cast<float>(minint[1]) >= maxAbsoluteInt
590 || static_cast<float>(maxint[2]) - static_cast<float>(minint[2]) >= maxAbsoluteInt)
592 /* turning value in unsigned by subtracting minint
593 * would cause overflow
597 sizeint[0] = maxint[0] - minint[0] + 1;
598 sizeint[1] = maxint[1] - minint[1] + 1;
599 sizeint[2] = maxint[2] - minint[2] + 1;
601 /* check if one of the sizes is to big to be multiplied */
602 if ((sizeint[0] | sizeint[1] | sizeint[2]) > 0xffffff)
604 bitsizeint[0] = sizeofint(sizeint[0]);
605 bitsizeint[1] = sizeofint(sizeint[1]);
606 bitsizeint[2] = sizeofint(sizeint[2]);
607 bitsize = 0; /* flag the use of large sizes */
611 bitsize = sizeofints(3, sizeint);
613 luip = reinterpret_cast<unsigned int*>(ip);
615 while (smallidx < LASTIDX && magicints[smallidx] < mindiff)
619 if (xdr_int(xdrs, &smallidx) == 0)
629 maxidx = std::min(LASTIDX, smallidx + 8);
630 minidx = maxidx - 8; /* often this equal smallidx */
631 smaller = magicints[std::max(FIRSTIDX, smallidx - 1)] / 2;
632 smallnum = magicints[smallidx] / 2;
633 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
634 larger = magicints[maxidx] / 2;
639 thiscoord = reinterpret_cast<int*>(luip) + i * 3;
640 if (smallidx < maxidx && i >= 1 && std::abs(thiscoord[0] - prevcoord[0]) < larger
641 && std::abs(thiscoord[1] - prevcoord[1]) < larger
642 && std::abs(thiscoord[2] - prevcoord[2]) < larger)
646 else if (smallidx > minidx)
656 if (std::abs(thiscoord[0] - thiscoord[3]) < smallnum
657 && std::abs(thiscoord[1] - thiscoord[4]) < smallnum
658 && std::abs(thiscoord[2] - thiscoord[5]) < smallnum)
660 /* interchange first with second atom for better
661 * compression of water molecules
664 thiscoord[0] = thiscoord[3];
667 thiscoord[1] = thiscoord[4];
670 thiscoord[2] = thiscoord[5];
675 tmpcoord[0] = thiscoord[0] - minint[0];
676 tmpcoord[1] = thiscoord[1] - minint[1];
677 tmpcoord[2] = thiscoord[2] - minint[2];
680 sendbits(buf, bitsizeint[0], tmpcoord[0]);
681 sendbits(buf, bitsizeint[1], tmpcoord[1]);
682 sendbits(buf, bitsizeint[2], tmpcoord[2]);
686 sendints(buf, 3, bitsize, sizeint, tmpcoord);
688 prevcoord[0] = thiscoord[0];
689 prevcoord[1] = thiscoord[1];
690 prevcoord[2] = thiscoord[2];
691 thiscoord = thiscoord + 3;
695 if (is_small == 0 && is_smaller == -1)
699 while (is_small && run < 8 * 3)
702 && (SQR(thiscoord[0] - prevcoord[0]) + SQR(thiscoord[1] - prevcoord[1])
703 + SQR(thiscoord[2] - prevcoord[2])
704 >= smaller * smaller))
709 tmpcoord[run++] = thiscoord[0] - prevcoord[0] + smallnum;
710 tmpcoord[run++] = thiscoord[1] - prevcoord[1] + smallnum;
711 tmpcoord[run++] = thiscoord[2] - prevcoord[2] + smallnum;
713 prevcoord[0] = thiscoord[0];
714 prevcoord[1] = thiscoord[1];
715 prevcoord[2] = thiscoord[2];
718 thiscoord = thiscoord + 3;
720 if (i < *size && abs(thiscoord[0] - prevcoord[0]) < smallnum
721 && abs(thiscoord[1] - prevcoord[1]) < smallnum
722 && abs(thiscoord[2] - prevcoord[2]) < smallnum)
727 if (run != prevrun || is_smaller != 0)
730 sendbits(buf, 1, 1); /* flag the change in run-length */
731 sendbits(buf, 5, run + is_smaller + 1);
735 sendbits(buf, 1, 0); /* flag the fact that runlength did not change */
737 for (k = 0; k < run; k += 3)
739 sendints(buf, 3, smallidx, sizesmall, &tmpcoord[k]);
743 smallidx += is_smaller;
747 smaller = magicints[smallidx - 1] / 2;
752 smallnum = magicints[smallidx] / 2;
754 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
761 /* buf[0] holds the length in bytes */
762 if (xdr_int(xdrs, &(buf[0])) == 0)
774 * (xdr_opaque(xdrs, reinterpret_cast<char*>(&(buf[3])), static_cast<unsigned int>(buf[0])));
785 /* xdrs is open for reading */
787 if (xdr_int(xdrs, &lsize) == 0)
791 if (*size != 0 && lsize != *size)
794 "wrong number of coordinates in xdr3dfcoord; "
795 "%d arg vs %d in file",
804 return (xdr_vector(xdrs,
805 reinterpret_cast<char*>(fp),
806 static_cast<unsigned int>(size3),
807 static_cast<unsigned int>(sizeof(*fp)),
808 reinterpret_cast<xdrproc_t>(xdr_float)));
810 if (xdr_float(xdrs, precision) == 0)
815 if (size3 <= prealloc_size)
823 bufsize = static_cast<int>(size3 * 1.2);
824 ip = reinterpret_cast<int*>(malloc(size3 * sizeof(*ip)));
825 buf = reinterpret_cast<int*>(malloc(bufsize * sizeof(*buf)));
826 if (ip == nullptr || buf == nullptr)
828 fprintf(stderr, "malloc failed\n");
833 buf[0] = buf[1] = buf[2] = 0;
835 if ((xdr_int(xdrs, &(minint[0])) == 0) || (xdr_int(xdrs, &(minint[1])) == 0)
836 || (xdr_int(xdrs, &(minint[2])) == 0) || (xdr_int(xdrs, &(maxint[0])) == 0)
837 || (xdr_int(xdrs, &(maxint[1])) == 0) || (xdr_int(xdrs, &(maxint[2])) == 0))
847 sizeint[0] = maxint[0] - minint[0] + 1;
848 sizeint[1] = maxint[1] - minint[1] + 1;
849 sizeint[2] = maxint[2] - minint[2] + 1;
851 /* check if one of the sizes is to big to be multiplied */
852 if ((sizeint[0] | sizeint[1] | sizeint[2]) > 0xffffff)
854 bitsizeint[0] = sizeofint(sizeint[0]);
855 bitsizeint[1] = sizeofint(sizeint[1]);
856 bitsizeint[2] = sizeofint(sizeint[2]);
857 bitsize = 0; /* flag the use of large sizes */
861 bitsize = sizeofints(3, sizeint);
864 if (xdr_int(xdrs, &smallidx) == 0)
874 smaller = magicints[std::max(FIRSTIDX, smallidx - 1)] / 2;
875 smallnum = magicints[smallidx] / 2;
876 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
878 /* buf[0] holds the length in bytes */
880 if (xdr_int(xdrs, &(buf[0])) == 0)
891 if (xdr_opaque(xdrs, reinterpret_cast<char*>(&(buf[3])), static_cast<unsigned int>(buf[0])) == 0)
902 buf[0] = buf[1] = buf[2] = 0;
905 inv_precision = 1.0 / *precision;
911 thiscoord = reinterpret_cast<int*>(lip) + i * 3;
915 thiscoord[0] = receivebits(buf, bitsizeint[0]);
916 thiscoord[1] = receivebits(buf, bitsizeint[1]);
917 thiscoord[2] = receivebits(buf, bitsizeint[2]);
921 receiveints(buf, 3, bitsize, sizeint, thiscoord);
925 thiscoord[0] += minint[0];
926 thiscoord[1] += minint[1];
927 thiscoord[2] += minint[2];
929 prevcoord[0] = thiscoord[0];
930 prevcoord[1] = thiscoord[1];
931 prevcoord[2] = thiscoord[2];
934 flag = receivebits(buf, 1);
938 run = receivebits(buf, 5);
939 is_smaller = run % 3;
946 for (k = 0; k < run; k += 3)
948 receiveints(buf, 3, smallidx, sizesmall, thiscoord);
950 thiscoord[0] += prevcoord[0] - smallnum;
951 thiscoord[1] += prevcoord[1] - smallnum;
952 thiscoord[2] += prevcoord[2] - smallnum;
955 /* interchange first with second atom for better
956 * compression of water molecules
959 thiscoord[0] = prevcoord[0];
962 thiscoord[1] = prevcoord[1];
965 thiscoord[2] = prevcoord[2];
967 *lfp++ = prevcoord[0] * inv_precision;
968 *lfp++ = prevcoord[1] * inv_precision;
969 *lfp++ = prevcoord[2] * inv_precision;
973 prevcoord[0] = thiscoord[0];
974 prevcoord[1] = thiscoord[1];
975 prevcoord[2] = thiscoord[2];
977 *lfp++ = thiscoord[0] * inv_precision;
978 *lfp++ = thiscoord[1] * inv_precision;
979 *lfp++ = thiscoord[2] * inv_precision;
984 *lfp++ = thiscoord[0] * inv_precision;
985 *lfp++ = thiscoord[1] * inv_precision;
986 *lfp++ = thiscoord[2] * inv_precision;
988 smallidx += is_smaller;
992 if (smallidx > FIRSTIDX)
994 smaller = magicints[smallidx - 1] / 2;
1001 else if (is_smaller > 0)
1004 smallnum = magicints[smallidx] / 2;
1006 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
1018 /******************************************************************
1020 XTC files have a relatively simple structure.
1021 They have a header of 16 bytes and the rest are
1022 the compressed coordinates of the files. Due to the
1023 compression 00 is not present in the coordinates.
1024 The first 4 bytes of the header are the magic number
1025 1995 (0x000007CB). If we find this number we are guaranteed
1026 to be in the header, due to the presence of so many zeros.
1027 The second 4 bytes are the number of atoms in the frame, and is
1028 assumed to be constant. The third 4 bytes are the frame number.
1029 The last 4 bytes are a floating point representation of the time.
1031 ********************************************************************/
1033 /* Must match definition in xtcio.c */
1035 # define XTC_MAGIC 1995
1038 static const int header_size = 16;
1040 /* Check if we are at the header start.
1041 At the same time it will also read 1 int */
1042 static int xtc_at_header_start(FILE* fp, XDR* xdrs, int natoms, int* timestep, float* time)
1050 if ((off = gmx_ftell(fp)) < 0)
1054 /* read magic natoms and timestep */
1055 for (i = 0; i < 3; i++)
1057 if (!xdr_int(xdrs, &(i_inp[i])))
1059 gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET);
1064 if (i_inp[0] != XTC_MAGIC)
1066 if (gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET))
1072 /* read time and box */
1073 for (i = 0; i < 10; i++)
1075 if (!xdr_float(xdrs, &(f_inp[i])))
1077 gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET);
1081 /* Make a rigourous check to see if we are in the beggining of a header
1082 Hopefully there are no ambiguous cases */
1083 /* This check makes use of the fact that the box matrix has 3 zeroes on the upper
1084 right triangle and that the first element must be nonzero unless the entire matrix is zero
1086 if (i_inp[1] == natoms
1087 && ((f_inp[1] != 0 && f_inp[6] == 0) || (f_inp[1] == 0 && f_inp[5] == 0 && f_inp[9] == 0)))
1089 if (gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET))
1094 *timestep = i_inp[2];
1097 if (gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET))
1104 static int xtc_get_next_frame_number(FILE* fp, XDR* xdrs, int natoms)
1111 if ((off = gmx_ftell(fp)) < 0)
1116 /* read one int just to make sure we dont read this frame but the next */
1117 xdr_int(xdrs, &step);
1120 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1123 if (gmx_fseek(fp, off, SEEK_SET))
1131 if (gmx_fseek(fp, off, SEEK_SET))
1140 static float xtc_get_next_frame_time(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1148 if ((off = gmx_ftell(fp)) < 0)
1152 /* read one int just to make sure we dont read this frame but the next */
1153 xdr_int(xdrs, &step);
1156 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1160 if (gmx_fseek(fp, off, SEEK_SET))
1169 if (gmx_fseek(fp, off, SEEK_SET))
1179 static float xtc_get_current_frame_time(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1187 if ((off = gmx_ftell(fp)) < 0)
1194 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1198 if (gmx_fseek(fp, off, SEEK_SET))
1207 if (gmx_fseek(fp, off, SEEK_SET))
1216 if (gmx_fseek(fp, -2 * XDR_INT_SIZE, SEEK_CUR))
1224 /* Currently not used, just for completeness */
1225 static int xtc_get_current_frame_number(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1233 if ((off = gmx_ftell(fp)) < 0)
1241 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1245 if (gmx_fseek(fp, off, SEEK_SET))
1254 if (gmx_fseek(fp, off, SEEK_SET))
1263 if (gmx_fseek(fp, -2 * XDR_INT_SIZE, SEEK_CUR))
1272 static gmx_off_t xtc_get_next_frame_start(FILE* fp, XDR* xdrs, int natoms)
1278 /* read one int just to make sure we dont read this frame but the next */
1279 xdr_int(xdrs, &step);
1282 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1285 if ((res = gmx_ftell(fp)) >= 0)
1287 return res - XDR_INT_SIZE;
1302 static float xdr_xtc_estimate_dt(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1309 if ((off = gmx_ftell(fp)) < 0)
1314 tinit = xtc_get_current_frame_time(fp, xdrs, natoms, bOK);
1321 res = xtc_get_next_frame_time(fp, xdrs, natoms, bOK);
1329 if (0 != gmx_fseek(fp, off, SEEK_SET))
1337 int xdr_xtc_seek_frame(int frame, FILE* fp, XDR* xdrs, int natoms)
1340 gmx_off_t high, pos;
1343 /* round to 4 bytes */
1346 if (gmx_fseek(fp, 0, SEEK_END))
1351 if ((high = gmx_ftell(fp)) < 0)
1356 /* round to 4 bytes */
1357 high /= XDR_INT_SIZE;
1358 high *= XDR_INT_SIZE;
1359 offset = ((high / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1361 if (gmx_fseek(fp, offset, SEEK_SET))
1368 fr = xtc_get_next_frame_number(fp, xdrs, natoms);
1373 if (fr != frame && llabs(low - high) > header_size)
1383 /* round to 4 bytes */
1384 offset = (((high + low) / 2) / 4) * 4;
1386 if (gmx_fseek(fp, offset, SEEK_SET))
1396 if (offset <= header_size)
1401 if (gmx_fseek(fp, offset, SEEK_SET))
1406 if ((pos = xtc_get_next_frame_start(fp, xdrs, natoms)) < 0)
1408 /* we probably hit an end of file */
1412 if (gmx_fseek(fp, pos, SEEK_SET))
1421 int xdr_xtc_seek_time(real time, FILE* fp, XDR* xdrs, int natoms, gmx_bool bSeekForwardOnly)
1425 gmx_bool bOK = FALSE;
1427 gmx_off_t high, offset, pos;
1430 if (bSeekForwardOnly)
1432 low = gmx_ftell(fp) - header_size;
1434 if (gmx_fseek(fp, 0, SEEK_END))
1439 if ((high = gmx_ftell(fp)) < 0)
1444 high /= XDR_INT_SIZE;
1445 high *= XDR_INT_SIZE;
1446 offset = (((high - low) / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1448 if (gmx_fseek(fp, offset, SEEK_SET))
1455 * No need to call xdr_xtc_estimate_dt here - since xdr_xtc_estimate_dt is called first thing in
1456 the loop dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1466 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1477 /* Found a place in the trajectory that has positive time step while
1478 other has negative time step */
1487 /* Found a place in the trajectory that has positive time step while
1488 other has negative time step */
1494 t = xtc_get_next_frame_time(fp, xdrs, natoms, &bOK);
1500 /* If we are before the target time and the time step is positive or 0, or we have
1501 after the target time and the time step is negative, or the difference between
1502 the current time and the target time is bigger than dt and above all the distance between
1503 high and low is bigger than 1 frame, then do another step of binary search. Otherwise
1504 stop and check if we reached the solution */
1505 if ((((t < time && dt_sign >= 0) || (t > time && dt_sign == -1))
1506 || ((t - time) >= dt && dt_sign >= 0) || ((time - t) >= -dt && dt_sign < 0))
1507 && (llabs(low - high) > header_size))
1509 if (dt >= 0 && dt_sign != -1)
1520 else if (dt <= 0 && dt_sign == -1)
1533 /* We should never reach here */
1536 /* round to 4 bytes and subtract header*/
1537 offset = (((high + low) / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1538 if (gmx_fseek(fp, offset, SEEK_SET))
1545 if (llabs(low - high) <= header_size)
1549 /* re-estimate dt */
1550 if (xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK) != dt)
1554 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1557 if (t >= time && t - time < dt)
1564 if (offset <= header_size)
1569 gmx_fseek(fp, offset, SEEK_SET);
1571 if ((pos = xtc_get_next_frame_start(fp, xdrs, natoms)) < 0)
1576 if (gmx_fseek(fp, pos, SEEK_SET))
1583 float xdr_xtc_get_last_frame_time(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1588 off = gmx_ftell(fp);
1595 if (gmx_fseek(fp, -3 * XDR_INT_SIZE, SEEK_END) != 0)
1601 time = xtc_get_current_frame_time(fp, xdrs, natoms, bOK);
1607 if (gmx_fseek(fp, off, SEEK_SET) != 0)
1616 int xdr_xtc_get_last_frame_number(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1622 if ((off = gmx_ftell(fp)) < 0)
1629 if (gmx_fseek(fp, -3 * XDR_INT_SIZE, SEEK_END))
1635 frame = xtc_get_current_frame_number(fp, xdrs, natoms, bOK);
1642 if (gmx_fseek(fp, off, SEEK_SET))