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
52 # define gmx_fseek(A,B,C) fseeko(A,B,C)
53 # define gmx_ftell(A) ftello(A)
54 # define gmx_off_t off_t
56 # define gmx_fseek(A,B,C) fseek(A,B,C)
57 # define gmx_ftell(A) ftell(A)
58 # define gmx_off_t int
63 static FILE *xdrfiles
[MAXID
];
64 static XDR
*xdridptr
[MAXID
];
65 static char xdrmodes
[MAXID
];
66 static unsigned int cnt
;
68 /* This is just for clarity - it can never be anything but 4! */
69 #define XDR_INT_SIZE 4
73 typedef void (* F77_FUNC(xdrfproc
,XDRFPROC
))(int *, void *, int *);
75 int ftocstr(char *ds
, int dl
, char *ss
, int sl
)
83 while ( --p
>= ss
&& *p
== ' ' );
96 int ctofstr(char *ds
, int dl
, char *ss
)
99 /* src string (0-term) */
111 F77_FUNC(xdrfbool
,XDRFBOOL
)(int *xdrid
, int *pb
, int *ret
)
113 *ret
= xdr_bool(xdridptr
[*xdrid
], pb
);
118 F77_FUNC(xdrfchar
,XDRFCHAR
)(int *xdrid
, char *cp
, int *ret
)
120 *ret
= xdr_char(xdridptr
[*xdrid
], cp
);
125 F77_FUNC(xdrfdouble
,XDRFDOUBLE
)(int *xdrid
, double *dp
, int *ret
)
127 *ret
= xdr_double(xdridptr
[*xdrid
], dp
);
128 cnt
+= sizeof(double);
132 F77_FUNC(xdrffloat
,XDRFFLOAT
)(int *xdrid
, float *fp
, int *ret
)
134 *ret
= xdr_float(xdridptr
[*xdrid
], fp
);
135 cnt
+= sizeof(float);
139 F77_FUNC(xdrfint
,XDRFINT
)(int *xdrid
, int *ip
, int *ret
)
141 *ret
= xdr_int(xdridptr
[*xdrid
], ip
);
145 F77_FUNC(xdrfshort
,XDRFSHORT
)(int *xdrid
, short *sp
, int *ret
)
147 *ret
= xdr_short(xdridptr
[*xdrid
], sp
);
152 F77_FUNC(xdrfuchar
,XDRFUCHAR
)(int *xdrid
, unsigned char *ucp
, int *ret
)
154 *ret
= xdr_u_char(xdridptr
[*xdrid
], (u_char
*)ucp
);
160 F77_FUNC(xdrfushort
,XDRFUSHORT
)(int *xdrid
, unsigned short *usp
, int *ret
)
162 *ret
= xdr_u_short(xdridptr
[*xdrid
], (unsigned short *)usp
);
163 cnt
+= sizeof(unsigned short);
167 F77_FUNC(xdrf3dfcoord
,XDRF3DFCOORD
)(int *xdrid
, float *fp
, int *size
, float *precision
, int *ret
)
169 *ret
= xdr3dfcoord(xdridptr
[*xdrid
], fp
, size
, precision
);
173 F77_FUNC(xdrfstring
,XDRFSTRING
)(int *xdrid
, char * sp_ptr
,
174 int *maxsize
, int *ret
, int sp_len
)
178 tsp
= (char*) malloc((size_t)(((sp_len
) + 1) * sizeof(char)));
183 if (ftocstr(tsp
, *maxsize
+1, sp_ptr
, sp_len
)) {
188 *ret
= xdr_string(xdridptr
[*xdrid
], (char **) &tsp
, (unsigned int) *maxsize
);
189 ctofstr( sp_ptr
, sp_len
, tsp
);
195 F77_FUNC(xdrfwrapstring
,XDRFWRAPSTRING
)(int *xdrid
, char *sp_ptr
,
196 int *ret
, int sp_len
)
200 maxsize
= (sp_len
) + 1;
201 tsp
= (char*) malloc((size_t)(maxsize
* sizeof(char)));
206 if (ftocstr(tsp
, maxsize
, sp_ptr
, sp_len
)) {
211 *ret
= xdr_string(xdridptr
[*xdrid
], (char **) &tsp
, (u_int
)maxsize
);
212 ctofstr( sp_ptr
, sp_len
, tsp
);
218 F77_FUNC(xdrfopaque
,XDRFOPAQUE
)(int *xdrid
, caddr_t
*cp
, int *ccnt
, int *ret
)
220 *ret
= xdr_opaque(xdridptr
[*xdrid
], (caddr_t
)*cp
, (u_int
)*ccnt
);
225 F77_FUNC(xdrfsetpos
,XDRFSETPOS
)(int *xdrid
, int *pos
, int *ret
)
227 *ret
= xdr_setpos(xdridptr
[*xdrid
], (u_int
) *pos
);
232 F77_FUNC(xdrf
,XDRF
)(int *xdrid
, int *pos
)
234 *pos
= xdr_getpos(xdridptr
[*xdrid
]);
238 F77_FUNC(xdrfvector
,XDRFVECTOR
)(int *xdrid
, char *cp
, int *size
, F77_FUNC(xdrfproc
,XDRFPROC
) elproc
, int *ret
)
242 for (lcnt
= 0; lcnt
< *size
; lcnt
++) {
243 elproc(xdrid
, (cp
+cnt
) , ret
);
249 F77_FUNC(xdrfclose
,XDRFCLOSE
)(int *xdrid
, int *ret
)
251 *ret
= xdrclose(xdridptr
[*xdrid
]);
256 F77_FUNC(xdrfopen
,XDRFOPEN
)(int *xdrid
, char *fp_ptr
, char *mode_ptr
,
257 int *ret
, int fp_len
, int mode_len
)
262 if (ftocstr(fname
, sizeof(fname
), fp_ptr
, fp_len
)) {
265 if (ftocstr(fmode
, sizeof(fmode
), mode_ptr
,
270 *xdrid
= xdropen(NULL
, fname
, fmode
);
276 #endif /* GMX_FORTRAN */
278 /*___________________________________________________________________________
280 | what follows are the C routines for opening, closing xdr streams
281 | and the routine to read/write compressed coordinates together
282 | with some routines to assist in this task (those are marked
283 | static and cannot be called from user programs)
285 #define MAXABS INT_MAX-2
288 #define MIN(x,y) ((x) < (y) ? (x):(y))
291 #define MAX(x,y) ((x) > (y) ? (x):(y))
294 #define SQR(x) ((x)*(x))
296 static int magicints
[] = {
297 0, 0, 0, 0, 0, 0, 0, 0, 0,
298 8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
299 80, 101, 128, 161, 203, 256, 322, 406, 512, 645,
300 812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501,
301 8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536,
302 82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,
303 832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042,
304 8388607, 10568983, 13316085, 16777216 };
307 /* note that magicints[FIRSTIDX-1] == 0 */
308 #define LASTIDX (sizeof(magicints) / sizeof(*magicints))
311 /*__________________________________________________________________________
313 | xdropen - open xdr file
315 | This versions differs from xdrstdio_create, because I need to know
316 | the state of the file (read or write) so I can use xdr3dfcoord
317 | in eigther read or write mode, and the file descriptor
318 | so I can close the file (something xdr_destroy doesn't do).
322 int xdropen(XDR
*xdrs
, const char *filename
, const char *type
) {
323 static int init_done
= 0;
328 if (init_done
== 0) {
329 for (xdrid
= 1; xdrid
< MAXID
; xdrid
++) {
330 xdridptr
[xdrid
] = NULL
;
335 while (xdrid
< MAXID
&& xdridptr
[xdrid
] != NULL
) {
338 if (xdrid
== MAXID
) {
341 if (*type
== 'w' || *type
== 'W')
343 xdrmodes
[xdrid
] = 'w';
344 strcpy(newtype
, "wb+");
347 else if (*type
== 'a' || *type
== 'A')
349 xdrmodes
[xdrid
] = 'a';
350 strcpy(newtype
, "ab+");
353 else if (strncasecmp(type
, "r+", 2) == 0)
355 xdrmodes
[xdrid
] = 'a';
356 strcpy(newtype
, "rb+");
361 xdrmodes
[xdrid
] = 'r';
362 strcpy(newtype
, "rb");
365 xdrfiles
[xdrid
] = fopen(filename
, newtype
);
367 if (xdrfiles
[xdrid
] == NULL
) {
372 /* next test isn't usefull in the case of C language
373 * but is used for the Fortran interface
374 * (C users are expected to pass the address of an already allocated
378 xdridptr
[xdrid
] = (XDR
*) malloc((size_t)sizeof(XDR
));
379 xdrstdio_create(xdridptr
[xdrid
], xdrfiles
[xdrid
], lmode
);
381 xdridptr
[xdrid
] = xdrs
;
382 xdrstdio_create(xdrs
, xdrfiles
[xdrid
], lmode
);
387 /*_________________________________________________________________________
389 | xdrclose - close a xdr file
391 | This will flush the xdr buffers, and destroy the xdr stream.
392 | It also closes the associated file descriptor (this is *not*
393 | done by xdr_destroy).
397 int xdrclose(XDR
*xdrs
) {
402 fprintf(stderr
, "xdrclose: passed a NULL pointer\n");
405 for (xdrid
= 1; xdrid
< MAXID
&& rc
==0; xdrid
++) {
406 if (xdridptr
[xdrid
] == xdrs
) {
409 rc
= fclose(xdrfiles
[xdrid
]);
410 xdridptr
[xdrid
] = NULL
;
411 return !rc
; /* xdr routines return 0 when ok */
414 fprintf(stderr
, "xdrclose: no such open xdr file\n");
417 /* to make some compilers happy: */
422 xdr_get_fp(int xdrid
)
424 return xdrfiles
[xdrid
];
428 /*____________________________________________________________________________
430 | sendbits - encode num into buf using the specified number of bits
432 | This routines appends the value of num to the bits already present in
433 | the array buf. You need to give it the number of bits to use and you
434 | better make sure that this number of bits is enough to hold the value
435 | Also num must be positive.
439 static void sendbits(int buf
[], int num_of_bits
, int num
) {
441 unsigned int cnt
, lastbyte
;
443 unsigned char * cbuf
;
445 cbuf
= ((unsigned char *)buf
) + 3 * sizeof(*buf
);
446 cnt
= (unsigned int) buf
[0];
448 lastbyte
=(unsigned int) buf
[2];
449 while (num_of_bits
>= 8) {
450 lastbyte
= (lastbyte
<< 8) | ((num
>> (num_of_bits
-8)) /* & 0xff*/);
451 cbuf
[cnt
++] = lastbyte
>> lastbits
;
454 if (num_of_bits
> 0) {
455 lastbyte
= (lastbyte
<< num_of_bits
) | num
;
456 lastbits
+= num_of_bits
;
459 cbuf
[cnt
++] = lastbyte
>> lastbits
;
466 cbuf
[cnt
] = lastbyte
<< (8 - lastbits
);
470 /*_________________________________________________________________________
472 | sizeofint - calculate bitsize of an integer
474 | return the number of bits needed to store an integer with given max size
478 static int sizeofint(const int size
) {
482 while (size
>= num
&& num_of_bits
< 32) {
489 /*___________________________________________________________________________
491 | sizeofints - calculate 'bitsize' of compressed ints
493 | given the number of small unsigned integers and the maximum value
494 | return the number of bits needed to read or write them with the
495 | routines receiveints and sendints. You need this parameter when
496 | calling these routines. Note that for many calls I can use
497 | the variable 'smallidx' which is exactly the number of bits, and
498 | So I don't need to call 'sizeofints for those calls.
501 static int sizeofints( const int num_of_ints
, unsigned int sizes
[]) {
504 unsigned int num_of_bytes
, num_of_bits
, bytecnt
, tmp
;
508 for (i
=0; i
< num_of_ints
; i
++) {
510 for (bytecnt
= 0; bytecnt
< num_of_bytes
; bytecnt
++) {
511 tmp
= bytes
[bytecnt
] * sizes
[i
] + tmp
;
512 bytes
[bytecnt
] = tmp
& 0xff;
516 bytes
[bytecnt
++] = tmp
& 0xff;
519 num_of_bytes
= bytecnt
;
523 while (bytes
[num_of_bytes
] >= num
) {
527 return num_of_bits
+ num_of_bytes
* 8;
531 /*____________________________________________________________________________
533 | sendints - send a small set of small integers in compressed format
535 | this routine is used internally by xdr3dfcoord, to send a set of
536 | small integers to the buffer.
537 | Multiplication with fixed (specified maximum ) sizes is used to get
538 | to one big, multibyte integer. Allthough the routine could be
539 | modified to handle sizes bigger than 16777216, or more than just
540 | a few integers, this is not done, because the gain in compression
541 | isn't worth the effort. Note that overflowing the multiplication
542 | or the byte buffer (32 bytes) is unchecked and causes bad results.
546 static void sendints(int buf
[], const int num_of_ints
, const int num_of_bits
,
547 unsigned int sizes
[], unsigned int nums
[]) {
549 int i
, num_of_bytes
, bytecnt
;
550 unsigned int bytes
[32], tmp
;
555 bytes
[num_of_bytes
++] = tmp
& 0xff;
559 for (i
= 1; i
< num_of_ints
; i
++) {
560 if (nums
[i
] >= sizes
[i
]) {
561 fprintf(stderr
,"major breakdown in sendints num %u doesn't "
562 "match size %u\n", nums
[i
], sizes
[i
]);
565 /* use one step multiply */
567 for (bytecnt
= 0; bytecnt
< num_of_bytes
; bytecnt
++) {
568 tmp
= bytes
[bytecnt
] * sizes
[i
] + tmp
;
569 bytes
[bytecnt
] = tmp
& 0xff;
573 bytes
[bytecnt
++] = tmp
& 0xff;
576 num_of_bytes
= bytecnt
;
578 if (num_of_bits
>= num_of_bytes
* 8) {
579 for (i
= 0; i
< num_of_bytes
; i
++) {
580 sendbits(buf
, 8, bytes
[i
]);
582 sendbits(buf
, num_of_bits
- num_of_bytes
* 8, 0);
584 for (i
= 0; i
< num_of_bytes
-1; i
++) {
585 sendbits(buf
, 8, bytes
[i
]);
587 sendbits(buf
, num_of_bits
- (num_of_bytes
-1) * 8, bytes
[i
]);
592 /*___________________________________________________________________________
594 | receivebits - decode number from buf using specified number of bits
596 | extract the number of bits from the array buf and construct an integer
597 | from it. Return that value.
601 static int receivebits(int buf
[], int num_of_bits
) {
603 int cnt
, num
, lastbits
;
604 unsigned int lastbyte
;
605 unsigned char * cbuf
;
606 int mask
= (1 << num_of_bits
) -1;
608 cbuf
= ((unsigned char *)buf
) + 3 * sizeof(*buf
);
610 lastbits
= (unsigned int) buf
[1];
611 lastbyte
= (unsigned int) buf
[2];
614 while (num_of_bits
>= 8) {
615 lastbyte
= ( lastbyte
<< 8 ) | cbuf
[cnt
++];
616 num
|= (lastbyte
>> lastbits
) << (num_of_bits
- 8);
619 if (num_of_bits
> 0) {
620 if (lastbits
< num_of_bits
) {
622 lastbyte
= (lastbyte
<< 8) | cbuf
[cnt
++];
624 lastbits
-= num_of_bits
;
625 num
|= (lastbyte
>> lastbits
) & ((1 << num_of_bits
) -1);
634 /*____________________________________________________________________________
636 | receiveints - decode 'small' integers from the buf array
638 | this routine is the inverse from sendints() and decodes the small integers
639 | written to buf by calculating the remainder and doing divisions with
640 | the given sizes[]. You need to specify the total number of bits to be
641 | used from buf in num_of_bits.
645 static void receiveints(int buf
[], const int num_of_ints
, int num_of_bits
,
646 unsigned int sizes
[], int nums
[]) {
648 int i
, j
, num_of_bytes
, p
, num
;
650 bytes
[1] = bytes
[2] = bytes
[3] = 0;
652 while (num_of_bits
> 8) {
653 bytes
[num_of_bytes
++] = receivebits(buf
, 8);
656 if (num_of_bits
> 0) {
657 bytes
[num_of_bytes
++] = receivebits(buf
, num_of_bits
);
659 for (i
= num_of_ints
-1; i
> 0; i
--) {
661 for (j
= num_of_bytes
-1; j
>=0; j
--) {
662 num
= (num
<< 8) | bytes
[j
];
665 num
= num
- p
* sizes
[i
];
669 nums
[0] = bytes
[0] | (bytes
[1] << 8) | (bytes
[2] << 16) | (bytes
[3] << 24);
672 /*____________________________________________________________________________
674 | xdr3dfcoord - read or write compressed 3d coordinates to xdr file.
676 | this routine reads or writes (depending on how you opened the file with
677 | xdropen() ) a large number of 3d coordinates (stored in *fp).
678 | The number of coordinates triplets to write is given by *size. On
679 | read this number may be zero, in which case it reads as many as were written
680 | or it may specify the number if triplets to read (which should match the
682 | Compression is achieved by first converting all floating numbers to integer
683 | using multiplication by *precision and rounding to the nearest integer.
684 | Then the minimum and maximum value are calculated to determine the range.
685 | The limited range of integers so found, is used to compress the coordinates.
686 | In addition the differences between succesive coordinates is calculated.
687 | If the difference happens to be 'small' then only the difference is saved,
688 | compressing the data even more. The notion of 'small' is changed dynamically
689 | and is enlarged or reduced whenever needed or possible.
690 | Extra compression is achieved in the case of GROMOS and coordinates of
691 | water molecules. GROMOS first writes out the Oxygen position, followed by
692 | the two hydrogens. In order to make the differences smaller (and thereby
693 | compression the data better) the order is changed into first one hydrogen
694 | then the oxygen, followed by the other hydrogen. This is rather special, but
695 | it shouldn't harm in the general case.
699 int xdr3dfcoord(XDR
*xdrs
, float *fp
, int *size
, float *precision
) {
702 static int *ip
= NULL
;
706 int minint
[3], maxint
[3], mindiff
, *lip
, diff
;
707 int lint1
, lint2
, lint3
, oldlint1
, oldlint2
, oldlint3
, smallidx
;
709 unsigned sizeint
[3], sizesmall
[3], bitsizeint
[3], size3
, *luip
;
711 int smallnum
, smaller
, larger
, i
, is_small
, is_smaller
, run
, prevrun
;
713 int tmp
, *thiscoord
, prevcoord
[3];
714 unsigned int tmpcoord
[30];
716 int bufsize
, xdrid
, lsize
;
717 unsigned int bitsize
;
722 bitsizeint
[0] = bitsizeint
[1] = bitsizeint
[2] = 0;
723 prevcoord
[0] = prevcoord
[1] = prevcoord
[2] = 0;
725 /* find out if xdrs is opened for reading or for writing */
727 while (xdridptr
[xdrid
] != xdrs
) {
729 if (xdrid
>= MAXID
) {
730 fprintf(stderr
, "xdr error. no open xdr stream\n");
734 if ((xdrmodes
[xdrid
] == 'w') || (xdrmodes
[xdrid
] == 'a')) {
736 /* xdrs is open for writing */
738 if (xdr_int(xdrs
, size
) == 0)
741 /* when the number of coordinates is small, don't try to compress; just
742 * write them as floats using xdr_vector
745 return (xdr_vector(xdrs
, (char *) fp
, (unsigned int)size3
,
746 (unsigned int)sizeof(*fp
), (xdrproc_t
)xdr_float
));
749 if(xdr_float(xdrs
, precision
) == 0)
753 ip
= (int *)malloc((size_t)(size3
* sizeof(*ip
)));
755 fprintf(stderr
,"malloc failed\n");
758 bufsize
= size3
* 1.2;
759 buf
= (int *)malloc((size_t)(bufsize
* sizeof(*buf
)));
761 fprintf(stderr
,"malloc failed\n");
765 } else if (*size
> oldsize
) {
766 ip
= (int *)realloc(ip
, (size_t)(size3
* sizeof(*ip
)));
768 fprintf(stderr
,"malloc failed\n");
771 bufsize
= size3
* 1.2;
772 buf
= (int *)realloc(buf
, (size_t)(bufsize
* sizeof(*buf
)));
774 fprintf(stderr
,"realloc failed\n");
779 /* buf[0-2] are special and do not contain actual data */
780 buf
[0] = buf
[1] = buf
[2] = 0;
781 minint
[0] = minint
[1] = minint
[2] = INT_MAX
;
782 maxint
[0] = maxint
[1] = maxint
[2] = INT_MIN
;
787 oldlint1
= oldlint2
= oldlint3
= 0;
788 while(lfp
< fp
+ size3
) {
789 /* find nearest integer */
791 lf
= *lfp
* *precision
+ 0.5;
793 lf
= *lfp
* *precision
- 0.5;
794 if (fabs(lf
) > MAXABS
) {
795 /* scaling would cause overflow */
799 if (lint1
< minint
[0]) minint
[0] = lint1
;
800 if (lint1
> maxint
[0]) maxint
[0] = lint1
;
804 lf
= *lfp
* *precision
+ 0.5;
806 lf
= *lfp
* *precision
- 0.5;
807 if (fabs(lf
) > MAXABS
) {
808 /* scaling would cause overflow */
812 if (lint2
< minint
[1]) minint
[1] = lint2
;
813 if (lint2
> maxint
[1]) maxint
[1] = lint2
;
817 lf
= *lfp
* *precision
+ 0.5;
819 lf
= *lfp
* *precision
- 0.5;
820 if (fabs(lf
) > MAXABS
) {
821 /* scaling would cause overflow */
825 if (lint3
< minint
[2]) minint
[2] = lint3
;
826 if (lint3
> maxint
[2]) maxint
[2] = lint3
;
829 diff
= abs(oldlint1
-lint1
)+abs(oldlint2
-lint2
)+abs(oldlint3
-lint3
);
830 if (diff
< mindiff
&& lfp
> fp
+ 3)
836 if ( (xdr_int(xdrs
, &(minint
[0])) == 0) ||
837 (xdr_int(xdrs
, &(minint
[1])) == 0) ||
838 (xdr_int(xdrs
, &(minint
[2])) == 0) ||
839 (xdr_int(xdrs
, &(maxint
[0])) == 0) ||
840 (xdr_int(xdrs
, &(maxint
[1])) == 0) ||
841 (xdr_int(xdrs
, &(maxint
[2])) == 0))
846 if ((float)maxint
[0] - (float)minint
[0] >= MAXABS
||
847 (float)maxint
[1] - (float)minint
[1] >= MAXABS
||
848 (float)maxint
[2] - (float)minint
[2] >= MAXABS
) {
849 /* turning value in unsigned by subtracting minint
850 * would cause overflow
854 sizeint
[0] = maxint
[0] - minint
[0]+1;
855 sizeint
[1] = maxint
[1] - minint
[1]+1;
856 sizeint
[2] = maxint
[2] - minint
[2]+1;
858 /* check if one of the sizes is to big to be multiplied */
859 if ((sizeint
[0] | sizeint
[1] | sizeint
[2] ) > 0xffffff) {
860 bitsizeint
[0] = sizeofint(sizeint
[0]);
861 bitsizeint
[1] = sizeofint(sizeint
[1]);
862 bitsizeint
[2] = sizeofint(sizeint
[2]);
863 bitsize
= 0; /* flag the use of large sizes */
865 bitsize
= sizeofints(3, sizeint
);
868 luip
= (unsigned int *) ip
;
870 while (smallidx
< LASTIDX
&& magicints
[smallidx
] < mindiff
) {
873 if(xdr_int(xdrs
, &smallidx
) == 0)
876 maxidx
= MIN(LASTIDX
, smallidx
+ 8) ;
877 minidx
= maxidx
- 8; /* often this equal smallidx */
878 smaller
= magicints
[MAX(FIRSTIDX
, smallidx
-1)] / 2;
879 smallnum
= magicints
[smallidx
] / 2;
880 sizesmall
[0] = sizesmall
[1] = sizesmall
[2] = magicints
[smallidx
];
881 larger
= magicints
[maxidx
] / 2;
885 thiscoord
= (int *)(luip
) + i
* 3;
886 if (smallidx
< maxidx
&& i
>= 1 &&
887 abs(thiscoord
[0] - prevcoord
[0]) < larger
&&
888 abs(thiscoord
[1] - prevcoord
[1]) < larger
&&
889 abs(thiscoord
[2] - prevcoord
[2]) < larger
) {
891 } else if (smallidx
> minidx
) {
897 if (abs(thiscoord
[0] - thiscoord
[3]) < smallnum
&&
898 abs(thiscoord
[1] - thiscoord
[4]) < smallnum
&&
899 abs(thiscoord
[2] - thiscoord
[5]) < smallnum
) {
900 /* interchange first with second atom for better
901 * compression of water molecules
903 tmp
= thiscoord
[0]; thiscoord
[0] = thiscoord
[3];
905 tmp
= thiscoord
[1]; thiscoord
[1] = thiscoord
[4];
907 tmp
= thiscoord
[2]; thiscoord
[2] = thiscoord
[5];
913 tmpcoord
[0] = thiscoord
[0] - minint
[0];
914 tmpcoord
[1] = thiscoord
[1] - minint
[1];
915 tmpcoord
[2] = thiscoord
[2] - minint
[2];
917 sendbits(buf
, bitsizeint
[0], tmpcoord
[0]);
918 sendbits(buf
, bitsizeint
[1], tmpcoord
[1]);
919 sendbits(buf
, bitsizeint
[2], tmpcoord
[2]);
921 sendints(buf
, 3, bitsize
, sizeint
, tmpcoord
);
923 prevcoord
[0] = thiscoord
[0];
924 prevcoord
[1] = thiscoord
[1];
925 prevcoord
[2] = thiscoord
[2];
926 thiscoord
= thiscoord
+ 3;
930 if (is_small
== 0 && is_smaller
== -1)
932 while (is_small
&& run
< 8*3) {
933 if (is_smaller
== -1 && (
934 SQR(thiscoord
[0] - prevcoord
[0]) +
935 SQR(thiscoord
[1] - prevcoord
[1]) +
936 SQR(thiscoord
[2] - prevcoord
[2]) >= smaller
* smaller
)) {
940 tmpcoord
[run
++] = thiscoord
[0] - prevcoord
[0] + smallnum
;
941 tmpcoord
[run
++] = thiscoord
[1] - prevcoord
[1] + smallnum
;
942 tmpcoord
[run
++] = thiscoord
[2] - prevcoord
[2] + smallnum
;
944 prevcoord
[0] = thiscoord
[0];
945 prevcoord
[1] = thiscoord
[1];
946 prevcoord
[2] = thiscoord
[2];
949 thiscoord
= thiscoord
+ 3;
952 abs(thiscoord
[0] - prevcoord
[0]) < smallnum
&&
953 abs(thiscoord
[1] - prevcoord
[1]) < smallnum
&&
954 abs(thiscoord
[2] - prevcoord
[2]) < smallnum
) {
958 if (run
!= prevrun
|| is_smaller
!= 0) {
960 sendbits(buf
, 1, 1); /* flag the change in run-length */
961 sendbits(buf
, 5, run
+is_smaller
+1);
963 sendbits(buf
, 1, 0); /* flag the fact that runlength did not change */
965 for (k
=0; k
< run
; k
+=3) {
966 sendints(buf
, 3, smallidx
, sizesmall
, &tmpcoord
[k
]);
968 if (is_smaller
!= 0) {
969 smallidx
+= is_smaller
;
970 if (is_smaller
< 0) {
972 smaller
= magicints
[smallidx
-1] / 2;
975 smallnum
= magicints
[smallidx
] / 2;
977 sizesmall
[0] = sizesmall
[1] = sizesmall
[2] = magicints
[smallidx
];
980 if (buf
[1] != 0) buf
[0]++;
981 /* buf[0] holds the length in bytes */
982 if(xdr_int(xdrs
, &(buf
[0])) == 0)
985 return errval
* (xdr_opaque(xdrs
, (char *)&(buf
[3]), (unsigned int)buf
[0]));
988 /* xdrs is open for reading */
990 if (xdr_int(xdrs
, &lsize
) == 0)
992 if (*size
!= 0 && lsize
!= *size
) {
993 fprintf(stderr
, "wrong number of coordinates in xdr3dfcoord; "
994 "%d arg vs %d in file", *size
, lsize
);
1000 return (xdr_vector(xdrs
, (char *) fp
, (unsigned int)size3
,
1001 (unsigned int)sizeof(*fp
), (xdrproc_t
)xdr_float
));
1003 if(xdr_float(xdrs
, precision
) == 0)
1007 ip
= (int *)malloc((size_t)(size3
* sizeof(*ip
)));
1009 fprintf(stderr
,"malloc failed\n");
1012 bufsize
= size3
* 1.2;
1013 buf
= (int *)malloc((size_t)(bufsize
* sizeof(*buf
)));
1015 fprintf(stderr
,"malloc failed\n");
1019 } else if (*size
> oldsize
) {
1020 ip
= (int *)realloc(ip
, (size_t)(size3
* sizeof(*ip
)));
1022 fprintf(stderr
,"malloc failed\n");
1025 bufsize
= size3
* 1.2;
1026 buf
= (int *)realloc(buf
, (size_t)(bufsize
* sizeof(*buf
)));
1028 fprintf(stderr
,"malloc failed\n");
1033 buf
[0] = buf
[1] = buf
[2] = 0;
1035 if ( (xdr_int(xdrs
, &(minint
[0])) == 0) ||
1036 (xdr_int(xdrs
, &(minint
[1])) == 0) ||
1037 (xdr_int(xdrs
, &(minint
[2])) == 0) ||
1038 (xdr_int(xdrs
, &(maxint
[0])) == 0) ||
1039 (xdr_int(xdrs
, &(maxint
[1])) == 0) ||
1040 (xdr_int(xdrs
, &(maxint
[2])) == 0))
1045 sizeint
[0] = maxint
[0] - minint
[0]+1;
1046 sizeint
[1] = maxint
[1] - minint
[1]+1;
1047 sizeint
[2] = maxint
[2] - minint
[2]+1;
1049 /* check if one of the sizes is to big to be multiplied */
1050 if ((sizeint
[0] | sizeint
[1] | sizeint
[2] ) > 0xffffff) {
1051 bitsizeint
[0] = sizeofint(sizeint
[0]);
1052 bitsizeint
[1] = sizeofint(sizeint
[1]);
1053 bitsizeint
[2] = sizeofint(sizeint
[2]);
1054 bitsize
= 0; /* flag the use of large sizes */
1056 bitsize
= sizeofints(3, sizeint
);
1059 if (xdr_int(xdrs
, &smallidx
) == 0)
1061 maxidx
= MIN(LASTIDX
, smallidx
+ 8) ;
1062 minidx
= maxidx
- 8; /* often this equal smallidx */
1063 smaller
= magicints
[MAX(FIRSTIDX
, smallidx
-1)] / 2;
1064 smallnum
= magicints
[smallidx
] / 2;
1065 sizesmall
[0] = sizesmall
[1] = sizesmall
[2] = magicints
[smallidx
] ;
1066 larger
= magicints
[maxidx
];
1068 /* buf[0] holds the length in bytes */
1070 if (xdr_int(xdrs
, &(buf
[0])) == 0)
1072 if (xdr_opaque(xdrs
, (char *)&(buf
[3]), (unsigned int)buf
[0]) == 0)
1074 buf
[0] = buf
[1] = buf
[2] = 0;
1077 inv_precision
= 1.0 / * precision
;
1081 while ( i
< lsize
) {
1082 thiscoord
= (int *)(lip
) + i
* 3;
1085 thiscoord
[0] = receivebits(buf
, bitsizeint
[0]);
1086 thiscoord
[1] = receivebits(buf
, bitsizeint
[1]);
1087 thiscoord
[2] = receivebits(buf
, bitsizeint
[2]);
1089 receiveints(buf
, 3, bitsize
, sizeint
, thiscoord
);
1093 thiscoord
[0] += minint
[0];
1094 thiscoord
[1] += minint
[1];
1095 thiscoord
[2] += minint
[2];
1097 prevcoord
[0] = thiscoord
[0];
1098 prevcoord
[1] = thiscoord
[1];
1099 prevcoord
[2] = thiscoord
[2];
1102 flag
= receivebits(buf
, 1);
1105 run
= receivebits(buf
, 5);
1106 is_smaller
= run
% 3;
1112 for (k
= 0; k
< run
; k
+=3) {
1113 receiveints(buf
, 3, smallidx
, sizesmall
, thiscoord
);
1115 thiscoord
[0] += prevcoord
[0] - smallnum
;
1116 thiscoord
[1] += prevcoord
[1] - smallnum
;
1117 thiscoord
[2] += prevcoord
[2] - smallnum
;
1119 /* interchange first with second atom for better
1120 * compression of water molecules
1122 tmp
= thiscoord
[0]; thiscoord
[0] = prevcoord
[0];
1124 tmp
= thiscoord
[1]; thiscoord
[1] = prevcoord
[1];
1126 tmp
= thiscoord
[2]; thiscoord
[2] = prevcoord
[2];
1128 *lfp
++ = prevcoord
[0] * inv_precision
;
1129 *lfp
++ = prevcoord
[1] * inv_precision
;
1130 *lfp
++ = prevcoord
[2] * inv_precision
;
1132 prevcoord
[0] = thiscoord
[0];
1133 prevcoord
[1] = thiscoord
[1];
1134 prevcoord
[2] = thiscoord
[2];
1136 *lfp
++ = thiscoord
[0] * inv_precision
;
1137 *lfp
++ = thiscoord
[1] * inv_precision
;
1138 *lfp
++ = thiscoord
[2] * inv_precision
;
1141 *lfp
++ = thiscoord
[0] * inv_precision
;
1142 *lfp
++ = thiscoord
[1] * inv_precision
;
1143 *lfp
++ = thiscoord
[2] * inv_precision
;
1145 smallidx
+= is_smaller
;
1146 if (is_smaller
< 0) {
1148 if (smallidx
> FIRSTIDX
) {
1149 smaller
= magicints
[smallidx
- 1] /2;
1153 } else if (is_smaller
> 0) {
1155 smallnum
= magicints
[smallidx
] / 2;
1157 sizesmall
[0] = sizesmall
[1] = sizesmall
[2] = magicints
[smallidx
] ;
1165 /******************************************************************
1167 XTC files have a relatively simple structure.
1168 They have a header of 16 bytes and the rest are
1169 the compressed coordinates of the files. Due to the
1170 compression 00 is not present in the coordinates.
1171 The first 4 bytes of the header are the magic number
1172 1995 (0x000007CB). If we find this number we are guaranteed
1173 to be in the header, due to the presence of so many zeros.
1174 The second 4 bytes are the number of atoms in the frame, and is
1175 assumed to be constant. The third 4 bytes are the frame number.
1176 The last 4 bytes are a floating point representation of the time.
1178 ********************************************************************/
1180 /* Must match definition in xtcio.c */
1182 #define XTC_MAGIC 1995
1185 static const int header_size
= 16;
1187 /* Check if we are at the header start.
1188 At the same time it will also read 1 int */
1189 static int xtc_at_header_start(FILE *fp
, XDR
*xdrs
,
1190 int natoms
, int * timestep
, float * time
){
1197 if((off
= gmx_ftell(fp
)) < 0){
1200 /* read magic natoms and timestep */
1202 if(!xdr_int(xdrs
, &(i_inp
[i
]))){
1203 gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
);
1208 if(i_inp
[0] != XTC_MAGIC
){
1209 if(gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
)){
1214 /* read time and box */
1215 for(i
= 0;i
<10;i
++){
1216 if(!xdr_float(xdrs
, &(f_inp
[i
]))){
1217 gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
);
1221 /* Make a rigourous check to see if we are in the beggining of a header
1222 Hopefully there are no ambiguous cases */
1223 /* This check makes use of the fact that the box matrix has 3 zeroes on the upper
1224 right triangle and that the first element must be nonzero unless the entire matrix is zero
1226 if(i_inp
[1] == natoms
&&
1227 ((f_inp
[1] != 0 && f_inp
[6] == 0) ||
1228 (f_inp
[1] == 0 && f_inp
[5] == 0 && f_inp
[9] == 0))){
1229 if(gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
)){
1233 *timestep
= i_inp
[2];
1236 if(gmx_fseek(fp
,off
+XDR_INT_SIZE
,SEEK_SET
)){
1243 xtc_get_next_frame_number(FILE *fp
, XDR
*xdrs
, int natoms
)
1250 if((off
= gmx_ftell(fp
)) < 0){
1254 /* read one int just to make sure we dont read this frame but the next */
1255 xdr_int(xdrs
,&step
);
1257 ret
= xtc_at_header_start(fp
,xdrs
,natoms
,&step
,&time
);
1259 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1263 }else if(ret
== -1){
1264 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1273 static float xtc_get_next_frame_time(FILE *fp
, XDR
*xdrs
, int natoms
,
1282 if ((off
= gmx_ftell(fp
)) < 0)
1286 /* read one int just to make sure we dont read this frame but the next */
1287 xdr_int(xdrs
, &step
);
1290 ret
= xtc_at_header_start(fp
, xdrs
, natoms
, &step
, &time
);
1294 if (gmx_fseek(fp
,off
,SEEK_SET
))
1303 if (gmx_fseek(fp
,off
,SEEK_SET
))
1315 xtc_get_current_frame_time(FILE *fp
, XDR
*xdrs
, int natoms
, bool * bOK
)
1323 if ((off
= gmx_ftell(fp
)) < 0)
1330 ret
= xtc_at_header_start(fp
, xdrs
, natoms
, &step
, &time
);
1334 if (gmx_fseek(fp
,off
,SEEK_SET
))
1343 if (gmx_fseek(fp
,off
,SEEK_SET
))
1352 if (gmx_fseek(fp
,-2*XDR_INT_SIZE
,SEEK_CUR
))
1361 /* Currently not used, just for completeness */
1363 xtc_get_current_frame_number(FILE *fp
,XDR
*xdrs
,int natoms
, bool * bOK
)
1371 if((off
= gmx_ftell(fp
)) < 0){
1377 ret
= xtc_at_header_start(fp
,xdrs
,natoms
,&step
,&time
);
1380 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1385 }else if(ret
== -1){
1386 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1393 if(gmx_fseek(fp
,-2*XDR_INT_SIZE
,SEEK_CUR
)){
1403 static gmx_off_t
xtc_get_next_frame_start(FILE *fp
, XDR
*xdrs
, int natoms
)
1410 /* read one int just to make sure we dont read this frame but the next */
1411 xdr_int(xdrs
,&step
);
1414 ret
= xtc_at_header_start(fp
,xdrs
,natoms
,&step
,&time
);
1416 if((res
= gmx_ftell(fp
)) >= 0){
1417 return res
- XDR_INT_SIZE
;
1421 }else if(ret
== -1){
1431 xdr_xtc_estimate_dt(FILE *fp
, XDR
*xdrs
, int natoms
, bool * bOK
)
1437 if((off
= gmx_ftell(fp
)) < 0){
1441 tinit
= xtc_get_current_frame_time(fp
,xdrs
,natoms
,bOK
);
1450 res
= xtc_get_next_frame_time(fp
,xdrs
,natoms
,bOK
);
1458 if(gmx_fseek(fp
,off
,SEEK_SET
)){
1467 xdr_xtc_seek_frame(int frame
, FILE *fp
, XDR
*xdrs
, int natoms
)
1473 /* round to 4 bytes */
1476 if(gmx_fseek(fp
,0,SEEK_END
)){
1480 if((high
= gmx_ftell(fp
)) < 0){
1484 /* round to 4 bytes */
1485 high
/= XDR_INT_SIZE
;
1486 high
*= XDR_INT_SIZE
;
1487 offset
= ((high
/2)/XDR_INT_SIZE
)*XDR_INT_SIZE
;
1489 if(gmx_fseek(fp
,offset
,SEEK_SET
)){
1495 fr
= xtc_get_next_frame_number(fp
,xdrs
,natoms
);
1500 if(fr
!= frame
&& abs(low
-high
) > header_size
)
1510 /* round to 4 bytes */
1511 offset
= (((high
+low
)/2)/4)*4;
1513 if(gmx_fseek(fp
,offset
,SEEK_SET
)){
1522 if(offset
<= header_size
)
1527 if(gmx_fseek(fp
,offset
,SEEK_SET
)){
1531 if((pos
= xtc_get_next_frame_start(fp
,xdrs
,natoms
))< 0){
1532 /* we probably hit an end of file */
1536 if(gmx_fseek(fp
,pos
,SEEK_SET
)){
1545 int xdr_xtc_seek_time(real time
, FILE *fp
, XDR
*xdrs
, int natoms
)
1551 gmx_off_t high
, offset
, pos
;
1555 if (gmx_fseek(fp
,0,SEEK_END
))
1560 if ((high
= gmx_ftell(fp
)) < 0)
1565 high
/= XDR_INT_SIZE
;
1566 high
*= XDR_INT_SIZE
;
1567 offset
= ((high
/ 2) / XDR_INT_SIZE
) * XDR_INT_SIZE
;
1569 if (gmx_fseek(fp
,offset
,SEEK_SET
))
1576 * No need to call xdr_xtc_estimate_dt here - since xdr_xtc_estimate_dt is called first thing in the loop
1577 dt = xdr_xtc_estimate_dt(fp, xdrs, natoms, &bOK);
1587 dt
= xdr_xtc_estimate_dt(fp
, xdrs
, natoms
, &bOK
);
1598 /* Found a place in the trajectory that has positive time step while
1599 other has negative time step */
1608 /* Found a place in the trajectory that has positive time step while
1609 other has negative time step */
1615 t
= xtc_get_next_frame_time(fp
, xdrs
, natoms
, &bOK
);
1621 /* If we are before the target time and the time step is positive or 0, or we have
1622 after the target time and the time step is negative, or the difference between
1623 the current time and the target time is bigger than dt and above all the distance between high
1624 and low is bigger than 1 frame, then do another step of binary search. Otherwise stop and check
1625 if we reached the solution */
1626 if ((((t
< time
&& dt_sign
>= 0) || (t
> time
&& dt_sign
== -1)) || ((t
1627 - time
) >= dt
&& dt_sign
>= 0)
1628 || ((time
- t
) >= -dt
&& dt_sign
< 0)) && (abs(low
- high
)
1631 if (dt
>= 0 && dt_sign
!= -1)
1642 else if (dt
<= 0 && dt_sign
== -1)
1655 /* We should never reach here */
1658 /* round to 4 bytes and subtract header*/
1659 offset
= (((high
+ low
) / 2) / XDR_INT_SIZE
) * XDR_INT_SIZE
;
1660 if (gmx_fseek(fp
,offset
,SEEK_SET
))
1667 if (abs(low
- high
) <= header_size
)
1671 /* re-estimate dt */
1672 if (xdr_xtc_estimate_dt(fp
, xdrs
, natoms
, &bOK
) != dt
)
1676 dt
= xdr_xtc_estimate_dt(fp
, xdrs
, natoms
, &bOK
);
1679 if (t
>= time
&& t
- time
< dt
)
1686 if (offset
<= header_size
)
1691 gmx_fseek(fp
,offset
,SEEK_SET
);
1693 if ((pos
= xtc_get_next_frame_start(fp
, xdrs
, natoms
)) < 0)
1698 if (gmx_fseek(fp
,pos
,SEEK_SET
))
1706 xdr_xtc_get_last_frame_time(FILE *fp
, XDR
*xdrs
, int natoms
, bool * bOK
)
1712 off
= gmx_ftell(fp
);
1718 if( (res
= gmx_fseek(fp
,-3*XDR_INT_SIZE
,SEEK_END
)) != 0){
1723 time
= xtc_get_current_frame_time(fp
, xdrs
, natoms
, bOK
);
1728 if( (res
= gmx_fseek(fp
,off
,SEEK_SET
)) != 0){
1737 xdr_xtc_get_last_frame_number(FILE *fp
, XDR
*xdrs
, int natoms
, bool * bOK
)
1744 if((off
= gmx_ftell(fp
)) < 0){
1750 if(gmx_fseek(fp
,-3*XDR_INT_SIZE
,SEEK_END
)){
1755 frame
= xtc_get_current_frame_number(fp
, xdrs
, natoms
, bOK
);
1761 if(gmx_fseek(fp
,off
,SEEK_SET
)){