1 /*____________________________________________________________________________
3 | libxdrf - portable fortran interface to xdr. some xdr routines
4 | are C routines for compressed coordinates
8 | This collection of routines is intended to write and read
9 | data in a portable way to a file, so data written on one type
10 | of machine can be read back on a different type.
12 | all fortran routines use an integer 'xdrid', which is an id to the
13 | current xdr file, and is set by xdrfopen.
14 | most routines have in integer 'ret' which is the return value.
15 | The value of 'ret' is zero on failure, and most of the time one
18 | There are three routines useful for C users:
19 | xdropen(), xdrclose(), xdr3dfcoord().
20 | The first two replace xdrstdio_create and xdr_destroy, and *must* be
21 | used when you plan to use xdr3dfcoord(). (they are also a bit
22 | easier to interface). For writing data other than compressed coordinates
23 | you should use the standard C xdr routines (see xdr man page)
25 | xdrfopen(xdrid, filename, mode, ret)
26 | character *(*) filename
29 | this will open the file with the given filename (string)
30 | and the given mode, it returns an id in xdrid, which is
31 | to be used in all other calls to xdrf routines.
32 | mode is 'w' to create, or update an file, for all other
33 | values of mode the file is opened for reading
35 | you need to call xdrfclose to flush the output and close
37 | Note that you should not use xdrstdio_create, which comes with the
38 | standard xdr library
40 | xdrfclose(xdrid, ret)
41 | flush the data to the file, and closes the file;
42 | You should not use xdr_destroy (which comes standard with
45 | xdrfbool(xdrid, bp, ret)
48 | This filter produces values of either 1 or 0
50 | xdrfchar(xdrid, cp, ret)
53 | filter that translate between characters and their xdr representation
54 | Note that the characters in not compressed and occupies 4 bytes.
56 | xdrfdouble(xdrid, dp, ret)
59 | read/write a double.
61 | xdrffloat(xdrid, fp, ret)
66 | xdrfint(xdrid, ip, ret)
71 | xdrflong(xdrid, lp, ret)
74 | this routine has a possible portablility problem due to 64 bits longs.
76 | xdrfshort(xdrid, sp, ret)
79 | xdrfstring(xdrid, sp, maxsize, ret)
83 | read/write a string, with maximum length given by maxsize
85 | xdrfwrapstring(xdris, sp, ret)
88 | read/write a string (it is the same as xdrfstring accept that it finds
89 | the stringlength itself.
91 | xdrfvector(xdrid, cp, size, xdrfproc, ret)
96 | read/write an array pointed to by cp, with number of elements
97 | defined by 'size'. the routine 'xdrfproc' is the name
98 | of one of the above routines to read/write data (like xdrfdouble)
99 | In contrast with the c-version you don't need to specify the
100 | byte size of an element.
101 | xdrfstring is not allowed here (it is in the c version)
103 | xdrf3dfcoord(xdrid, fp, size, precision, ret)
108 | this is *NOT* a standard xdr routine. I named it this way, because
109 | it invites people to use the other xdr routines.
110 | It is introduced to store specifically 3d coordinates of molecules
111 | (as found in molecular dynamics) and it writes it in a compressed way.
112 | It starts by multiplying all numbers by precision and
113 | rounding the result to integer. effectively converting
114 | all floating point numbers to fixed point.
115 | it uses an algorithm for compression that is optimized for
116 | molecular data, but could be used for other 3d coordinates
117 | as well. There is subtantial overhead involved, so call this
118 | routine only if you have a large number of coordinates to read/write
120 | ________________________________________________________________________
122 | Below are the routines to be used by C programmers. Use the 'normal'
123 | xdr routines to write integers, floats, etc (see man xdr)
125 | int xdropen(XDR *xdrs, const char *filename, const char *type)
126 | This will open the file with the given filename and the
127 | given mode. You should pass it an allocated XDR struct
128 | in xdrs, to be used in all other calls to xdr routines.
129 | Mode is 'w' to create, or update an file, and for all
130 | other values of mode the file is opened for reading.
131 | You need to call xdrclose to flush the output and close
134 | Note that you should not use xdrstdio_create, which
135 | comes with the standard xdr library.
137 | int xdrclose(XDR *xdrs)
138 | Flush the data to the file, and close the file;
139 | You should not use xdr_destroy (which comes standard
140 | with the xdr libraries).
142 | int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision)
143 | This is \fInot\fR a standard xdr routine. I named it this
144 | way, because it invites people to use the other xdr
147 | (c) 1995 Frans van Hoesel, hoesel@chem.rug.nl
160 int ftocstr(char *, int, char *, int);
161 int ctofstr(char *, int, char *);
164 static FILE *xdrfiles[MAXID];
165 static XDR *xdridptr[MAXID];
166 static char xdrmodes[MAXID];
167 static unsigned int cnt;
169 typedef void (* FUNCTION(xdrfproc)) (int *, void *, int *);
172 FUNCTION(xdrfbool) ARGS(`xdrid, pb, ret')
176 *ret = xdr_bool(xdridptr[*xdrid], (bool_t *) pb);
181 FUNCTION(xdrfchar) ARGS(`xdrid, cp, ret')
185 *ret = xdr_char(xdridptr[*xdrid], cp);
190 FUNCTION(xdrfdouble) ARGS(`xdrid, dp, ret')
194 *ret = xdr_double(xdridptr[*xdrid], dp);
195 cnt += sizeof(double);
199 FUNCTION(xdrffloat) ARGS(`xdrid, fp, ret')
203 *ret = xdr_float(xdridptr[*xdrid], fp);
204 cnt += sizeof(float);
208 FUNCTION(xdrfint) ARGS(`xdrid, ip, ret')
212 *ret = xdr_int(xdridptr[*xdrid], ip);
217 FUNCTION(xdrflong) ARGS(`xdrid, lp, ret')
221 *ret = xdr_long(xdridptr[*xdrid], lp);
226 FUNCTION(xdrfshort) ARGS(`xdrid, sp, ret')
230 *ret = xdr_short(xdridptr[*xdrid], sp);
235 FUNCTION(xdrfuchar) ARGS(`xdrid, ucp, ret')
239 *ret = xdr_u_char(xdridptr[*xdrid], ucp);
244 FUNCTION(xdrfulong) ARGS(`xdrid, ulp, ret')
248 *ret = xdr_u_long(xdridptr[*xdrid], ulp);
249 cnt += sizeof(unsigned long);
253 FUNCTION(xdrfushort) ARGS(`xdrid, usp, ret')
257 *ret = xdr_u_short(xdridptr[*xdrid], usp);
258 cnt += sizeof(unsigned short);
262 FUNCTION(xdrf3dfcoord) ARGS(`xdrid, fp, size, precision, ret')
268 *ret = xdr3dfcoord(xdridptr[*xdrid], fp, size, precision);
272 FUNCTION(xdrfstring) ARGS(`xdrid, STRING_ARG(sp), maxsize, ret')
279 tsp = (char*) malloc(((STRING_LEN(sp)) + 1) * sizeof(char));
284 if (ftocstr(tsp, *maxsize+1, STRING_PTR(sp), STRING_LEN(sp))) {
289 *ret = xdr_string(xdridptr[*xdrid], (char **) &tsp, (u_int) *maxsize);
290 ctofstr( STRING_PTR(sp), STRING_LEN(sp), tsp);
296 FUNCTION(xdrfwrapstring) ARGS(`xdrid, STRING_ARG(sp), ret')
302 maxsize = (STRING_LEN(sp)) + 1;
303 tsp = (char*) malloc(maxsize * sizeof(char));
308 if (ftocstr(tsp, maxsize, STRING_PTR(sp), STRING_LEN(sp))) {
313 *ret = xdr_string(xdridptr[*xdrid], (char **) &tsp, (u_int)maxsize);
314 ctofstr( STRING_PTR(sp), STRING_LEN(sp), tsp);
320 FUNCTION(xdrfopaque) ARGS(`xdrid, cp, ccnt, ret')
325 *ret = xdr_opaque(xdridptr[*xdrid], (caddr_t)*cp, (u_int)*ccnt);
330 FUNCTION(xdrfsetpos) ARGS(`xdrid, pos, ret')
334 *ret = xdr_setpos(xdridptr[*xdrid], (u_int) *pos);
338 FUNCTION(xdrf) ARGS(`xdrid, pos')
341 *pos = xdr_getpos(xdridptr[*xdrid]);
345 FUNCTION(xdrfvector) ARGS(`xdrid, cp, size, elproc, ret')
349 FUNCTION(xdrfproc) elproc;
353 for (lcnt = 0; lcnt < *size; lcnt++) {
354 elproc(xdrid, (cp+cnt) , ret);
360 FUNCTION(xdrfclose) ARGS(`xdrid, ret')
364 *ret = xdrclose(xdridptr[*xdrid]);
369 FUNCTION(xdrfopen) ARGS(`xdrid, STRING_ARG(fp), STRING_ARG(mode), ret')
372 STRING_ARG_DECL(mode);
378 if (ftocstr(fname, sizeof(fname), STRING_PTR(fp), STRING_LEN(fp))) {
381 if (ftocstr(fmode, sizeof(fmode), STRING_PTR(mode),
386 *xdrid = xdropen(NULL, fname, fmode);
393 /*___________________________________________________________________________
395 | what follows are the C routines for opening, closing xdr streams
396 | and the routine to read/write compressed coordinates together
397 | with some routines to assist in this task (those are marked
398 | static and cannot be called from user programs)
400 #define MAXABS INT_MAX-2
403 #define MIN(x,y) ((x) < (y) ? (x):(y))
406 #define MAX(x,y) ((x) > (y) ? (x):(y))
409 #define SQR(x) ((x)*(x))
411 static int magicints[] = {
412 0, 0, 0, 0, 0, 0, 0, 0, 0,
413 8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
414 80, 101, 128, 161, 203, 256, 322, 406, 512, 645,
415 812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501,
416 8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536,
417 82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,
418 832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042,
419 8388607, 10568983, 13316085, 16777216 };
422 /* note that magicints[FIRSTIDX-1] == 0 */
423 #define LASTIDX (sizeof(magicints) / sizeof(*magicints))
426 /*__________________________________________________________________________
428 | xdropen - open xdr file
430 | This versions differs from xdrstdio_create, because I need to know
431 | the state of the file (read or write) so I can use xdr3dfcoord
432 | in eigther read or write mode, and the file descriptor
433 | so I can close the file (something xdr_destroy doesn't do).
437 int xdropen(XDR *xdrs, const char *filename, const char *type) {
438 static int init_done = 0;
443 if (init_done == 0) {
444 for (xdrid = 1; xdrid < MAXID; xdrid++) {
445 xdridptr[xdrid] = NULL;
450 while (xdrid < MAXID && xdridptr[xdrid] != NULL) {
453 if (xdrid == MAXID) {
456 if (*type == 'w' || *type == 'W') {
460 } else if (*type == 'a' || *type == 'A') {
469 xdrfiles[xdrid] = fopen(filename, type1);
470 if (xdrfiles[xdrid] == NULL) {
474 xdrmodes[xdrid] = *type;
475 /* next test isn't usefull in the case of C language
476 * but is used for the Fortran interface
477 * (C users are expected to pass the address of an already allocated
481 xdridptr[xdrid] = (XDR *) malloc(sizeof(XDR));
482 xdrstdio_create(xdridptr[xdrid], xdrfiles[xdrid], lmode);
484 xdridptr[xdrid] = xdrs;
485 xdrstdio_create(xdrs, xdrfiles[xdrid], lmode);
490 /*_________________________________________________________________________
492 | xdrclose - close a xdr file
494 | This will flush the xdr buffers, and destroy the xdr stream.
495 | It also closes the associated file descriptor (this is *not*
496 | done by xdr_destroy).
500 int xdrclose(XDR *xdrs) {
504 fprintf(stderr, "xdrclose: passed a NULL pointer\n");
507 for (xdrid = 1; xdrid < MAXID; xdrid++) {
508 if (xdridptr[xdrid] == xdrs) {
511 fclose(xdrfiles[xdrid]);
512 xdridptr[xdrid] = NULL;
516 fprintf(stderr, "xdrclose: no such open xdr file\n");
521 /*____________________________________________________________________________
523 | sendbits - encode num into buf using the specified number of bits
525 | This routines appends the value of num to the bits already present in
526 | the array buf. You need to give it the number of bits to use and you
527 | better make sure that this number of bits is enough to hold the value
528 | Also num must be positive.
532 static void sendbits(int buf[], int num_of_bits, int num) {
534 unsigned int cnt, lastbyte;
536 unsigned char * cbuf;
538 cbuf = ((unsigned char *)buf) + 3 * sizeof(*buf);
539 cnt = (unsigned int) buf[0];
541 lastbyte =(unsigned int) buf[2];
542 while (num_of_bits >= 8) {
543 lastbyte = (lastbyte << 8) | ((num >> (num_of_bits -8)) /* & 0xff*/);
544 cbuf[cnt++] = lastbyte >> lastbits;
547 if (num_of_bits > 0) {
548 lastbyte = (lastbyte << num_of_bits) | num;
549 lastbits += num_of_bits;
552 cbuf[cnt++] = lastbyte >> lastbits;
559 cbuf[cnt] = lastbyte << (8 - lastbits);
563 /*_________________________________________________________________________
565 | sizeofint - calculate bitsize of an integer
567 | return the number of bits needed to store an integer with given max size
571 static int sizeofint(const int size) {
572 unsigned int num = 1;
575 while (size >= num && num_of_bits < 32) {
582 /*___________________________________________________________________________
584 | sizeofints - calculate 'bitsize' of compressed ints
586 | given the number of small unsigned integers and the maximum value
587 | return the number of bits needed to read or write them with the
588 | routines receiveints and sendints. You need this parameter when
589 | calling these routines. Note that for many calls I can use
590 | the variable 'smallidx' which is exactly the number of bits, and
591 | So I don't need to call 'sizeofints for those calls.
594 static int sizeofints( const int num_of_ints, unsigned int sizes[]) {
596 unsigned int num_of_bytes, num_of_bits, bytes[32], bytecnt, tmp;
600 for (i=0; i < num_of_ints; i++) {
602 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++) {
603 tmp = bytes[bytecnt] * sizes[i] + tmp;
604 bytes[bytecnt] = tmp & 0xff;
608 bytes[bytecnt++] = tmp & 0xff;
611 num_of_bytes = bytecnt;
615 while (bytes[num_of_bytes] >= num) {
619 return num_of_bits + num_of_bytes * 8;
623 /*____________________________________________________________________________
625 | sendints - send a small set of small integers in compressed format
627 | this routine is used internally by xdr3dfcoord, to send a set of
628 | small integers to the buffer.
629 | Multiplication with fixed (specified maximum ) sizes is used to get
630 | to one big, multibyte integer. Allthough the routine could be
631 | modified to handle sizes bigger than 16777216, or more than just
632 | a few integers, this is not done, because the gain in compression
633 | isn't worth the effort. Note that overflowing the multiplication
634 | or the byte buffer (32 bytes) is unchecked and causes bad results.
638 static void sendints(int buf[], const int num_of_ints, const int num_of_bits,
639 unsigned int sizes[], unsigned int nums[]) {
642 unsigned int bytes[32], num_of_bytes, bytecnt, tmp;
647 bytes[num_of_bytes++] = tmp & 0xff;
651 for (i = 1; i < num_of_ints; i++) {
652 if (nums[i] >= sizes[i]) {
653 fprintf(stderr,"major breakdown in sendints num %d doesn't "
654 "match size %d\n", nums[i], sizes[i]);
657 /* use one step multiply */
659 for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++) {
660 tmp = bytes[bytecnt] * sizes[i] + tmp;
661 bytes[bytecnt] = tmp & 0xff;
665 bytes[bytecnt++] = tmp & 0xff;
668 num_of_bytes = bytecnt;
670 if (num_of_bits >= num_of_bytes * 8) {
671 for (i = 0; i < num_of_bytes; i++) {
672 sendbits(buf, 8, bytes[i]);
674 sendbits(buf, num_of_bits - num_of_bytes * 8, 0);
676 for (i = 0; i < num_of_bytes-1; i++) {
677 sendbits(buf, 8, bytes[i]);
679 sendbits(buf, num_of_bits- (num_of_bytes -1) * 8, bytes[i]);
684 /*___________________________________________________________________________
686 | receivebits - decode number from buf using specified number of bits
688 | extract the number of bits from the array buf and construct an integer
689 | from it. Return that value.
693 static int receivebits(int buf[], int num_of_bits) {
696 unsigned int lastbits, lastbyte;
697 unsigned char * cbuf;
698 int mask = (1 << num_of_bits) -1;
700 cbuf = ((unsigned char *)buf) + 3 * sizeof(*buf);
702 lastbits = (unsigned int) buf[1];
703 lastbyte = (unsigned int) buf[2];
706 while (num_of_bits >= 8) {
707 lastbyte = ( lastbyte << 8 ) | cbuf[cnt++];
708 num |= (lastbyte >> lastbits) << (num_of_bits - 8);
711 if (num_of_bits > 0) {
712 if (lastbits < num_of_bits) {
714 lastbyte = (lastbyte << 8) | cbuf[cnt++];
716 lastbits -= num_of_bits;
717 num |= (lastbyte >> lastbits) & ((1 << num_of_bits) -1);
726 /*____________________________________________________________________________
728 | receiveints - decode 'small' integers from the buf array
730 | this routine is the inverse from sendints() and decodes the small integers
731 | written to buf by calculating the remainder and doing divisions with
732 | the given sizes[]. You need to specify the total number of bits to be
733 | used from buf in num_of_bits.
737 static void receiveints(int buf[], const int num_of_ints, int num_of_bits,
738 unsigned int sizes[], int nums[]) {
740 int i, j, num_of_bytes, p, num;
742 bytes[1] = bytes[2] = bytes[3] = 0;
744 while (num_of_bits > 8) {
745 bytes[num_of_bytes++] = receivebits(buf, 8);
748 if (num_of_bits > 0) {
749 bytes[num_of_bytes++] = receivebits(buf, num_of_bits);
751 for (i = num_of_ints-1; i > 0; i--) {
753 for (j = num_of_bytes-1; j >=0; j--) {
754 num = (num << 8) | bytes[j];
757 num = num - p * sizes[i];
761 nums[0] = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
764 /*____________________________________________________________________________
766 | xdr3dfcoord - read or write compressed 3d coordinates to xdr file.
768 | this routine reads or writes (depending on how you opened the file with
769 | xdropen() ) a large number of 3d coordinates (stored in *fp).
770 | The number of coordinates triplets to write is given by *size. On
771 | read this number may be zero, in which case it reads as many as were written
772 | or it may specify the number if triplets to read (which should match the
774 | Compression is achieved by first converting all floating numbers to integer
775 | using multiplication by *precision and rounding to the nearest integer.
776 | Then the minimum and maximum value are calculated to determine the range.
777 | The limited range of integers so found, is used to compress the coordinates.
778 | In addition the differences between succesive coordinates is calculated.
779 | If the difference happens to be 'small' then only the difference is saved,
780 | compressing the data even more. The notion of 'small' is changed dynamically
781 | and is enlarged or reduced whenever needed or possible.
782 | Extra compression is achieved in the case of GROMOS and coordinates of
783 | water molecules. GROMOS first writes out the Oxygen position, followed by
784 | the two hydrogens. In order to make the differences smaller (and thereby
785 | compression the data better) the order is changed into first one hydrogen
786 | then the oxygen, followed by the other hydrogen. This is rather special, but
787 | it shouldn't harm in the general case.
791 int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision) {
794 static int *ip = NULL;
798 int minint[3], maxint[3], mindiff, *lip, diff;
799 int lint1, lint2, lint3, oldlint1, oldlint2, oldlint3, smallidx;
801 unsigned sizeint[3], sizesmall[3], bitsizeint[3], size3, *luip;
803 int small, smaller, larger, i, is_small, is_smaller, run, prevrun;
805 int tmp, *thiscoord, prevcoord[3];
806 unsigned int tmpcoord[30];
808 int bufsize, xdrid, lsize;
809 unsigned int bitsize;
813 /* find out if xdrs is opened for reading or for writing */
815 while (xdridptr[xdrid] != xdrs) {
817 if (xdrid >= MAXID) {
818 fprintf(stderr, "xdr error. no open xdr stream\n");
822 if (xdrmodes[xdrid] == 'w') {
824 /* xdrs is open for writing */
826 if (xdr_int(xdrs, size) == 0)
829 /* when the number of coordinates is small, don't try to compress; just
830 * write them as floats using xdr_vector
833 return (xdr_vector(xdrs, (char *) fp, size3, sizeof(*fp),
834 (xdrproc_t)xdr_float));
837 xdr_float(xdrs, precision);
839 ip = (int *)malloc(size3 * sizeof(*ip));
841 fprintf(stderr,"malloc failed\n");
844 bufsize = size3 * 1.2;
845 buf = (int *)malloc(bufsize * sizeof(*buf));
847 fprintf(stderr,"malloc failed\n");
851 } else if (*size > oldsize) {
852 ip = (int *)realloc(ip, size3 * sizeof(*ip));
854 fprintf(stderr,"malloc failed\n");
857 bufsize = size3 * 1.2;
858 buf = (int *)realloc(buf, bufsize * sizeof(*buf));
860 fprintf(stderr,"malloc failed\n");
865 /* buf[0-2] are special and do not contain actual data */
866 buf[0] = buf[1] = buf[2] = 0;
867 minint[0] = minint[1] = minint[2] = INT_MAX;
868 maxint[0] = maxint[1] = maxint[2] = INT_MIN;
873 oldlint1 = oldlint2 = oldlint3 = 0;
874 while(lfp < fp + size3 ) {
875 /* find nearest integer */
877 lf = *lfp * *precision + 0.5;
879 lf = *lfp * *precision - 0.5;
880 if (fabs(lf) > MAXABS) {
881 /* scaling would cause overflow */
885 if (lint1 < minint[0]) minint[0] = lint1;
886 if (lint1 > maxint[0]) maxint[0] = lint1;
890 lf = *lfp * *precision + 0.5;
892 lf = *lfp * *precision - 0.5;
893 if (fabs(lf) > MAXABS) {
894 /* scaling would cause overflow */
898 if (lint2 < minint[1]) minint[1] = lint2;
899 if (lint2 > maxint[1]) maxint[1] = lint2;
903 lf = *lfp * *precision + 0.5;
905 lf = *lfp * *precision - 0.5;
906 if (fabs(lf) > MAXABS) {
907 /* scaling would cause overflow */
911 if (lint3 < minint[2]) minint[2] = lint3;
912 if (lint3 > maxint[2]) maxint[2] = lint3;
915 diff = abs(oldlint1-lint1)+abs(oldlint2-lint2)+abs(oldlint3-lint3);
916 if (diff < mindiff && lfp > fp + 3)
922 xdr_int(xdrs, &(minint[0]));
923 xdr_int(xdrs, &(minint[1]));
924 xdr_int(xdrs, &(minint[2]));
926 xdr_int(xdrs, &(maxint[0]));
927 xdr_int(xdrs, &(maxint[1]));
928 xdr_int(xdrs, &(maxint[2]));
930 if ((float)maxint[0] - (float)minint[0] >= MAXABS ||
931 (float)maxint[1] - (float)minint[1] >= MAXABS ||
932 (float)maxint[2] - (float)minint[2] >= MAXABS) {
933 /* turning value in unsigned by subtracting minint
934 * would cause overflow
938 sizeint[0] = maxint[0] - minint[0]+1;
939 sizeint[1] = maxint[1] - minint[1]+1;
940 sizeint[2] = maxint[2] - minint[2]+1;
942 /* check if one of the sizes is to big to be multiplied */
943 if ((sizeint[0] | sizeint[1] | sizeint[2] ) > 0xffffff) {
944 bitsizeint[0] = sizeofint(sizeint[0]);
945 bitsizeint[1] = sizeofint(sizeint[1]);
946 bitsizeint[2] = sizeofint(sizeint[2]);
947 bitsize = 0; /* flag the use of large sizes */
949 bitsize = sizeofints(3, sizeint);
952 luip = (unsigned int *) ip;
954 while (smallidx < LASTIDX && magicints[smallidx] < mindiff) {
957 xdr_int(xdrs, &smallidx);
958 maxidx = MIN(LASTIDX, smallidx + 8) ;
959 minidx = maxidx - 8; /* often this equal smallidx */
960 smaller = magicints[MAX(FIRSTIDX, smallidx-1)] / 2;
961 small = magicints[smallidx] / 2;
962 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
963 larger = magicints[maxidx] / 2;
967 thiscoord = (int *)(luip) + i * 3;
968 if (smallidx < maxidx && i >= 1 &&
969 abs(thiscoord[0] - prevcoord[0]) < larger &&
970 abs(thiscoord[1] - prevcoord[1]) < larger &&
971 abs(thiscoord[2] - prevcoord[2]) < larger) {
973 } else if (smallidx > minidx) {
979 if (abs(thiscoord[0] - thiscoord[3]) < small &&
980 abs(thiscoord[1] - thiscoord[4]) < small &&
981 abs(thiscoord[2] - thiscoord[5]) < small) {
982 /* interchange first with second atom for better
983 * compression of water molecules
985 tmp = thiscoord[0]; thiscoord[0] = thiscoord[3];
987 tmp = thiscoord[1]; thiscoord[1] = thiscoord[4];
989 tmp = thiscoord[2]; thiscoord[2] = thiscoord[5];
995 tmpcoord[0] = thiscoord[0] - minint[0];
996 tmpcoord[1] = thiscoord[1] - minint[1];
997 tmpcoord[2] = thiscoord[2] - minint[2];
999 sendbits(buf, bitsizeint[0], tmpcoord[0]);
1000 sendbits(buf, bitsizeint[1], tmpcoord[1]);
1001 sendbits(buf, bitsizeint[2], tmpcoord[2]);
1003 sendints(buf, 3, bitsize, sizeint, tmpcoord);
1005 prevcoord[0] = thiscoord[0];
1006 prevcoord[1] = thiscoord[1];
1007 prevcoord[2] = thiscoord[2];
1008 thiscoord = thiscoord + 3;
1012 if (is_small == 0 && is_smaller == -1)
1014 while (is_small && run < 8*3) {
1015 if (is_smaller == -1 && (
1016 SQR(thiscoord[0] - prevcoord[0]) +
1017 SQR(thiscoord[1] - prevcoord[1]) +
1018 SQR(thiscoord[2] - prevcoord[2]) >= smaller * smaller)) {
1022 tmpcoord[run++] = thiscoord[0] - prevcoord[0] + small;
1023 tmpcoord[run++] = thiscoord[1] - prevcoord[1] + small;
1024 tmpcoord[run++] = thiscoord[2] - prevcoord[2] + small;
1026 prevcoord[0] = thiscoord[0];
1027 prevcoord[1] = thiscoord[1];
1028 prevcoord[2] = thiscoord[2];
1031 thiscoord = thiscoord + 3;
1034 abs(thiscoord[0] - prevcoord[0]) < small &&
1035 abs(thiscoord[1] - prevcoord[1]) < small &&
1036 abs(thiscoord[2] - prevcoord[2]) < small) {
1040 if (run != prevrun || is_smaller != 0) {
1042 sendbits(buf, 1, 1); /* flag the change in run-length */
1043 sendbits(buf, 5, run+is_smaller+1);
1045 sendbits(buf, 1, 0); /* flag the fact that runlength did not change */
1047 for (k=0; k < run; k+=3) {
1048 sendints(buf, 3, smallidx, sizesmall, &tmpcoord[k]);
1050 if (is_smaller != 0) {
1051 smallidx += is_smaller;
1052 if (is_smaller < 0) {
1054 smaller = magicints[smallidx-1] / 2;
1057 small = magicints[smallidx] / 2;
1059 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
1062 if (buf[1] != 0) buf[0]++;;
1063 xdr_int(xdrs, &(buf[0])); /* buf[0] holds the length in bytes */
1064 return errval * (xdr_opaque(xdrs, (caddr_t)&(buf[3]), (u_int)buf[0]));
1067 /* xdrs is open for reading */
1069 if (xdr_int(xdrs, &lsize) == 0)
1071 if (*size != 0 && lsize != *size) {
1072 fprintf(stderr, "wrong number of coordinates in xdr3dfcoor; "
1073 "%d arg vs %d in file", *size, lsize);
1078 return (xdr_vector(xdrs, (char *) fp, size3, sizeof(*fp),
1079 (xdrproc_t)xdr_float));
1081 xdr_float(xdrs, precision);
1083 ip = (int *)malloc(size3 * sizeof(*ip));
1085 fprintf(stderr,"malloc failed\n");
1088 bufsize = size3 * 1.2;
1089 buf = (int *)malloc(bufsize * sizeof(*buf));
1091 fprintf(stderr,"malloc failed\n");
1095 } else if (*size > oldsize) {
1096 ip = (int *)realloc(ip, size3 * sizeof(*ip));
1098 fprintf(stderr,"malloc failed\n");
1101 bufsize = size3 * 1.2;
1102 buf = (int *)realloc(buf, bufsize * sizeof(*buf));
1104 fprintf(stderr,"malloc failed\n");
1109 buf[0] = buf[1] = buf[2] = 0;
1111 xdr_int(xdrs, &(minint[0]));
1112 xdr_int(xdrs, &(minint[1]));
1113 xdr_int(xdrs, &(minint[2]));
1115 xdr_int(xdrs, &(maxint[0]));
1116 xdr_int(xdrs, &(maxint[1]));
1117 xdr_int(xdrs, &(maxint[2]));
1119 sizeint[0] = maxint[0] - minint[0]+1;
1120 sizeint[1] = maxint[1] - minint[1]+1;
1121 sizeint[2] = maxint[2] - minint[2]+1;
1123 /* check if one of the sizes is to big to be multiplied */
1124 if ((sizeint[0] | sizeint[1] | sizeint[2] ) > 0xffffff) {
1125 bitsizeint[0] = sizeofint(sizeint[0]);
1126 bitsizeint[1] = sizeofint(sizeint[1]);
1127 bitsizeint[2] = sizeofint(sizeint[2]);
1128 bitsize = 0; /* flag the use of large sizes */
1130 bitsize = sizeofints(3, sizeint);
1133 xdr_int(xdrs, &smallidx);
1134 maxidx = MIN(LASTIDX, smallidx + 8) ;
1135 minidx = maxidx - 8; /* often this equal smallidx */
1136 smaller = magicints[MAX(FIRSTIDX, smallidx-1)] / 2;
1137 small = magicints[smallidx] / 2;
1138 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx] ;
1139 larger = magicints[maxidx];
1141 /* buf[0] holds the length in bytes */
1143 if (xdr_int(xdrs, &(buf[0])) == 0)
1145 if (xdr_opaque(xdrs, (caddr_t)&(buf[3]), (u_int)buf[0]) == 0)
1147 buf[0] = buf[1] = buf[2] = 0;
1150 inv_precision = 1.0 / * precision;
1154 while ( i < lsize ) {
1155 thiscoord = (int *)(lip) + i * 3;
1158 thiscoord[0] = receivebits(buf, bitsizeint[0]);
1159 thiscoord[1] = receivebits(buf, bitsizeint[1]);
1160 thiscoord[2] = receivebits(buf, bitsizeint[2]);
1162 receiveints(buf, 3, bitsize, sizeint, thiscoord);
1166 thiscoord[0] += minint[0];
1167 thiscoord[1] += minint[1];
1168 thiscoord[2] += minint[2];
1170 prevcoord[0] = thiscoord[0];
1171 prevcoord[1] = thiscoord[1];
1172 prevcoord[2] = thiscoord[2];
1175 flag = receivebits(buf, 1);
1178 run = receivebits(buf, 5);
1179 is_smaller = run % 3;
1185 for (k = 0; k < run; k+=3) {
1186 receiveints(buf, 3, smallidx, sizesmall, thiscoord);
1188 thiscoord[0] += prevcoord[0] - small;
1189 thiscoord[1] += prevcoord[1] - small;
1190 thiscoord[2] += prevcoord[2] - small;
1192 /* interchange first with second atom for better
1193 * compression of water molecules
1195 tmp = thiscoord[0]; thiscoord[0] = prevcoord[0];
1197 tmp = thiscoord[1]; thiscoord[1] = prevcoord[1];
1199 tmp = thiscoord[2]; thiscoord[2] = prevcoord[2];
1201 *lfp++ = prevcoord[0] * inv_precision;
1202 *lfp++ = prevcoord[1] * inv_precision;
1203 *lfp++ = prevcoord[2] * inv_precision;
1205 prevcoord[0] = thiscoord[0];
1206 prevcoord[1] = thiscoord[1];
1207 prevcoord[2] = thiscoord[2];
1209 *lfp++ = thiscoord[0] * inv_precision;
1210 *lfp++ = thiscoord[1] * inv_precision;
1211 *lfp++ = thiscoord[2] * inv_precision;
1214 *lfp++ = thiscoord[0] * inv_precision;
1215 *lfp++ = thiscoord[1] * inv_precision;
1216 *lfp++ = thiscoord[2] * inv_precision;
1218 smallidx += is_smaller;
1219 if (is_smaller < 0) {
1221 if (smallidx > FIRSTIDX) {
1222 smaller = magicints[smallidx - 1] /2;
1226 } else if (is_smaller > 0) {
1228 small = magicints[smallidx] / 2;
1230 sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx] ;