Separate job script files for gmxapi package versions.
[gromacs.git] / src / gromacs / fileio / libxdrf.cpp
blob2e64a58682fefd055129d30dc6fabb02b87d774d
1 /*
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.
38 #include "gmxpre.h"
40 #include <climits>
41 #include <cmath>
42 #include <cstdio>
43 #include <cstdlib>
44 #include <cstring>
46 #include <algorithm>
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)
74 #ifndef SQR
75 # define SQR(x) ((x) * (x))
76 #endif
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
88 #define FIRSTIDX 9
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;
108 int lastbits;
109 unsigned char* cbuf;
111 cbuf = (reinterpret_cast<unsigned char*>(buf)) + 3 * sizeof(*buf);
112 cnt = static_cast<unsigned int>(buf[0]);
113 lastbits = buf[1];
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;
119 num_of_bits -= 8;
121 if (num_of_bits > 0)
123 lastbyte = (lastbyte << num_of_bits) | num;
124 lastbits += num_of_bits;
125 if (lastbits >= 8)
127 lastbits -= 8;
128 cbuf[cnt++] = lastbyte >> lastbits;
131 buf[0] = cnt;
132 buf[1] = lastbits;
133 buf[2] = lastbyte;
134 if (lastbits > 0)
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)
150 int num = 1;
151 int num_of_bits = 0;
153 while (size >= num && num_of_bits < 32)
155 num_of_bits++;
156 num <<= 1;
158 return num_of_bits;
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[])
175 int i, num;
176 int bytes[32];
177 unsigned int num_of_bytes, num_of_bits, bytecnt, tmp;
178 num_of_bytes = 1;
179 bytes[0] = 1;
180 num_of_bits = 0;
181 for (i = 0; i < num_of_ints; i++)
183 tmp = 0;
184 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++)
186 tmp = bytes[bytecnt] * sizes[i] + tmp;
187 bytes[bytecnt] = tmp & 0xff;
188 tmp >>= 8;
190 while (tmp != 0)
192 bytes[bytecnt++] = tmp & 0xff;
193 tmp >>= 8;
195 num_of_bytes = bytecnt;
197 num = 1;
198 num_of_bytes--;
199 while (bytes[num_of_bytes] >= num)
201 num_of_bits++;
202 num *= 2;
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[],
226 unsigned int nums[])
229 int i, num_of_bytes, bytecnt;
230 unsigned int bytes[32], tmp;
232 tmp = nums[0];
233 num_of_bytes = 0;
236 bytes[num_of_bytes++] = tmp & 0xff;
237 tmp >>= 8;
238 } while (tmp != 0);
240 for (i = 1; i < num_of_ints; i++)
242 if (nums[i] >= sizes[i])
244 fprintf(stderr,
245 "major breakdown in sendints num %u doesn't "
246 "match size %u\n",
247 nums[i], sizes[i]);
248 exit(1);
250 /* use one step multiply */
251 tmp = nums[i];
252 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++)
254 tmp = bytes[bytecnt] * sizes[i] + tmp;
255 bytes[bytecnt] = tmp & 0xff;
256 tmp >>= 8;
258 while (tmp != 0)
260 bytes[bytecnt++] = tmp & 0xff;
261 tmp >>= 8;
263 num_of_bytes = bytecnt;
265 if (num_of_bits >= num_of_bytes * 8)
267 for (i = 0; i < num_of_bytes; i++)
269 sendbits(buf, 8, bytes[i]);
271 sendbits(buf, num_of_bits - num_of_bytes * 8, 0);
273 else
275 for (i = 0; i < num_of_bytes - 1; i++)
277 sendbits(buf, 8, bytes[i]);
279 sendbits(buf, num_of_bits - (num_of_bytes - 1) * 8, bytes[i]);
284 /*___________________________________________________________________________
286 | receivebits - decode number from buf using specified number of bits
288 | extract the number of bits from the array buf and construct an integer
289 | from it. Return that value.
293 static int receivebits(int buf[], int num_of_bits)
296 int cnt, num, lastbits;
297 unsigned int lastbyte;
298 unsigned char* cbuf;
299 int mask = (1 << num_of_bits) - 1;
301 cbuf = reinterpret_cast<unsigned char*>(buf) + 3 * sizeof(*buf);
302 cnt = buf[0];
303 lastbits = static_cast<unsigned int>(buf[1]);
304 lastbyte = static_cast<unsigned int>(buf[2]);
306 num = 0;
307 while (num_of_bits >= 8)
309 lastbyte = (lastbyte << 8) | cbuf[cnt++];
310 num |= (lastbyte >> lastbits) << (num_of_bits - 8);
311 num_of_bits -= 8;
313 if (num_of_bits > 0)
315 if (lastbits < num_of_bits)
317 lastbits += 8;
318 lastbyte = (lastbyte << 8) | cbuf[cnt++];
320 lastbits -= num_of_bits;
321 num |= (lastbyte >> lastbits) & ((1 << num_of_bits) - 1);
323 num &= mask;
324 buf[0] = cnt;
325 buf[1] = lastbits;
326 buf[2] = lastbyte;
327 return num;
330 /*____________________________________________________________________________
332 | receiveints - decode 'small' integers from the buf array
334 | this routine is the inverse from sendints() and decodes the small integers
335 | written to buf by calculating the remainder and doing divisions with
336 | the given sizes[]. You need to specify the total number of bits to be
337 | used from buf in num_of_bits.
341 static void receiveints(int buf[], const int num_of_ints, int num_of_bits, const unsigned int sizes[], int nums[])
343 int bytes[32];
344 int i, j, num_of_bytes, p, num;
346 bytes[0] = bytes[1] = bytes[2] = bytes[3] = 0;
347 num_of_bytes = 0;
348 while (num_of_bits > 8)
350 bytes[num_of_bytes++] = receivebits(buf, 8);
351 num_of_bits -= 8;
353 if (num_of_bits > 0)
355 bytes[num_of_bytes++] = receivebits(buf, num_of_bits);
357 for (i = num_of_ints - 1; i > 0; i--)
359 num = 0;
360 for (j = num_of_bytes - 1; j >= 0; j--)
362 num = (num << 8) | bytes[j];
363 p = num / sizes[i];
364 bytes[j] = p;
365 num = num - p * sizes[i];
367 nums[i] = num;
369 nums[0] = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
372 /*____________________________________________________________________________
374 | xdr3dfcoord - read or write compressed 3d coordinates to xdr file.
376 | this routine reads or writes (depending on how you opened the file with
377 | xdropen() ) a large number of 3d coordinates (stored in *fp).
378 | The number of coordinates triplets to write is given by *size. On
379 | read this number may be zero, in which case it reads as many as were written
380 | or it may specify the number if triplets to read (which should match the
381 | number written).
382 | Compression is achieved by first converting all floating numbers to integer
383 | using multiplication by *precision and rounding to the nearest integer.
384 | Then the minimum and maximum value are calculated to determine the range.
385 | The limited range of integers so found, is used to compress the coordinates.
386 | In addition the differences between succesive coordinates is calculated.
387 | If the difference happens to be 'small' then only the difference is saved,
388 | compressing the data even more. The notion of 'small' is changed dynamically
389 | and is enlarged or reduced whenever needed or possible.
390 | Extra compression is achieved in the case of GROMOS and coordinates of
391 | water molecules. GROMOS first writes out the Oxygen position, followed by
392 | the two hydrogens. In order to make the differences smaller (and thereby
393 | compression the data better) the order is changed into first one hydrogen
394 | then the oxygen, followed by the other hydrogen. This is rather special, but
395 | it shouldn't harm in the general case.
399 int xdr3dfcoord(XDR* xdrs, float* fp, int* size, float* precision)
401 int* ip = nullptr;
402 int* buf = nullptr;
403 gmx_bool bRead;
405 /* preallocate a small buffer and ip on the stack - if we need more
406 we can always malloc(). This is faster for small values of size: */
407 unsigned prealloc_size = 3 * 16;
408 int prealloc_ip[3 * 16], prealloc_buf[3 * 20];
409 int we_should_free = 0;
411 int minint[3], maxint[3], mindiff, *lip, diff;
412 int lint1, lint2, lint3, oldlint1, oldlint2, oldlint3, smallidx;
413 int minidx, maxidx;
414 unsigned sizeint[3], sizesmall[3], bitsizeint[3], size3, *luip;
415 int flag, k;
416 int smallnum, smaller, larger, i, is_small, is_smaller, run, prevrun;
417 float * lfp, lf;
418 int tmp, *thiscoord, prevcoord[3];
419 unsigned int tmpcoord[30];
421 int bufsize, lsize;
422 unsigned int bitsize;
423 float inv_precision;
424 int errval = 1;
425 int rc;
427 bRead = (xdrs->x_op == XDR_DECODE);
428 bitsizeint[0] = bitsizeint[1] = bitsizeint[2] = 0;
429 prevcoord[0] = prevcoord[1] = prevcoord[2] = 0;
431 // The static analyzer warns about garbage values for thiscoord[] further
432 // down. It might be thrown off by all the reinterpret_casts, but we might
433 // as well make sure the small preallocated buffer is zero-initialized.
434 for (i = 0; i < static_cast<int>(prealloc_size); i++)
436 prealloc_ip[i] = 0;
439 if (!bRead)
441 /* xdrs is open for writing */
443 if (xdr_int(xdrs, size) == 0)
445 return 0;
447 size3 = *size * 3;
448 /* when the number of coordinates is small, don't try to compress; just
449 * write them as floats using xdr_vector
451 if (*size <= 9)
453 return (xdr_vector(xdrs, reinterpret_cast<char*>(fp), static_cast<unsigned int>(size3),
454 static_cast<unsigned int>(sizeof(*fp)),
455 reinterpret_cast<xdrproc_t>(xdr_float)));
458 if (xdr_float(xdrs, precision) == 0)
460 return 0;
463 if (size3 <= prealloc_size)
465 ip = prealloc_ip;
466 buf = prealloc_buf;
468 else
470 we_should_free = 1;
471 bufsize = static_cast<int>(size3 * 1.2);
472 ip = reinterpret_cast<int*>(malloc(size3 * sizeof(*ip)));
473 buf = reinterpret_cast<int*>(malloc(bufsize * sizeof(*buf)));
474 if (ip == nullptr || buf == nullptr)
476 fprintf(stderr, "malloc failed\n");
477 exit(1);
480 /* buf[0-2] are special and do not contain actual data */
481 buf[0] = buf[1] = buf[2] = 0;
482 minint[0] = minint[1] = minint[2] = INT_MAX;
483 maxint[0] = maxint[1] = maxint[2] = INT_MIN;
484 prevrun = -1;
485 lfp = fp;
486 lip = ip;
487 mindiff = INT_MAX;
488 oldlint1 = oldlint2 = oldlint3 = 0;
489 while (lfp < fp + size3)
491 /* find nearest integer */
492 if (*lfp >= 0.0)
494 lf = *lfp * *precision + 0.5;
496 else
498 lf = *lfp * *precision - 0.5;
500 if (std::fabs(lf) > maxAbsoluteInt)
502 /* scaling would cause overflow */
503 errval = 0;
505 lint1 = static_cast<int>(lf);
506 if (lint1 < minint[0])
508 minint[0] = lint1;
510 if (lint1 > maxint[0])
512 maxint[0] = lint1;
514 *lip++ = lint1;
515 lfp++;
516 if (*lfp >= 0.0)
518 lf = *lfp * *precision + 0.5;
520 else
522 lf = *lfp * *precision - 0.5;
524 if (std::fabs(lf) > maxAbsoluteInt)
526 /* scaling would cause overflow */
527 errval = 0;
529 lint2 = static_cast<int>(lf);
530 if (lint2 < minint[1])
532 minint[1] = lint2;
534 if (lint2 > maxint[1])
536 maxint[1] = lint2;
538 *lip++ = lint2;
539 lfp++;
540 if (*lfp >= 0.0)
542 lf = *lfp * *precision + 0.5;
544 else
546 lf = *lfp * *precision - 0.5;
548 if (std::abs(lf) > maxAbsoluteInt)
550 /* scaling would cause overflow */
551 errval = 0;
553 lint3 = static_cast<int>(lf);
554 if (lint3 < minint[2])
556 minint[2] = lint3;
558 if (lint3 > maxint[2])
560 maxint[2] = lint3;
562 *lip++ = lint3;
563 lfp++;
564 diff = std::abs(oldlint1 - lint1) + std::abs(oldlint2 - lint2) + std::abs(oldlint3 - lint3);
565 if (diff < mindiff && lfp > fp + 3)
567 mindiff = diff;
569 oldlint1 = lint1;
570 oldlint2 = lint2;
571 oldlint3 = lint3;
573 if ((xdr_int(xdrs, &(minint[0])) == 0) || (xdr_int(xdrs, &(minint[1])) == 0)
574 || (xdr_int(xdrs, &(minint[2])) == 0) || (xdr_int(xdrs, &(maxint[0])) == 0)
575 || (xdr_int(xdrs, &(maxint[1])) == 0) || (xdr_int(xdrs, &(maxint[2])) == 0))
577 if (we_should_free)
579 free(ip);
580 free(buf);
582 return 0;
585 if (static_cast<float>(maxint[0]) - static_cast<float>(minint[0]) >= maxAbsoluteInt
586 || static_cast<float>(maxint[1]) - static_cast<float>(minint[1]) >= maxAbsoluteInt
587 || static_cast<float>(maxint[2]) - static_cast<float>(minint[2]) >= maxAbsoluteInt)
589 /* turning value in unsigned by subtracting minint
590 * would cause overflow
592 errval = 0;
594 sizeint[0] = maxint[0] - minint[0] + 1;
595 sizeint[1] = maxint[1] - minint[1] + 1;
596 sizeint[2] = maxint[2] - minint[2] + 1;
598 /* check if one of the sizes is to big to be multiplied */
599 if ((sizeint[0] | sizeint[1] | sizeint[2]) > 0xffffff)
601 bitsizeint[0] = sizeofint(sizeint[0]);
602 bitsizeint[1] = sizeofint(sizeint[1]);
603 bitsizeint[2] = sizeofint(sizeint[2]);
604 bitsize = 0; /* flag the use of large sizes */
606 else
608 bitsize = sizeofints(3, sizeint);
610 luip = reinterpret_cast<unsigned int*>(ip);
611 smallidx = FIRSTIDX;
612 while (smallidx < LASTIDX && magicints[smallidx] < mindiff)
614 smallidx++;
616 if (xdr_int(xdrs, &smallidx) == 0)
618 if (we_should_free)
620 free(ip);
621 free(buf);
623 return 0;
626 maxidx = std::min(LASTIDX, smallidx + 8);
627 minidx = maxidx - 8; /* often this equal smallidx */
628 smaller = magicints[std::max(FIRSTIDX, smallidx - 1)] / 2;
629 smallnum = magicints[smallidx] / 2;
630 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
631 larger = magicints[maxidx] / 2;
632 i = 0;
633 while (i < *size)
635 is_small = 0;
636 thiscoord = reinterpret_cast<int*>(luip) + i * 3;
637 if (smallidx < maxidx && i >= 1 && std::abs(thiscoord[0] - prevcoord[0]) < larger
638 && std::abs(thiscoord[1] - prevcoord[1]) < larger
639 && std::abs(thiscoord[2] - prevcoord[2]) < larger)
641 is_smaller = 1;
643 else if (smallidx > minidx)
645 is_smaller = -1;
647 else
649 is_smaller = 0;
651 if (i + 1 < *size)
653 if (std::abs(thiscoord[0] - thiscoord[3]) < smallnum
654 && std::abs(thiscoord[1] - thiscoord[4]) < smallnum
655 && std::abs(thiscoord[2] - thiscoord[5]) < smallnum)
657 /* interchange first with second atom for better
658 * compression of water molecules
660 tmp = thiscoord[0];
661 thiscoord[0] = thiscoord[3];
662 thiscoord[3] = tmp;
663 tmp = thiscoord[1];
664 thiscoord[1] = thiscoord[4];
665 thiscoord[4] = tmp;
666 tmp = thiscoord[2];
667 thiscoord[2] = thiscoord[5];
668 thiscoord[5] = tmp;
669 is_small = 1;
672 tmpcoord[0] = thiscoord[0] - minint[0];
673 tmpcoord[1] = thiscoord[1] - minint[1];
674 tmpcoord[2] = thiscoord[2] - minint[2];
675 if (bitsize == 0)
677 sendbits(buf, bitsizeint[0], tmpcoord[0]);
678 sendbits(buf, bitsizeint[1], tmpcoord[1]);
679 sendbits(buf, bitsizeint[2], tmpcoord[2]);
681 else
683 sendints(buf, 3, bitsize, sizeint, tmpcoord);
685 prevcoord[0] = thiscoord[0];
686 prevcoord[1] = thiscoord[1];
687 prevcoord[2] = thiscoord[2];
688 thiscoord = thiscoord + 3;
689 i++;
691 run = 0;
692 if (is_small == 0 && is_smaller == -1)
694 is_smaller = 0;
696 while (is_small && run < 8 * 3)
698 if (is_smaller == -1
699 && (SQR(thiscoord[0] - prevcoord[0]) + SQR(thiscoord[1] - prevcoord[1])
700 + SQR(thiscoord[2] - prevcoord[2])
701 >= smaller * smaller))
703 is_smaller = 0;
706 tmpcoord[run++] = thiscoord[0] - prevcoord[0] + smallnum;
707 tmpcoord[run++] = thiscoord[1] - prevcoord[1] + smallnum;
708 tmpcoord[run++] = thiscoord[2] - prevcoord[2] + smallnum;
710 prevcoord[0] = thiscoord[0];
711 prevcoord[1] = thiscoord[1];
712 prevcoord[2] = thiscoord[2];
714 i++;
715 thiscoord = thiscoord + 3;
716 is_small = 0;
717 if (i < *size && abs(thiscoord[0] - prevcoord[0]) < smallnum
718 && abs(thiscoord[1] - prevcoord[1]) < smallnum
719 && abs(thiscoord[2] - prevcoord[2]) < smallnum)
721 is_small = 1;
724 if (run != prevrun || is_smaller != 0)
726 prevrun = run;
727 sendbits(buf, 1, 1); /* flag the change in run-length */
728 sendbits(buf, 5, run + is_smaller + 1);
730 else
732 sendbits(buf, 1, 0); /* flag the fact that runlength did not change */
734 for (k = 0; k < run; k += 3)
736 sendints(buf, 3, smallidx, sizesmall, &tmpcoord[k]);
738 if (is_smaller != 0)
740 smallidx += is_smaller;
741 if (is_smaller < 0)
743 smallnum = smaller;
744 smaller = magicints[smallidx - 1] / 2;
746 else
748 smaller = smallnum;
749 smallnum = magicints[smallidx] / 2;
751 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
754 if (buf[1] != 0)
756 buf[0]++;
758 /* buf[0] holds the length in bytes */
759 if (xdr_int(xdrs, &(buf[0])) == 0)
761 if (we_should_free)
763 free(ip);
764 free(buf);
766 return 0;
770 rc = errval
771 * (xdr_opaque(xdrs, reinterpret_cast<char*>(&(buf[3])), static_cast<unsigned int>(buf[0])));
772 if (we_should_free)
774 free(ip);
775 free(buf);
777 return rc;
779 else
782 /* xdrs is open for reading */
784 if (xdr_int(xdrs, &lsize) == 0)
786 return 0;
788 if (*size != 0 && lsize != *size)
790 fprintf(stderr,
791 "wrong number of coordinates in xdr3dfcoord; "
792 "%d arg vs %d in file",
793 *size, lsize);
795 *size = lsize;
796 size3 = *size * 3;
797 if (*size <= 9)
799 *precision = -1;
800 return (xdr_vector(xdrs, reinterpret_cast<char*>(fp), static_cast<unsigned int>(size3),
801 static_cast<unsigned int>(sizeof(*fp)),
802 reinterpret_cast<xdrproc_t>(xdr_float)));
804 if (xdr_float(xdrs, precision) == 0)
806 return 0;
809 if (size3 <= prealloc_size)
811 ip = prealloc_ip;
812 buf = prealloc_buf;
814 else
816 we_should_free = 1;
817 bufsize = static_cast<int>(size3 * 1.2);
818 ip = reinterpret_cast<int*>(malloc(size3 * sizeof(*ip)));
819 buf = reinterpret_cast<int*>(malloc(bufsize * sizeof(*buf)));
820 if (ip == nullptr || buf == nullptr)
822 fprintf(stderr, "malloc failed\n");
823 exit(1);
827 buf[0] = buf[1] = buf[2] = 0;
829 if ((xdr_int(xdrs, &(minint[0])) == 0) || (xdr_int(xdrs, &(minint[1])) == 0)
830 || (xdr_int(xdrs, &(minint[2])) == 0) || (xdr_int(xdrs, &(maxint[0])) == 0)
831 || (xdr_int(xdrs, &(maxint[1])) == 0) || (xdr_int(xdrs, &(maxint[2])) == 0))
833 if (we_should_free)
835 free(ip);
836 free(buf);
838 return 0;
841 sizeint[0] = maxint[0] - minint[0] + 1;
842 sizeint[1] = maxint[1] - minint[1] + 1;
843 sizeint[2] = maxint[2] - minint[2] + 1;
845 /* check if one of the sizes is to big to be multiplied */
846 if ((sizeint[0] | sizeint[1] | sizeint[2]) > 0xffffff)
848 bitsizeint[0] = sizeofint(sizeint[0]);
849 bitsizeint[1] = sizeofint(sizeint[1]);
850 bitsizeint[2] = sizeofint(sizeint[2]);
851 bitsize = 0; /* flag the use of large sizes */
853 else
855 bitsize = sizeofints(3, sizeint);
858 if (xdr_int(xdrs, &smallidx) == 0)
860 if (we_should_free)
862 free(ip);
863 free(buf);
865 return 0;
868 smaller = magicints[std::max(FIRSTIDX, smallidx - 1)] / 2;
869 smallnum = magicints[smallidx] / 2;
870 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
872 /* buf[0] holds the length in bytes */
874 if (xdr_int(xdrs, &(buf[0])) == 0)
876 if (we_should_free)
878 free(ip);
879 free(buf);
881 return 0;
885 if (xdr_opaque(xdrs, reinterpret_cast<char*>(&(buf[3])), static_cast<unsigned int>(buf[0])) == 0)
887 if (we_should_free)
889 free(ip);
890 free(buf);
892 return 0;
896 buf[0] = buf[1] = buf[2] = 0;
898 lfp = fp;
899 inv_precision = 1.0 / *precision;
900 run = 0;
901 i = 0;
902 lip = ip;
903 while (i < lsize)
905 thiscoord = reinterpret_cast<int*>(lip) + i * 3;
907 if (bitsize == 0)
909 thiscoord[0] = receivebits(buf, bitsizeint[0]);
910 thiscoord[1] = receivebits(buf, bitsizeint[1]);
911 thiscoord[2] = receivebits(buf, bitsizeint[2]);
913 else
915 receiveints(buf, 3, bitsize, sizeint, thiscoord);
918 i++;
919 thiscoord[0] += minint[0];
920 thiscoord[1] += minint[1];
921 thiscoord[2] += minint[2];
923 prevcoord[0] = thiscoord[0];
924 prevcoord[1] = thiscoord[1];
925 prevcoord[2] = thiscoord[2];
928 flag = receivebits(buf, 1);
929 is_smaller = 0;
930 if (flag == 1)
932 run = receivebits(buf, 5);
933 is_smaller = run % 3;
934 run -= is_smaller;
935 is_smaller--;
937 if (run > 0)
939 thiscoord += 3;
940 for (k = 0; k < run; k += 3)
942 receiveints(buf, 3, smallidx, sizesmall, thiscoord);
943 i++;
944 thiscoord[0] += prevcoord[0] - smallnum;
945 thiscoord[1] += prevcoord[1] - smallnum;
946 thiscoord[2] += prevcoord[2] - smallnum;
947 if (k == 0)
949 /* interchange first with second atom for better
950 * compression of water molecules
952 tmp = thiscoord[0];
953 thiscoord[0] = prevcoord[0];
954 prevcoord[0] = tmp;
955 tmp = thiscoord[1];
956 thiscoord[1] = prevcoord[1];
957 prevcoord[1] = tmp;
958 tmp = thiscoord[2];
959 thiscoord[2] = prevcoord[2];
960 prevcoord[2] = tmp;
961 *lfp++ = prevcoord[0] * inv_precision;
962 *lfp++ = prevcoord[1] * inv_precision;
963 *lfp++ = prevcoord[2] * inv_precision;
965 else
967 prevcoord[0] = thiscoord[0];
968 prevcoord[1] = thiscoord[1];
969 prevcoord[2] = thiscoord[2];
971 *lfp++ = thiscoord[0] * inv_precision;
972 *lfp++ = thiscoord[1] * inv_precision;
973 *lfp++ = thiscoord[2] * inv_precision;
976 else
978 *lfp++ = thiscoord[0] * inv_precision;
979 *lfp++ = thiscoord[1] * inv_precision;
980 *lfp++ = thiscoord[2] * inv_precision;
982 smallidx += is_smaller;
983 if (is_smaller < 0)
985 smallnum = smaller;
986 if (smallidx > FIRSTIDX)
988 smaller = magicints[smallidx - 1] / 2;
990 else
992 smaller = 0;
995 else if (is_smaller > 0)
997 smaller = smallnum;
998 smallnum = magicints[smallidx] / 2;
1000 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
1003 if (we_should_free)
1005 free(ip);
1006 free(buf);
1008 return 1;
1012 /******************************************************************
1014 XTC files have a relatively simple structure.
1015 They have a header of 16 bytes and the rest are
1016 the compressed coordinates of the files. Due to the
1017 compression 00 is not present in the coordinates.
1018 The first 4 bytes of the header are the magic number
1019 1995 (0x000007CB). If we find this number we are guaranteed
1020 to be in the header, due to the presence of so many zeros.
1021 The second 4 bytes are the number of atoms in the frame, and is
1022 assumed to be constant. The third 4 bytes are the frame number.
1023 The last 4 bytes are a floating point representation of the time.
1025 ********************************************************************/
1027 /* Must match definition in xtcio.c */
1028 #ifndef XTC_MAGIC
1029 # define XTC_MAGIC 1995
1030 #endif
1032 static const int header_size = 16;
1034 /* Check if we are at the header start.
1035 At the same time it will also read 1 int */
1036 static int xtc_at_header_start(FILE* fp, XDR* xdrs, int natoms, int* timestep, float* time)
1038 int i_inp[3];
1039 float f_inp[10];
1040 int i;
1041 gmx_off_t off;
1044 if ((off = gmx_ftell(fp)) < 0)
1046 return -1;
1048 /* read magic natoms and timestep */
1049 for (i = 0; i < 3; i++)
1051 if (!xdr_int(xdrs, &(i_inp[i])))
1053 gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET);
1054 return -1;
1057 /* quick return */
1058 if (i_inp[0] != XTC_MAGIC)
1060 if (gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET))
1062 return -1;
1064 return 0;
1066 /* read time and box */
1067 for (i = 0; i < 10; i++)
1069 if (!xdr_float(xdrs, &(f_inp[i])))
1071 gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET);
1072 return -1;
1075 /* Make a rigourous check to see if we are in the beggining of a header
1076 Hopefully there are no ambiguous cases */
1077 /* This check makes use of the fact that the box matrix has 3 zeroes on the upper
1078 right triangle and that the first element must be nonzero unless the entire matrix is zero
1080 if (i_inp[1] == natoms
1081 && ((f_inp[1] != 0 && f_inp[6] == 0) || (f_inp[1] == 0 && f_inp[5] == 0 && f_inp[9] == 0)))
1083 if (gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET))
1085 return -1;
1087 *time = f_inp[0];
1088 *timestep = i_inp[2];
1089 return 1;
1091 if (gmx_fseek(fp, off + XDR_INT_SIZE, SEEK_SET))
1093 return -1;
1095 return 0;
1098 static int xtc_get_next_frame_number(FILE* fp, XDR* xdrs, int natoms)
1100 gmx_off_t off;
1101 int step;
1102 float time;
1103 int ret;
1105 if ((off = gmx_ftell(fp)) < 0)
1107 return -1;
1110 /* read one int just to make sure we dont read this frame but the next */
1111 xdr_int(xdrs, &step);
1112 while (true)
1114 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1115 if (ret == 1)
1117 if (gmx_fseek(fp, off, SEEK_SET))
1119 return -1;
1121 return step;
1123 else if (ret == -1)
1125 if (gmx_fseek(fp, off, SEEK_SET))
1127 return -1;
1134 static float xtc_get_next_frame_time(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1136 gmx_off_t off;
1137 float time;
1138 int step;
1139 int ret;
1140 *bOK = false;
1142 if ((off = gmx_ftell(fp)) < 0)
1144 return -1;
1146 /* read one int just to make sure we dont read this frame but the next */
1147 xdr_int(xdrs, &step);
1148 while (true)
1150 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1151 if (ret == 1)
1153 *bOK = true;
1154 if (gmx_fseek(fp, off, SEEK_SET))
1156 *bOK = false;
1157 return -1;
1159 return time;
1161 else if (ret == -1)
1163 if (gmx_fseek(fp, off, SEEK_SET))
1165 return -1;
1167 return -1;
1173 static float xtc_get_current_frame_time(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1175 gmx_off_t off;
1176 int step;
1177 float time;
1178 int ret;
1179 *bOK = false;
1181 if ((off = gmx_ftell(fp)) < 0)
1183 return -1;
1186 while (true)
1188 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1189 if (ret == 1)
1191 *bOK = true;
1192 if (gmx_fseek(fp, off, SEEK_SET))
1194 *bOK = false;
1195 return -1;
1197 return time;
1199 else if (ret == -1)
1201 if (gmx_fseek(fp, off, SEEK_SET))
1203 return -1;
1205 return -1;
1207 else if (ret == 0)
1209 /*Go back.*/
1210 if (gmx_fseek(fp, -2 * XDR_INT_SIZE, SEEK_CUR))
1212 return -1;
1218 /* Currently not used, just for completeness */
1219 static int xtc_get_current_frame_number(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1221 gmx_off_t off;
1222 int ret;
1223 int step;
1224 float time;
1225 *bOK = false;
1227 if ((off = gmx_ftell(fp)) < 0)
1229 return -1;
1233 while (true)
1235 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1236 if (ret == 1)
1238 *bOK = true;
1239 if (gmx_fseek(fp, off, SEEK_SET))
1241 *bOK = false;
1242 return -1;
1244 return step;
1246 else if (ret == -1)
1248 if (gmx_fseek(fp, off, SEEK_SET))
1250 return -1;
1252 return -1;
1254 else if (ret == 0)
1256 /*Go back.*/
1257 if (gmx_fseek(fp, -2 * XDR_INT_SIZE, SEEK_CUR))
1259 return -1;
1266 static gmx_off_t xtc_get_next_frame_start(FILE* fp, XDR* xdrs, int natoms)
1268 gmx_off_t res;
1269 int ret;
1270 int step;
1271 float time;
1272 /* read one int just to make sure we dont read this frame but the next */
1273 xdr_int(xdrs, &step);
1274 while (true)
1276 ret = xtc_at_header_start(fp, xdrs, natoms, &step, &time);
1277 if (ret == 1)
1279 if ((res = gmx_ftell(fp)) >= 0)
1281 return res - XDR_INT_SIZE;
1283 else
1285 return res;
1288 else if (ret == -1)
1290 return -1;
1296 static float xdr_xtc_estimate_dt(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1298 float res;
1299 float tinit;
1300 gmx_off_t off;
1302 *bOK = false;
1303 if ((off = gmx_ftell(fp)) < 0)
1305 return -1;
1308 tinit = xtc_get_current_frame_time(fp, xdrs, natoms, bOK);
1310 if (!(*bOK))
1312 return -1;
1315 res = xtc_get_next_frame_time(fp, xdrs, natoms, bOK);
1317 if (!(*bOK))
1319 return -1;
1322 res -= tinit;
1323 if (0 != gmx_fseek(fp, off, SEEK_SET))
1325 *bOK = false;
1326 return -1;
1328 return res;
1331 int xdr_xtc_seek_frame(int frame, FILE* fp, XDR* xdrs, int natoms)
1333 gmx_off_t low = 0;
1334 gmx_off_t high, pos;
1337 /* round to 4 bytes */
1338 int fr;
1339 gmx_off_t offset;
1340 if (gmx_fseek(fp, 0, SEEK_END))
1342 return -1;
1345 if ((high = gmx_ftell(fp)) < 0)
1347 return -1;
1350 /* round to 4 bytes */
1351 high /= XDR_INT_SIZE;
1352 high *= XDR_INT_SIZE;
1353 offset = ((high / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1355 if (gmx_fseek(fp, offset, SEEK_SET))
1357 return -1;
1360 while (true)
1362 fr = xtc_get_next_frame_number(fp, xdrs, natoms);
1363 if (fr < 0)
1365 return -1;
1367 if (fr != frame && llabs(low - high) > header_size)
1369 if (fr < frame)
1371 low = offset;
1373 else
1375 high = offset;
1377 /* round to 4 bytes */
1378 offset = (((high + low) / 2) / 4) * 4;
1380 if (gmx_fseek(fp, offset, SEEK_SET))
1382 return -1;
1385 else
1387 break;
1390 if (offset <= header_size)
1392 offset = low;
1395 if (gmx_fseek(fp, offset, SEEK_SET))
1397 return -1;
1400 if ((pos = xtc_get_next_frame_start(fp, xdrs, natoms)) < 0)
1402 /* we probably hit an end of file */
1403 return -1;
1406 if (gmx_fseek(fp, pos, SEEK_SET))
1408 return -1;
1411 return 0;
1415 int xdr_xtc_seek_time(real time, FILE* fp, XDR* xdrs, int natoms, gmx_bool bSeekForwardOnly)
1417 float t;
1418 float dt;
1419 gmx_bool bOK = FALSE;
1420 gmx_off_t low = 0;
1421 gmx_off_t high, offset, pos;
1422 int dt_sign = 0;
1424 if (bSeekForwardOnly)
1426 low = gmx_ftell(fp) - header_size;
1428 if (gmx_fseek(fp, 0, SEEK_END))
1430 return -1;
1433 if ((high = gmx_ftell(fp)) < 0)
1435 return -1;
1437 /* round to int */
1438 high /= XDR_INT_SIZE;
1439 high *= XDR_INT_SIZE;
1440 offset = (((high - low) / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1442 if (gmx_fseek(fp, offset, SEEK_SET))
1444 return -1;
1449 * No need to call xdr_xtc_estimate_dt here - since xdr_xtc_estimate_dt is called first thing in
1450 the loop dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1452 if (!bOK)
1454 return -1;
1458 while (true)
1460 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1461 if (!bOK)
1463 return -1;
1465 else
1467 if (dt > 0)
1469 if (dt_sign == -1)
1471 /* Found a place in the trajectory that has positive time step while
1472 other has negative time step */
1473 return -2;
1475 dt_sign = 1;
1477 else if (dt < 0)
1479 if (dt_sign == 1)
1481 /* Found a place in the trajectory that has positive time step while
1482 other has negative time step */
1483 return -2;
1485 dt_sign = -1;
1488 t = xtc_get_next_frame_time(fp, xdrs, natoms, &bOK);
1489 if (!bOK)
1491 return -1;
1494 /* If we are before the target time and the time step is positive or 0, or we have
1495 after the target time and the time step is negative, or the difference between
1496 the current time and the target time is bigger than dt and above all the distance between
1497 high and low is bigger than 1 frame, then do another step of binary search. Otherwise
1498 stop and check if we reached the solution */
1499 if ((((t < time && dt_sign >= 0) || (t > time && dt_sign == -1))
1500 || ((t - time) >= dt && dt_sign >= 0) || ((time - t) >= -dt && dt_sign < 0))
1501 && (llabs(low - high) > header_size))
1503 if (dt >= 0 && dt_sign != -1)
1505 if (t < time)
1507 low = offset;
1509 else
1511 high = offset;
1514 else if (dt <= 0 && dt_sign == -1)
1516 if (t >= time)
1518 low = offset;
1520 else
1522 high = offset;
1525 else
1527 /* We should never reach here */
1528 return -1;
1530 /* round to 4 bytes and subtract header*/
1531 offset = (((high + low) / 2) / XDR_INT_SIZE) * XDR_INT_SIZE;
1532 if (gmx_fseek(fp, offset, SEEK_SET))
1534 return -1;
1537 else
1539 if (llabs(low - high) <= header_size)
1541 break;
1543 /* re-estimate dt */
1544 if (xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK) != dt)
1546 if (bOK)
1548 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1551 if (t >= time && t - time < dt)
1553 break;
1558 if (offset <= header_size)
1560 offset = low;
1563 gmx_fseek(fp, offset, SEEK_SET);
1565 if ((pos = xtc_get_next_frame_start(fp, xdrs, natoms)) < 0)
1567 return -1;
1570 if (gmx_fseek(fp, pos, SEEK_SET))
1572 return -1;
1574 return 0;
1577 float xdr_xtc_get_last_frame_time(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1579 float time;
1580 gmx_off_t off;
1581 *bOK = true;
1582 off = gmx_ftell(fp);
1583 if (off < 0)
1585 *bOK = false;
1586 return -1;
1589 if (gmx_fseek(fp, -3 * XDR_INT_SIZE, SEEK_END) != 0)
1591 *bOK = false;
1592 return -1;
1595 time = xtc_get_current_frame_time(fp, xdrs, natoms, bOK);
1596 if (!(*bOK))
1598 return -1;
1601 if (gmx_fseek(fp, off, SEEK_SET) != 0)
1603 *bOK = false;
1604 return -1;
1606 return time;
1610 int xdr_xtc_get_last_frame_number(FILE* fp, XDR* xdrs, int natoms, gmx_bool* bOK)
1612 int frame;
1613 gmx_off_t off;
1614 *bOK = true;
1616 if ((off = gmx_ftell(fp)) < 0)
1618 *bOK = false;
1619 return -1;
1623 if (gmx_fseek(fp, -3 * XDR_INT_SIZE, SEEK_END))
1625 *bOK = false;
1626 return -1;
1629 frame = xtc_get_current_frame_number(fp, xdrs, natoms, bOK);
1630 if (!*bOK)
1632 return -1;
1636 if (gmx_fseek(fp, off, SEEK_SET))
1638 *bOK = false;
1639 return -1;
1642 return frame;