3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * GROningen Mixture of Alchemy and Childrens' Stories
51 # define gmx_fseek(A,B,C) fseeko(A,B,C)
52 # define gmx_ftell(A) ftello(A)
53 # define gmx_off_t off_t
55 # define gmx_fseek(A,B,C) fseek(A,B,C)
56 # define gmx_ftell(A) ftell(A)
57 # define gmx_off_t int
62 static FILE *xdrfiles
[MAXID
];
63 static XDR
*xdridptr
[MAXID
];
64 static char xdrmodes
[MAXID
];
65 static unsigned int cnt
;
67 /* This is just for clarity - it can never be anything but 4! */
68 #define XDR_INT_SIZE 4
72 typedef void (* F77_FUNC(xdrfproc
,XDRFPROC
))(int *, void *, int *);
74 int ftocstr(char *ds
, int dl
, char *ss
, int sl
)
82 while ( --p
>= ss
&& *p
== ' ' );
95 int ctofstr(char *ds
, int dl
, char *ss
)
98 /* src string (0-term) */
110 F77_FUNC(xdrfbool
,XDRFBOOL
)(int *xdrid
, int *pb
, int *ret
)
112 *ret
= xdr_bool(xdridptr
[*xdrid
], pb
);
117 F77_FUNC(xdrfchar
,XDRFCHAR
)(int *xdrid
, char *cp
, int *ret
)
119 *ret
= xdr_char(xdridptr
[*xdrid
], cp
);
124 F77_FUNC(xdrfdouble
,XDRFDOUBLE
)(int *xdrid
, double *dp
, int *ret
)
126 *ret
= xdr_double(xdridptr
[*xdrid
], dp
);
127 cnt
+= sizeof(double);
131 F77_FUNC(xdrffloat
,XDRFFLOAT
)(int *xdrid
, float *fp
, int *ret
)
133 *ret
= xdr_float(xdridptr
[*xdrid
], fp
);
134 cnt
+= sizeof(float);
138 F77_FUNC(xdrfint
,XDRFINT
)(int *xdrid
, int *ip
, int *ret
)
140 *ret
= xdr_int(xdridptr
[*xdrid
], ip
);
144 F77_FUNC(xdrfshort
,XDRFSHORT
)(int *xdrid
, short *sp
, int *ret
)
146 *ret
= xdr_short(xdridptr
[*xdrid
], sp
);
151 F77_FUNC(xdrfuchar
,XDRFUCHAR
)(int *xdrid
, unsigned char *ucp
, int *ret
)
153 *ret
= xdr_u_char(xdridptr
[*xdrid
], (u_char
*)ucp
);
159 F77_FUNC(xdrfushort
,XDRFUSHORT
)(int *xdrid
, unsigned short *usp
, int *ret
)
161 *ret
= xdr_u_short(xdridptr
[*xdrid
], (unsigned short *)usp
);
162 cnt
+= sizeof(unsigned short);
166 F77_FUNC(xdrf3dfcoord
,XDRF3DFCOORD
)(int *xdrid
, float *fp
, int *size
, float *precision
, int *ret
)
168 *ret
= xdr3dfcoord(xdridptr
[*xdrid
], fp
, size
, precision
);
172 F77_FUNC(xdrfstring
,XDRFSTRING
)(int *xdrid
, char * sp_ptr
,
173 int *maxsize
, int *ret
, int sp_len
)
177 tsp
= (char*) malloc((size_t)(((sp_len
) + 1) * sizeof(char)));
182 if (ftocstr(tsp
, *maxsize
+1, sp_ptr
, sp_len
)) {
187 *ret
= xdr_string(xdridptr
[*xdrid
], (char **) &tsp
, (unsigned int) *maxsize
);
188 ctofstr( sp_ptr
, sp_len
, tsp
);
194 F77_FUNC(xdrfwrapstring
,XDRFWRAPSTRING
)(int *xdrid
, char *sp_ptr
,
195 int *ret
, int sp_len
)
199 maxsize
= (sp_len
) + 1;
200 tsp
= (char*) malloc((size_t)(maxsize
* sizeof(char)));
205 if (ftocstr(tsp
, maxsize
, sp_ptr
, sp_len
)) {
210 *ret
= xdr_string(xdridptr
[*xdrid
], (char **) &tsp
, (u_int
)maxsize
);
211 ctofstr( sp_ptr
, sp_len
, tsp
);
217 F77_FUNC(xdrfopaque
,XDRFOPAQUE
)(int *xdrid
, caddr_t
*cp
, int *ccnt
, int *ret
)
219 *ret
= xdr_opaque(xdridptr
[*xdrid
], (caddr_t
)*cp
, (u_int
)*ccnt
);
224 F77_FUNC(xdrfsetpos
,XDRFSETPOS
)(int *xdrid
, int *pos
, int *ret
)
226 *ret
= xdr_setpos(xdridptr
[*xdrid
], (u_int
) *pos
);
231 F77_FUNC(xdrf
,XDRF
)(int *xdrid
, int *pos
)
233 *pos
= xdr_getpos(xdridptr
[*xdrid
]);
237 F77_FUNC(xdrfvector
,XDRFVECTOR
)(int *xdrid
, char *cp
, int *size
, F77_FUNC(xdrfproc
,XDRFPROC
) elproc
, int *ret
)
241 for (lcnt
= 0; lcnt
< *size
; lcnt
++) {
242 elproc(xdrid
, (cp
+cnt
) , ret
);
248 F77_FUNC(xdrfclose
,XDRFCLOSE
)(int *xdrid
, int *ret
)
250 *ret
= xdrclose(xdridptr
[*xdrid
]);
255 F77_FUNC(xdrfopen
,XDRFOPEN
)(int *xdrid
, char *fp_ptr
, char *mode_ptr
,
256 int *ret
, int fp_len
, int mode_len
)
261 if (ftocstr(fname
, sizeof(fname
), fp_ptr
, fp_len
)) {
264 if (ftocstr(fmode
, sizeof(fmode
), mode_ptr
,
269 *xdrid
= xdropen(NULL
, fname
, fmode
);
275 #endif /* GMX_FORTRAN */
277 /*___________________________________________________________________________
279 | what follows are the C routines for opening, closing xdr streams
280 | and the routine to read/write compressed coordinates together
281 | with some routines to assist in this task (those are marked
282 | static and cannot be called from user programs)
284 #define MAXABS INT_MAX-2
287 #define MIN(x,y) ((x) < (y) ? (x):(y))
290 #define MAX(x,y) ((x) > (y) ? (x):(y))
293 #define SQR(x) ((x)*(x))
295 static int magicints
[] = {
296 0, 0, 0, 0, 0, 0, 0, 0, 0,
297 8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
298 80, 101, 128, 161, 203, 256, 322, 406, 512, 645,
299 812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501,
300 8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536,
301 82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,
302 832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042,
303 8388607, 10568983, 13316085, 16777216 };
306 /* note that magicints[FIRSTIDX-1] == 0 */
307 #define LASTIDX (sizeof(magicints) / sizeof(*magicints))
310 /*__________________________________________________________________________
312 | xdropen - open xdr file
314 | This versions differs from xdrstdio_create, because I need to know
315 | the state of the file (read or write) so I can use xdr3dfcoord
316 | in eigther read or write mode, and the file descriptor
317 | so I can close the file (something xdr_destroy doesn't do).
321 int xdropen(XDR
*xdrs
, const char *filename
, const char *type
) {
322 static int init_done
= 0;
327 if (init_done
== 0) {
328 for (xdrid
= 1; xdrid
< MAXID
; xdrid
++) {
329 xdridptr
[xdrid
] = NULL
;
334 while (xdrid
< MAXID
&& xdridptr
[xdrid
] != NULL
) {
337 if (xdrid
== MAXID
) {
340 if (*type
== 'w' || *type
== 'W')
342 xdrmodes
[xdrid
] = 'w';
343 strcpy(newtype
, "wb+");
346 else if (*type
== 'a' || *type
== 'A')
348 xdrmodes
[xdrid
] = 'a';
349 strcpy(newtype
, "ab+");
352 else if (strncasecmp(type
, "r+", 2) == 0)
354 xdrmodes
[xdrid
] = 'a';
355 strcpy(newtype
, "rb+");
360 xdrmodes
[xdrid
] = 'r';
361 strcpy(newtype
, "rb");
364 xdrfiles
[xdrid
] = fopen(filename
, newtype
);
366 if (xdrfiles
[xdrid
] == NULL
) {
371 /* next test isn't usefull in the case of C language
372 * but is used for the Fortran interface
373 * (C users are expected to pass the address of an already allocated
377 xdridptr
[xdrid
] = (XDR
*) malloc((size_t)sizeof(XDR
));
378 xdrstdio_create(xdridptr
[xdrid
], xdrfiles
[xdrid
], lmode
);
380 xdridptr
[xdrid
] = xdrs
;
381 xdrstdio_create(xdrs
, xdrfiles
[xdrid
], lmode
);
386 /*_________________________________________________________________________
388 | xdrclose - close a xdr file
390 | This will flush the xdr buffers, and destroy the xdr stream.
391 | It also closes the associated file descriptor (this is *not*
392 | done by xdr_destroy).
396 int xdrclose(XDR
*xdrs
) {
401 fprintf(stderr
, "xdrclose: passed a NULL pointer\n");
404 for (xdrid
= 1; xdrid
< MAXID
&& rc
==0; xdrid
++) {
405 if (xdridptr
[xdrid
] == xdrs
) {
408 rc
= fclose(xdrfiles
[xdrid
]);
409 xdridptr
[xdrid
] = NULL
;
410 return !rc
; /* xdr routines return 0 when ok */
413 fprintf(stderr
, "xdrclose: no such open xdr file\n");
416 /* to make some compilers happy: */
421 xdr_get_fp(int xdrid
)
423 return xdrfiles
[xdrid
];
427 /*____________________________________________________________________________
429 | sendbits - encode num into buf using the specified number of bits
431 | This routines appends the value of num to the bits already present in
432 | the array buf. You need to give it the number of bits to use and you
433 | better make sure that this number of bits is enough to hold the value
434 | Also num must be positive.
438 static void sendbits(int buf
[], int num_of_bits
, int num
) {
440 unsigned int cnt
, lastbyte
;
442 unsigned char * cbuf
;
444 cbuf
= ((unsigned char *)buf
) + 3 * sizeof(*buf
);
445 cnt
= (unsigned int) buf
[0];
447 lastbyte
=(unsigned int) buf
[2];
448 while (num_of_bits
>= 8) {
449 lastbyte
= (lastbyte
<< 8) | ((num
>> (num_of_bits
-8)) /* & 0xff*/);
450 cbuf
[cnt
++] = lastbyte
>> lastbits
;
453 if (num_of_bits
> 0) {
454 lastbyte
= (lastbyte
<< num_of_bits
) | num
;
455 lastbits
+= num_of_bits
;
458 cbuf
[cnt
++] = lastbyte
>> lastbits
;
465 cbuf
[cnt
] = lastbyte
<< (8 - lastbits
);
469 /*_________________________________________________________________________
471 | sizeofint - calculate bitsize of an integer
473 | return the number of bits needed to store an integer with given max size
477 static int sizeofint(const int size
) {
481 while (size
>= num
&& num_of_bits
< 32) {
488 /*___________________________________________________________________________
490 | sizeofints - calculate 'bitsize' of compressed ints
492 | given the number of small unsigned integers and the maximum value
493 | return the number of bits needed to read or write them with the
494 | routines receiveints and sendints. You need this parameter when
495 | calling these routines. Note that for many calls I can use
496 | the variable 'smallidx' which is exactly the number of bits, and
497 | So I don't need to call 'sizeofints for those calls.
500 static int sizeofints( const int num_of_ints
, unsigned int sizes
[]) {
503 unsigned int num_of_bytes
, num_of_bits
, bytecnt
, tmp
;
507 for (i
=0; i
< num_of_ints
; i
++) {
509 for (bytecnt
= 0; bytecnt
< num_of_bytes
; bytecnt
++) {
510 tmp
= bytes
[bytecnt
] * sizes
[i
] + tmp
;
511 bytes
[bytecnt
] = tmp
& 0xff;
515 bytes
[bytecnt
++] = tmp
& 0xff;
518 num_of_bytes
= bytecnt
;
522 while (bytes
[num_of_bytes
] >= num
) {
526 return num_of_bits
+ num_of_bytes
* 8;
530 /*____________________________________________________________________________
532 | sendints - send a small set of small integers in compressed format
534 | this routine is used internally by xdr3dfcoord, to send a set of
535 | small integers to the buffer.
536 | Multiplication with fixed (specified maximum ) sizes is used to get
537 | to one big, multibyte integer. Allthough the routine could be
538 | modified to handle sizes bigger than 16777216, or more than just
539 | a few integers, this is not done, because the gain in compression
540 | isn't worth the effort. Note that overflowing the multiplication
541 | or the byte buffer (32 bytes) is unchecked and causes bad results.
545 static void sendints(int buf
[], const int num_of_ints
, const int num_of_bits
,
546 unsigned int sizes
[], unsigned int nums
[]) {
548 int i
, num_of_bytes
, bytecnt
;
549 unsigned int bytes
[32], tmp
;
554 bytes
[num_of_bytes
++] = tmp
& 0xff;
558 for (i
= 1; i
< num_of_ints
; i
++) {
559 if (nums
[i
] >= sizes
[i
]) {
560 fprintf(stderr
,"major breakdown in sendints num %u doesn't "
561 "match size %u\n", nums
[i
], sizes
[i
]);
564 /* use one step multiply */
566 for (bytecnt
= 0; bytecnt
< num_of_bytes
; bytecnt
++) {
567 tmp
= bytes
[bytecnt
] * sizes
[i
] + tmp
;
568 bytes
[bytecnt
] = tmp
& 0xff;
572 bytes
[bytecnt
++] = tmp
& 0xff;
575 num_of_bytes
= bytecnt
;
577 if (num_of_bits
>= num_of_bytes
* 8) {
578 for (i
= 0; i
< num_of_bytes
; i
++) {
579 sendbits(buf
, 8, bytes
[i
]);
581 sendbits(buf
, num_of_bits
- num_of_bytes
* 8, 0);
583 for (i
= 0; i
< num_of_bytes
-1; i
++) {
584 sendbits(buf
, 8, bytes
[i
]);
586 sendbits(buf
, num_of_bits
- (num_of_bytes
-1) * 8, bytes
[i
]);
591 /*___________________________________________________________________________
593 | receivebits - decode number from buf using specified number of bits
595 | extract the number of bits from the array buf and construct an integer
596 | from it. Return that value.
600 static int receivebits(int buf
[], int num_of_bits
) {
602 int cnt
, num
, lastbits
;
603 unsigned int lastbyte
;
604 unsigned char * cbuf
;
605 int mask
= (1 << num_of_bits
) -1;
607 cbuf
= ((unsigned char *)buf
) + 3 * sizeof(*buf
);
609 lastbits
= (unsigned int) buf
[1];
610 lastbyte
= (unsigned int) buf
[2];
613 while (num_of_bits
>= 8) {
614 lastbyte
= ( lastbyte
<< 8 ) | cbuf
[cnt
++];
615 num
|= (lastbyte
>> lastbits
) << (num_of_bits
- 8);
618 if (num_of_bits
> 0) {
619 if (lastbits
< num_of_bits
) {
621 lastbyte
= (lastbyte
<< 8) | cbuf
[cnt
++];
623 lastbits
-= num_of_bits
;
624 num
|= (lastbyte
>> lastbits
) & ((1 << num_of_bits
) -1);
633 /*____________________________________________________________________________
635 | receiveints - decode 'small' integers from the buf array
637 | this routine is the inverse from sendints() and decodes the small integers
638 | written to buf by calculating the remainder and doing divisions with
639 | the given sizes[]. You need to specify the total number of bits to be
640 | used from buf in num_of_bits.
644 static void receiveints(int buf
[], const int num_of_ints
, int num_of_bits
,
645 unsigned int sizes
[], int nums
[]) {
647 int i
, j
, num_of_bytes
, p
, num
;
649 bytes
[1] = bytes
[2] = bytes
[3] = 0;
651 while (num_of_bits
> 8) {
652 bytes
[num_of_bytes
++] = receivebits(buf
, 8);
655 if (num_of_bits
> 0) {
656 bytes
[num_of_bytes
++] = receivebits(buf
, num_of_bits
);
658 for (i
= num_of_ints
-1; i
> 0; i
--) {
660 for (j
= num_of_bytes
-1; j
>=0; j
--) {
661 num
= (num
<< 8) | bytes
[j
];
664 num
= num
- p
* sizes
[i
];
668 nums
[0] = bytes
[0] | (bytes
[1] << 8) | (bytes
[2] << 16) | (bytes
[3] << 24);
671 /*____________________________________________________________________________
673 | xdr3dfcoord - read or write compressed 3d coordinates to xdr file.
675 | this routine reads or writes (depending on how you opened the file with
676 | xdropen() ) a large number of 3d coordinates (stored in *fp).
677 | The number of coordinates triplets to write is given by *size. On
678 | read this number may be zero, in which case it reads as many as were written
679 | or it may specify the number if triplets to read (which should match the
681 | Compression is achieved by first converting all floating numbers to integer
682 | using multiplication by *precision and rounding to the nearest integer.
683 | Then the minimum and maximum value are calculated to determine the range.
684 | The limited range of integers so found, is used to compress the coordinates.
685 | In addition the differences between succesive coordinates is calculated.
686 | If the difference happens to be 'small' then only the difference is saved,
687 | compressing the data even more. The notion of 'small' is changed dynamically
688 | and is enlarged or reduced whenever needed or possible.
689 | Extra compression is achieved in the case of GROMOS and coordinates of
690 | water molecules. GROMOS first writes out the Oxygen position, followed by
691 | the two hydrogens. In order to make the differences smaller (and thereby
692 | compression the data better) the order is changed into first one hydrogen
693 | then the oxygen, followed by the other hydrogen. This is rather special, but
694 | it shouldn't harm in the general case.
698 int xdr3dfcoord(XDR
*xdrs
, float *fp
, int *size
, float *precision
) {
701 static int *ip
= NULL
;
705 int minint
[3], maxint
[3], mindiff
, *lip
, diff
;
706 int lint1
, lint2
, lint3
, oldlint1
, oldlint2
, oldlint3
, smallidx
;
708 unsigned sizeint
[3], sizesmall
[3], bitsizeint
[3], size3
, *luip
;
710 int smallnum
, smaller
, larger
, i
, is_small
, is_smaller
, run
, prevrun
;
712 int tmp
, *thiscoord
, prevcoord
[3];
713 unsigned int tmpcoord
[30];
715 int bufsize
, xdrid
, lsize
;
716 unsigned int bitsize
;
721 bitsizeint
[0] = bitsizeint
[1] = bitsizeint
[2] = 0;
722 prevcoord
[0] = prevcoord
[1] = prevcoord
[2] = 0;
724 /* find out if xdrs is opened for reading or for writing */
726 while (xdridptr
[xdrid
] != xdrs
) {
728 if (xdrid
>= MAXID
) {
729 fprintf(stderr
, "xdr error. no open xdr stream\n");
733 if ((xdrmodes
[xdrid
] == 'w') || (xdrmodes
[xdrid
] == 'a')) {
735 /* xdrs is open for writing */
737 if (xdr_int(xdrs
, size
) == 0)
740 /* when the number of coordinates is small, don't try to compress; just
741 * write them as floats using xdr_vector
744 return (xdr_vector(xdrs
, (char *) fp
, (unsigned int)size3
,
745 (unsigned int)sizeof(*fp
), (xdrproc_t
)xdr_float
));
748 if(xdr_float(xdrs
, precision
) == 0)
752 ip
= (int *)malloc((size_t)(size3
* sizeof(*ip
)));
754 fprintf(stderr
,"malloc failed\n");
757 bufsize
= size3
* 1.2;
758 buf
= (int *)malloc((size_t)(bufsize
* sizeof(*buf
)));
760 fprintf(stderr
,"malloc failed\n");
764 } else if (*size
> oldsize
) {
765 ip
= (int *)realloc(ip
, (size_t)(size3
* sizeof(*ip
)));
767 fprintf(stderr
,"malloc failed\n");
770 bufsize
= size3
* 1.2;
771 buf
= (int *)realloc(buf
, (size_t)(bufsize
* sizeof(*buf
)));
773 fprintf(stderr
,"realloc failed\n");
778 /* buf[0-2] are special and do not contain actual data */
779 buf
[0] = buf
[1] = buf
[2] = 0;
780 minint
[0] = minint
[1] = minint
[2] = INT_MAX
;
781 maxint
[0] = maxint
[1] = maxint
[2] = INT_MIN
;
786 oldlint1
= oldlint2
= oldlint3
= 0;
787 while(lfp
< fp
+ size3
) {
788 /* find nearest integer */
790 lf
= *lfp
* *precision
+ 0.5;
792 lf
= *lfp
* *precision
- 0.5;
793 if (fabs(lf
) > MAXABS
) {
794 /* scaling would cause overflow */
798 if (lint1
< minint
[0]) minint
[0] = lint1
;
799 if (lint1
> maxint
[0]) maxint
[0] = lint1
;
803 lf
= *lfp
* *precision
+ 0.5;
805 lf
= *lfp
* *precision
- 0.5;
806 if (fabs(lf
) > MAXABS
) {
807 /* scaling would cause overflow */
811 if (lint2
< minint
[1]) minint
[1] = lint2
;
812 if (lint2
> maxint
[1]) maxint
[1] = lint2
;
816 lf
= *lfp
* *precision
+ 0.5;
818 lf
= *lfp
* *precision
- 0.5;
819 if (fabs(lf
) > MAXABS
) {
820 /* scaling would cause overflow */
824 if (lint3
< minint
[2]) minint
[2] = lint3
;
825 if (lint3
> maxint
[2]) maxint
[2] = lint3
;
828 diff
= abs(oldlint1
-lint1
)+abs(oldlint2
-lint2
)+abs(oldlint3
-lint3
);
829 if (diff
< mindiff
&& lfp
> fp
+ 3)
835 if ( (xdr_int(xdrs
, &(minint
[0])) == 0) ||
836 (xdr_int(xdrs
, &(minint
[1])) == 0) ||
837 (xdr_int(xdrs
, &(minint
[2])) == 0) ||
838 (xdr_int(xdrs
, &(maxint
[0])) == 0) ||
839 (xdr_int(xdrs
, &(maxint
[1])) == 0) ||
840 (xdr_int(xdrs
, &(maxint
[2])) == 0))
845 if ((float)maxint
[0] - (float)minint
[0] >= MAXABS
||
846 (float)maxint
[1] - (float)minint
[1] >= MAXABS
||
847 (float)maxint
[2] - (float)minint
[2] >= MAXABS
) {
848 /* turning value in unsigned by subtracting minint
849 * would cause overflow
853 sizeint
[0] = maxint
[0] - minint
[0]+1;
854 sizeint
[1] = maxint
[1] - minint
[1]+1;
855 sizeint
[2] = maxint
[2] - minint
[2]+1;
857 /* check if one of the sizes is to big to be multiplied */
858 if ((sizeint
[0] | sizeint
[1] | sizeint
[2] ) > 0xffffff) {
859 bitsizeint
[0] = sizeofint(sizeint
[0]);
860 bitsizeint
[1] = sizeofint(sizeint
[1]);
861 bitsizeint
[2] = sizeofint(sizeint
[2]);
862 bitsize
= 0; /* flag the use of large sizes */
864 bitsize
= sizeofints(3, sizeint
);
867 luip
= (unsigned int *) ip
;
869 while (smallidx
< LASTIDX
&& magicints
[smallidx
] < mindiff
) {
872 if(xdr_int(xdrs
, &smallidx
) == 0)
875 maxidx
= MIN(LASTIDX
, smallidx
+ 8) ;
876 minidx
= maxidx
- 8; /* often this equal smallidx */
877 smaller
= magicints
[MAX(FIRSTIDX
, smallidx
-1)] / 2;
878 smallnum
= magicints
[smallidx
] / 2;
879 sizesmall
[0] = sizesmall
[1] = sizesmall
[2] = magicints
[smallidx
];
880 larger
= magicints
[maxidx
] / 2;
884 thiscoord
= (int *)(luip
) + i
* 3;
885 if (smallidx
< maxidx
&& i
>= 1 &&
886 abs(thiscoord
[0] - prevcoord
[0]) < larger
&&
887 abs(thiscoord
[1] - prevcoord
[1]) < larger
&&
888 abs(thiscoord
[2] - prevcoord
[2]) < larger
) {
890 } else if (smallidx
> minidx
) {
896 if (abs(thiscoord
[0] - thiscoord
[3]) < smallnum
&&
897 abs(thiscoord
[1] - thiscoord
[4]) < smallnum
&&
898 abs(thiscoord
[2] - thiscoord
[5]) < smallnum
) {
899 /* interchange first with second atom for better
900 * compression of water molecules
902 tmp
= thiscoord
[0]; thiscoord
[0] = thiscoord
[3];
904 tmp
= thiscoord
[1]; thiscoord
[1] = thiscoord
[4];
906 tmp
= thiscoord
[2]; thiscoord
[2] = thiscoord
[5];
912 tmpcoord
[0] = thiscoord
[0] - minint
[0];
913 tmpcoord
[1] = thiscoord
[1] - minint
[1];
914 tmpcoord
[2] = thiscoord
[2] - minint
[2];
916 sendbits(buf
, bitsizeint
[0], tmpcoord
[0]);
917 sendbits(buf
, bitsizeint
[1], tmpcoord
[1]);
918 sendbits(buf
, bitsizeint
[2], tmpcoord
[2]);
920 sendints(buf
, 3, bitsize
, sizeint
, tmpcoord
);
922 prevcoord
[0] = thiscoord
[0];
923 prevcoord
[1] = thiscoord
[1];
924 prevcoord
[2] = thiscoord
[2];
925 thiscoord
= thiscoord
+ 3;
929 if (is_small
== 0 && is_smaller
== -1)
931 while (is_small
&& run
< 8*3) {
932 if (is_smaller
== -1 && (
933 SQR(thiscoord
[0] - prevcoord
[0]) +
934 SQR(thiscoord
[1] - prevcoord
[1]) +
935 SQR(thiscoord
[2] - prevcoord
[2]) >= smaller
* smaller
)) {
939 tmpcoord
[run
++] = thiscoord
[0] - prevcoord
[0] + smallnum
;
940 tmpcoord
[run
++] = thiscoord
[1] - prevcoord
[1] + smallnum
;
941 tmpcoord
[run
++] = thiscoord
[2] - prevcoord
[2] + smallnum
;
943 prevcoord
[0] = thiscoord
[0];
944 prevcoord
[1] = thiscoord
[1];
945 prevcoord
[2] = thiscoord
[2];
948 thiscoord
= thiscoord
+ 3;
951 abs(thiscoord
[0] - prevcoord
[0]) < smallnum
&&
952 abs(thiscoord
[1] - prevcoord
[1]) < smallnum
&&
953 abs(thiscoord
[2] - prevcoord
[2]) < smallnum
) {
957 if (run
!= prevrun
|| is_smaller
!= 0) {
959 sendbits(buf
, 1, 1); /* flag the change in run-length */
960 sendbits(buf
, 5, run
+is_smaller
+1);
962 sendbits(buf
, 1, 0); /* flag the fact that runlength did not change */
964 for (k
=0; k
< run
; k
+=3) {
965 sendints(buf
, 3, smallidx
, sizesmall
, &tmpcoord
[k
]);
967 if (is_smaller
!= 0) {
968 smallidx
+= is_smaller
;
969 if (is_smaller
< 0) {
971 smaller
= magicints
[smallidx
-1] / 2;
974 smallnum
= magicints
[smallidx
] / 2;
976 sizesmall
[0] = sizesmall
[1] = sizesmall
[2] = magicints
[smallidx
];
979 if (buf
[1] != 0) buf
[0]++;
980 /* buf[0] holds the length in bytes */
981 if(xdr_int(xdrs
, &(buf
[0])) == 0)
984 return errval
* (xdr_opaque(xdrs
, (char *)&(buf
[3]), (unsigned int)buf
[0]));
987 /* xdrs is open for reading */
989 if (xdr_int(xdrs
, &lsize
) == 0)
991 if (*size
!= 0 && lsize
!= *size
) {
992 fprintf(stderr
, "wrong number of coordinates in xdr3dfcoord; "
993 "%d arg vs %d in file", *size
, lsize
);
999 return (xdr_vector(xdrs
, (char *) fp
, (unsigned int)size3
,
1000 (unsigned int)sizeof(*fp
), (xdrproc_t
)xdr_float
));
1002 if(xdr_float(xdrs
, precision
) == 0)
1006 ip
= (int *)malloc((size_t)(size3
* sizeof(*ip
)));
1008 fprintf(stderr
,"malloc failed\n");
1011 bufsize
= size3
* 1.2;
1012 buf
= (int *)malloc((size_t)(bufsize
* sizeof(*buf
)));
1014 fprintf(stderr
,"malloc failed\n");
1018 } else if (*size
> oldsize
) {
1019 ip
= (int *)realloc(ip
, (size_t)(size3
* sizeof(*ip
)));
1021 fprintf(stderr
,"malloc failed\n");
1024 bufsize
= size3
* 1.2;
1025 buf
= (int *)realloc(buf
, (size_t)(bufsize
* sizeof(*buf
)));
1027 fprintf(stderr
,"malloc failed\n");
1032 buf
[0] = buf
[1] = buf
[2] = 0;
1034 if ( (xdr_int(xdrs
, &(minint
[0])) == 0) ||
1035 (xdr_int(xdrs
, &(minint
[1])) == 0) ||
1036 (xdr_int(xdrs
, &(minint
[2])) == 0) ||
1037 (xdr_int(xdrs
, &(maxint
[0])) == 0) ||
1038 (xdr_int(xdrs
, &(maxint
[1])) == 0) ||
1039 (xdr_int(xdrs
, &(maxint
[2])) == 0))
1044 sizeint
[0] = maxint
[0] - minint
[0]+1;
1045 sizeint
[1] = maxint
[1] - minint
[1]+1;
1046 sizeint
[2] = maxint
[2] - minint
[2]+1;
1048 /* check if one of the sizes is to big to be multiplied */
1049 if ((sizeint
[0] | sizeint
[1] | sizeint
[2] ) > 0xffffff) {
1050 bitsizeint
[0] = sizeofint(sizeint
[0]);
1051 bitsizeint
[1] = sizeofint(sizeint
[1]);
1052 bitsizeint
[2] = sizeofint(sizeint
[2]);
1053 bitsize
= 0; /* flag the use of large sizes */
1055 bitsize
= sizeofints(3, sizeint
);
1058 if (xdr_int(xdrs
, &smallidx
) == 0)
1060 maxidx
= MIN(LASTIDX
, smallidx
+ 8) ;
1061 minidx
= maxidx
- 8; /* often this equal smallidx */
1062 smaller
= magicints
[MAX(FIRSTIDX
, smallidx
-1)] / 2;
1063 smallnum
= magicints
[smallidx
] / 2;
1064 sizesmall
[0] = sizesmall
[1] = sizesmall
[2] = magicints
[smallidx
] ;
1065 larger
= magicints
[maxidx
];
1067 /* buf[0] holds the length in bytes */
1069 if (xdr_int(xdrs
, &(buf
[0])) == 0)
1071 if (xdr_opaque(xdrs
, (char *)&(buf
[3]), (unsigned int)buf
[0]) == 0)
1073 buf
[0] = buf
[1] = buf
[2] = 0;
1076 inv_precision
= 1.0 / * precision
;
1080 while ( i
< lsize
) {
1081 thiscoord
= (int *)(lip
) + i
* 3;
1084 thiscoord
[0] = receivebits(buf
, bitsizeint
[0]);
1085 thiscoord
[1] = receivebits(buf
, bitsizeint
[1]);
1086 thiscoord
[2] = receivebits(buf
, bitsizeint
[2]);
1088 receiveints(buf
, 3, bitsize
, sizeint
, thiscoord
);
1092 thiscoord
[0] += minint
[0];
1093 thiscoord
[1] += minint
[1];
1094 thiscoord
[2] += minint
[2];
1096 prevcoord
[0] = thiscoord
[0];
1097 prevcoord
[1] = thiscoord
[1];
1098 prevcoord
[2] = thiscoord
[2];
1101 flag
= receivebits(buf
, 1);
1104 run
= receivebits(buf
, 5);
1105 is_smaller
= run
% 3;
1111 for (k
= 0; k
< run
; k
+=3) {
1112 receiveints(buf
, 3, smallidx
, sizesmall
, thiscoord
);
1114 thiscoord
[0] += prevcoord
[0] - smallnum
;
1115 thiscoord
[1] += prevcoord
[1] - smallnum
;
1116 thiscoord
[2] += prevcoord
[2] - smallnum
;
1118 /* interchange first with second atom for better
1119 * compression of water molecules
1121 tmp
= thiscoord
[0]; thiscoord
[0] = prevcoord
[0];
1123 tmp
= thiscoord
[1]; thiscoord
[1] = prevcoord
[1];
1125 tmp
= thiscoord
[2]; thiscoord
[2] = prevcoord
[2];
1127 *lfp
++ = prevcoord
[0] * inv_precision
;
1128 *lfp
++ = prevcoord
[1] * inv_precision
;
1129 *lfp
++ = prevcoord
[2] * inv_precision
;
1131 prevcoord
[0] = thiscoord
[0];
1132 prevcoord
[1] = thiscoord
[1];
1133 prevcoord
[2] = thiscoord
[2];
1135 *lfp
++ = thiscoord
[0] * inv_precision
;
1136 *lfp
++ = thiscoord
[1] * inv_precision
;
1137 *lfp
++ = thiscoord
[2] * inv_precision
;
1140 *lfp
++ = thiscoord
[0] * inv_precision
;
1141 *lfp
++ = thiscoord
[1] * inv_precision
;
1142 *lfp
++ = thiscoord
[2] * inv_precision
;
1144 smallidx
+= is_smaller
;
1145 if (is_smaller
< 0) {
1147 if (smallidx
> FIRSTIDX
) {
1148 smaller
= magicints
[smallidx
- 1] /2;
1152 } else if (is_smaller
> 0) {
1154 smallnum
= magicints
[smallidx
] / 2;
1156 sizesmall
[0] = sizesmall
[1] = sizesmall
[2] = magicints
[smallidx
] ;
1164 /******************************************************************
1166 XTC files have a relatively simple structure.
1167 They have a header of 16 bytes and the rest are
1168 the compressed coordinates of the files. Due to the
1169 compression 00 is not present in the coordinates.
1170 The first 4 bytes of the header are the magic number
1171 1995 (0x000007CB). If we find this number we are guaranteed
1172 to be in the header, due to the presence of so many zeros.
1173 The second 4 bytes are the number of atoms in the frame, and is
1174 assumed to be constant. The third 4 bytes are the frame number.
1175 The last 4 bytes are a floating point representation of the time.
1177 ********************************************************************/
1179 /* Must match definition in xtcio.c */
1181 #define XTC_MAGIC 1995
1184 static const int header_size
= 16;
1186 /* Check if we are at the header start.
1187 At the same time it will also read 1 int */
1188 static int xtc_at_header_start(FILE *fp
, XDR
*xdrs
,
1189 int natoms
, int * timestep
, float * time
){
1196 if((off
= gmx_ftell(fp
)) < 0){
1199 /* read magic natoms and timestep */
1201 if(!xdr_int(xdrs
, &(i_inp
[i
]))){
1202 gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
);
1207 if(i_inp
[0] != XTC_MAGIC
){
1208 if(gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
)){
1213 /* read time and box */
1214 for(i
= 0;i
<10;i
++){
1215 if(!xdr_float(xdrs
, &(f_inp
[i
]))){
1216 gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
);
1220 /* Make a rigourous check to see if we are in the beggining of a header
1221 Hopefully there are no ambiguous cases */
1222 /* This check makes use of the fact that the box matrix has 3 zeroes on the upper
1223 right triangle and that the first element must be nonzero unless the entire matrix is zero
1225 if(i_inp
[1] == natoms
&&
1226 ((f_inp
[1] != 0 && f_inp
[6] == 0) ||
1227 (f_inp
[1] == 0 && f_inp
[5] == 0 && f_inp
[9] == 0))){
1228 if(gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
)){
1232 *timestep
= i_inp
[2];
1235 if(gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
)){
1242 xtc_get_next_frame_number(FILE *fp
, XDR
*xdrs
, int natoms
)
1249 if((off
= gmx_ftell(fp
)) < 0){
1253 /* read one int just to make sure we dont read this frame but the next */
1254 xdr_int(xdrs
,&step
);
1256 ret
= xtc_at_header_start(fp
,xdrs
,natoms
,&step
,&time
);
1258 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1262 }else if(ret
== -1){
1263 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1272 static float xtc_get_next_frame_time(FILE *fp
, XDR
*xdrs
, int natoms
,
1281 if ((off
= gmx_ftell(fp
)) < 0)
1285 /* read one int just to make sure we dont read this frame but the next */
1286 xdr_int(xdrs
, &step
);
1289 ret
= xtc_at_header_start(fp
, xdrs
, natoms
, &step
, &time
);
1293 if (gmx_fseek(fp
,off
,SEEK_SET
))
1302 if (gmx_fseek(fp
,off
,SEEK_SET
))
1314 xtc_get_current_frame_time(FILE *fp
, XDR
*xdrs
, int natoms
, bool * bOK
)
1322 if ((off
= gmx_ftell(fp
)) < 0)
1329 ret
= xtc_at_header_start(fp
, xdrs
, natoms
, &step
, &time
);
1333 if (gmx_fseek(fp
,off
,SEEK_SET
))
1342 if (gmx_fseek(fp
,off
,SEEK_SET
))
1351 if (gmx_fseek(fp
,-2*XDR_INT_SIZE
,SEEK_CUR
))
1360 /* Currently not used, just for completeness */
1362 xtc_get_current_frame_number(FILE *fp
,XDR
*xdrs
,int natoms
, bool * bOK
)
1370 if((off
= gmx_ftell(fp
)) < 0){
1376 ret
= xtc_at_header_start(fp
,xdrs
,natoms
,&step
,&time
);
1379 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1384 }else if(ret
== -1){
1385 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1392 if(gmx_fseek(fp
,-2*XDR_INT_SIZE
,SEEK_CUR
)){
1402 static gmx_off_t
xtc_get_next_frame_start(FILE *fp
, XDR
*xdrs
, int natoms
)
1409 /* read one int just to make sure we dont read this frame but the next */
1410 xdr_int(xdrs
,&step
);
1413 ret
= xtc_at_header_start(fp
,xdrs
,natoms
,&step
,&time
);
1415 if((res
= gmx_ftell(fp
)) >= 0){
1416 return res
- XDR_INT_SIZE
;
1420 }else if(ret
== -1){
1430 xdr_xtc_estimate_dt(FILE *fp
, XDR
*xdrs
, int natoms
, bool * bOK
)
1436 if((off
= gmx_ftell(fp
)) < 0){
1440 tinit
= xtc_get_current_frame_time(fp
,xdrs
,natoms
,bOK
);
1449 res
= xtc_get_next_frame_time(fp
,xdrs
,natoms
,bOK
);
1457 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1466 xdr_xtc_seek_frame(int frame
, FILE *fp
, XDR
*xdrs
, int natoms
)
1472 /* round to 4 bytes */
1475 if(gmx_fseek(fp
,0,SEEK_END
)){
1479 if((high
= gmx_ftell(fp
)) < 0){
1483 /* round to 4 bytes */
1484 high
/= XDR_INT_SIZE
;
1485 high
*= XDR_INT_SIZE
;
1486 offset
= ((high
/2)/XDR_INT_SIZE
)*XDR_INT_SIZE
;
1488 if(gmx_fseek(fp
,offset
,SEEK_SET
)){
1494 fr
= xtc_get_next_frame_number(fp
,xdrs
,natoms
);
1499 if(fr
!= frame
&& abs(low
-high
) > header_size
)
1509 /* round to 4 bytes */
1510 offset
= (((high
+low
)/2)/4)*4;
1512 if(gmx_fseek(fp
,offset
,SEEK_SET
)){
1521 if(offset
<= header_size
)
1526 if(gmx_fseek(fp
,offset
,SEEK_SET
)){
1530 if((pos
= xtc_get_next_frame_start(fp
,xdrs
,natoms
))< 0){
1531 /* we probably hit an end of file */
1535 if(gmx_fseek(fp
,pos
,SEEK_SET
)){
1544 int xdr_xtc_seek_time(real time
, FILE *fp
, XDR
*xdrs
, int natoms
)
1550 gmx_off_t high
, offset
, pos
;
1554 if (gmx_fseek(fp
,0,SEEK_END
))
1559 if ((high
= gmx_ftell(fp
)) < 0)
1564 high
/= XDR_INT_SIZE
;
1565 high
*= XDR_INT_SIZE
;
1566 offset
= ((high
/ 2) / XDR_INT_SIZE
) * XDR_INT_SIZE
;
1568 if (gmx_fseek(fp
,offset
,SEEK_SET
))
1575 * No need to call xdr_xtc_estimate_dt here - since xdr_xtc_estimate_dt is called first thing in the loop
1576 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1586 dt
= xdr_xtc_estimate_dt(fp
, xdrs
, natoms
, &bOK
);
1597 /* Found a place in the trajectory that has positive time step while
1598 other has negative time step */
1607 /* Found a place in the trajectory that has positive time step while
1608 other has negative time step */
1614 t
= xtc_get_next_frame_time(fp
, xdrs
, natoms
, &bOK
);
1620 /* If we are before the target time and the time step is positive or 0, or we have
1621 after the target time and the time step is negative, or the difference between
1622 the current time and the target time is bigger than dt and above all the distance between high
1623 and low is bigger than 1 frame, then do another step of binary search. Otherwise stop and check
1624 if we reached the solution */
1625 if ((((t
< time
&& dt_sign
>= 0) || (t
> time
&& dt_sign
== -1)) || ((t
1626 - time
) >= dt
&& dt_sign
>= 0)
1627 || ((time
- t
) >= -dt
&& dt_sign
< 0)) && (abs(low
- high
)
1630 if (dt
>= 0 && dt_sign
!= -1)
1641 else if (dt
<= 0 && dt_sign
== -1)
1654 /* We should never reach here */
1657 /* round to 4 bytes and subtract header*/
1658 offset
= (((high
+ low
) / 2) / XDR_INT_SIZE
) * XDR_INT_SIZE
;
1659 if (gmx_fseek(fp
,offset
,SEEK_SET
))
1666 if (abs(low
- high
) <= header_size
)
1670 /* re-estimate dt */
1671 if (xdr_xtc_estimate_dt(fp
, xdrs
, natoms
, &bOK
) != dt
)
1675 dt
= xdr_xtc_estimate_dt(fp
, xdrs
, natoms
, &bOK
);
1678 if (t
>= time
&& t
- time
< dt
)
1685 if (offset
<= header_size
)
1690 gmx_fseek(fp
,offset
,SEEK_SET
);
1692 if ((pos
= xtc_get_next_frame_start(fp
, xdrs
, natoms
)) < 0)
1697 if (gmx_fseek(fp
,pos
,SEEK_SET
))
1705 xdr_xtc_get_last_frame_time(FILE *fp
, XDR
*xdrs
, int natoms
, bool * bOK
)
1711 off
= gmx_ftell(fp
);
1717 if( (res
= gmx_fseek(fp
,-3*XDR_INT_SIZE
,SEEK_END
)) != 0){
1722 time
= xtc_get_current_frame_time(fp
, xdrs
, natoms
, bOK
);
1727 if( (res
= gmx_fseek(fp
,off
,SEEK_SET
)) != 0){
1736 xdr_xtc_get_last_frame_number(FILE *fp
, XDR
*xdrs
, int natoms
, bool * bOK
)
1743 if((off
= gmx_ftell(fp
)) < 0){
1749 if(gmx_fseek(fp
,-3*XDR_INT_SIZE
,SEEK_END
)){
1754 frame
= xtc_get_current_frame_number(fp
, xdrs
, natoms
, bOK
);
1760 if(gmx_fseek(fp
,off
,SEEK_SET
)){