Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Gromacs.h

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2006 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 /***************************************************************************
00009  * RCS INFORMATION:
00010  *      $RCSfile: Gromacs.h,v $
00011  *      $Author: johns $       $Locker:  $             $State: Exp $
00012  *      $Revision: 1.22 $       $Date: 2006/02/24 00:57:10 $
00013  ***************************************************************************/
00014 
00015 /*
00016  * GROMACS file format reader for VMD
00017  *
00018  * This code provides a high level I/O library for reading
00019  * and writing the following file formats:
00020  *      gro     GROMACS format or trajectory
00021  *      g96     GROMOS-96 format or trajectory
00022  *      trj     Trajectory - x, v and f (binary, full precision)
00023  *      trr     Trajectory - x, v and f (binary, full precision, portable)
00024  *      xtc     Trajectory - x only (compressed, portable, any precision)
00025  *      top
00026  * Currently supported: gro trj trr g96 [xtc]
00027  *
00028  * TODO list
00029  *   o  velocities are ignored because VMD doesn't use them, but some other 
00030  *      program might ...
00031  *   o  gro_rec() assumes positions in .gro files are nanometers and
00032  *      converts to angstroms, whereas they really could be any unit
00033  */
00034 
00035 #ifndef GROMACS_H
00036 #define GROMACS_H
00037 
00038 #include <math.h>
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 #include <ctype.h>
00043 
00044 #if defined(_AIX)
00045 #include <strings.h>
00046 #endif
00047 
00048 #include "endianswap.h"
00049 
00050 #if defined(WIN32) || defined(WIN64)
00051 #define strcasecmp stricmp
00052 #endif
00053 
00054 #ifndef M_PI_2
00055 #define M_PI_2 1.57079632679489661922
00056 #endif
00057 
00058 // Error codes for mdio_errno
00059 #define MDIO_SUCCESS            0
00060 #define MDIO_BADFORMAT          1
00061 #define MDIO_EOF                2
00062 #define MDIO_BADPARAMS          3
00063 #define MDIO_IOERROR            4
00064 #define MDIO_BADPRECISION       5
00065 #define MDIO_BADMALLOC          6
00066 #define MDIO_CANTOPEN           7
00067 #define MDIO_BADEXTENSION       8
00068 #define MDIO_UNKNOWNFMT         9
00069 #define MDIO_CANTCLOSE          10
00070 #define MDIO_WRONGFORMAT        11
00071 #define MDIO_SIZEERROR          12
00072 #define MDIO_UNKNOWNERROR       1000
00073 
00074 #define MDIO_READ       0
00075 #define MDIO_WRITE      1
00076 
00077 #define MDIO_MAX_ERRVAL         11
00078 
00079 // Format extensions
00080 const char *mdio_fmtexts[] = {
00081     "",
00082     ".gro",
00083     ".trr",
00084     ".g96",
00085     ".trj",
00086     ".xtc",
00087     NULL
00088 };
00089 
00090 
00091 static int mdio_errcode;        // Last error code
00092 
00093 #define TRX_MAGIC       1993    // Magic number for .trX files
00094 #define XTC_MAGIC       1995    // Magic number for .xtc files
00095 #define MAX_GRO_LINE    500     // Maximum line length of .gro files
00096 #define MAX_G96_LINE    500     // Maximum line length of .g96 files
00097 #define MAX_TRX_TITLE   80      // Maximum length of a title in .trX
00098 #define MAX_MDIO_TITLE  80      // Maximum supported title length
00099 #define ANGS_PER_NM     10      // Unit conversion factor
00100 
00101 
00102 // All the supported file types and their respective extensions
00103 #define MDFMT_GRO               1
00104 #define MDFMT_TRR               2
00105 #define MDFMT_G96               3
00106 #define MDFMT_TRJ               4
00107 #define MDFMT_XTC               5
00108 
00109 
00110 // A structure to hold .trX file format header information. This
00111 // is an optional member of the md_file structure that is used
00112 // when .trX files are being dealt with.
00113 typedef struct {
00114         int version;            // File version number
00115         char title[MAX_TRX_TITLE + 1];  // File title
00116         int ir_size;
00117         int e_size;
00118         int box_size;
00119         int vir_size;
00120         int pres_size;
00121         int top_size;
00122         int sym_size;
00123         int x_size;             // Positions of atoms
00124         int v_size;             // Velocities of atoms
00125         int f_size;
00126         int natoms;             // Number of atoms in the system
00127         int step;
00128         int nre;
00129         float t;
00130         float lambda;
00131 } trx_hdr;
00132 
00133 
00134 // A generic i/o structure that contains information about the
00135 // file itself and the input/output state
00136 typedef struct {
00137         FILE *  f;      // Pointer to the file
00138         int     fmt;    // The file format
00139         int     prec;   // Real number precision
00140         int     rev;    // Reverse endiannism?
00141         trx_hdr * trx;  // Trx files require a great deal more
00142                         // header data to be stored.
00143 } md_file;
00144 
00145 
00146 // A format-independent structure to hold header data from files
00147 typedef struct {
00148         char title[MAX_MDIO_TITLE + 1];
00149         int natoms;
00150         float timeval;
00151 } md_header;
00152 
00153 
00154 // A format-independent structure to hold unit cell data
00155 typedef struct {
00156   float A, B, C, alpha, beta, gamma;
00157 } md_box;
00158 
00159 
00160 // Timestep information
00161 typedef struct {
00162         float *pos;     // Position array (3 * natoms)
00163         //float *vel;   // Velocity array ** (VMD doesn't use this) **
00164         //float *f;     // Force array ** (VMD doesn't use this) **
00165         //float *box;   // Computational box ** (VMD doesn't use this) **
00166         int natoms;     // Number of atoms
00167         int step;       // Simulation step
00168         float time;     // Time of simulation
00169   md_box *box;
00170 } md_ts;
00171 
00172 
00173 // Atom information
00174 typedef struct {
00175         char resid[7];          // Residue index number
00176         char resname[7];        // Residue name
00177         int atomnum;            // Atom index number
00178         char atomname[7];       // Atom name
00179         float pos[3];           // Position array (3 * natoms)
00180         //float vel[3]; // Velocity array ** (VMD doesn't use this) **
00181 } md_atom;
00182 
00183 
00184 // Open a molecular dynamics file. The second parameter specifies
00185 // the format of the file. If it is zero, the format is determined
00186 // from the file extension. the third argument (if given) decides
00187 // whether to read (==0) or to write (!= 0).
00188 // using a default argument set to read for backward compatibility.
00189 static md_file *mdio_open(const char *, const int, const int=MDIO_READ);
00190 
00191 // Closes a molecular dynamics file.
00192 static int mdio_close(md_file *);
00193 
00194 
00195 // Format-independent file I/O routines
00196 static int mdio_header(md_file *, md_header *);
00197 static int mdio_timestep(md_file *, md_ts *);
00198 
00199 
00200 // .gro file functions
00201 static int gro_header(md_file *, char *, int, float *, int *, int = 1);
00202 static int gro_rec(md_file *, md_atom *);
00203 static int gro_timestep(md_file *, md_ts *);
00204 
00205 
00206 // .trX file functions
00207 static int trx_header(md_file *, int = 0);
00208 static int trx_int(md_file *, int *);
00209 static int trx_real(md_file *, float *);
00210 
00211 static int trx_rvector(md_file *, float *);
00212 static int trx_string(md_file *, char *, int);
00213 static int trx_timestep(md_file *, md_ts *);
00214 
00215 // .g96 file functions
00216 static int g96_header(md_file *, char *, int, float *);
00217 static int g96_timestep(md_file *, md_ts *);
00218 static int g96_rec(md_file *, md_atom *);
00219 static int g96_countatoms(md_file *);
00220 
00221 
00222 // .xtc file functions
00223 static int xtc_int(md_file *, int *);
00224 static int xtc_float(md_file *, float *);
00225 /* 
00226 static int xtc_receivebits(int *, int);
00227 static void xtc_receiveints(int *, int, int, const unsigned *, int *);
00228 */
00229 static int xtc_timestep(md_file *, md_ts *);
00230 static int xtc_3dfcoord(md_file *, float *, int *, float *);
00231 
00232 
00233 // Error reporting functions
00234 static int mdio_errno(void);
00235 static const char *mdio_errmsg(int);
00236 static int mdio_seterror(int);
00237 
00238 
00239 // Miscellaneous functions
00240 static int strip_white(char *);
00241 static int mdio_readline(md_file *, char *, int, int = 1);
00242 static int mdio_tsfree(md_ts *, int = 0);
00243 static int mdio_readbox(md_box *, float *, float *, float *);
00244 
00245 
00246 
00247 static int xtc_receivebits(int *, int);
00248 
00249 // Error descriptions for mdio_errno
00250 static const char *mdio_errdescs[] = {
00251         "no error",
00252         "file does not match format",
00253         "unexpected end-of-file reached",
00254         "function called with bad parameters",
00255         "file i/o error",
00256         "unsupported precision",
00257         "out of memory",
00258         "cannot open file",
00259         "bad file extension",
00260         "unknown file format",
00261         "cannot close file",
00262         "wrong file format for this function",
00263         "binary i/o error: sizeof(int) != 4",
00264         NULL
00265 };
00266 
00269 static inline int host_is_little_endian(void) 
00270 {
00271   const union { char c[4]; unsigned int i; } 
00272   fixed = { { 0x10 , 0x20 , 0x40 , 0x80 } };
00273   const unsigned int i = 0x80402010U;
00274         
00275   if (fixed.i == i) {
00276     return 1;
00277   }
00278   return 0;
00279 }
00280 
00281 
00282 
00283 // Open a molecular dynamics file. The second parameter specifies
00284 // the format of the file. If it is zero, the format is determined
00285 // from the file extension.
00286 md_file *mdio_open(const char *fn, const int fmt, const int rw) {
00287         md_file *mf;
00288 
00289         if (!fn) {
00290                 mdio_seterror(MDIO_BADPARAMS);
00291                 return NULL;
00292         }
00293 
00294         // Allocate memory
00295         mf = (md_file *) malloc(sizeof(md_file));
00296         if (!mf) {
00297                 mdio_seterror(MDIO_BADMALLOC);
00298                 return NULL;
00299         }
00300 
00301         // Zero out the structure
00302         memset(mf, 0, sizeof(md_file));
00303 
00304         // Determine the file type from the extension
00305         if (!fmt) {
00306                 char *p;
00307                 int n;
00308 
00309                 // Seek to the extension part of the filename
00310                 for (p = (char *) &fn[strlen(fn) - 1]; *p != '.' && p > fn; p--);
00311                 if (p == fn) {
00312                         free(mf);
00313                         mdio_seterror(MDIO_BADEXTENSION);
00314                         return NULL;
00315                 }
00316 
00317                 // Check the extension against known extensions
00318                 for (n = 1; mdio_fmtexts[n]; n++)
00319                         if (!strcasecmp(p, mdio_fmtexts[n])) break;
00320 
00321                 // If !mdio_fmtexts[n], we failed (unknown ext)
00322                 if (!mdio_fmtexts[n]) {
00323                         free(mf);
00324                         mdio_seterror(MDIO_UNKNOWNFMT);
00325                         return NULL;
00326                 }
00327 
00328                 // All set
00329                 mf->fmt = n;
00330         }
00331         else {
00332                 mf->fmt = fmt;
00333         }
00334 
00335         // Differentiate between binary and ascii files. Also,
00336         // .trX files need a header information structure allocated.
00337         switch (mf->fmt) {
00338     case MDFMT_GRO:
00339         case MDFMT_G96: /* fallthrough */
00340         if (rw) 
00341             mf->f = fopen(fn, "wt");
00342         else
00343             mf->f = fopen(fn, "rt");
00344 
00345                 break;
00346         case MDFMT_TRR:
00347         case MDFMT_TRJ: /* fallthrough */
00348                 // Allocate the trx header data struct
00349                 mf->trx = (trx_hdr *) malloc(sizeof(trx_hdr));
00350                 if (!mf->trx) {
00351                         free(mf);
00352                         mdio_seterror(MDIO_BADMALLOC);
00353                         return NULL;
00354                 }
00355                 memset(mf->trx, 0, sizeof(trx_hdr));
00356         case MDFMT_XTC:  /* fallthrough */
00357                 // Finally, open the file
00358         if (rw)
00359             mf->f = fopen(fn, "wb");
00360         else
00361             mf->f = fopen(fn, "rb");
00362 
00363                 break;
00364         default:
00365                 free(mf);
00366                 mdio_seterror(MDIO_UNKNOWNFMT);
00367                 return NULL;
00368         }
00369 
00370         // Check for opening error
00371         if (!mf->f) {
00372                 if (mf->trx) free(mf->trx);
00373                 free(mf);
00374                 mdio_seterror(MDIO_CANTOPEN);
00375                 return NULL;
00376         }
00377 
00378         // File is opened, we're all set!
00379         mdio_seterror(MDIO_SUCCESS);
00380         return mf;
00381 }
00382 
00383 
00384 // Closes a molecular dynamics file.
00385 static int mdio_close(md_file *mf) {
00386         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
00387 
00388         if (fclose(mf->f) == EOF) return mdio_seterror(MDIO_CANTCLOSE);
00389 
00390         // Free the dynamically allocated memory
00391         if (mf->trx) free(mf->trx);
00392         free(mf);
00393         return mdio_seterror(MDIO_SUCCESS);
00394 }
00395 
00396 
00397 // Returns the last error code reported by any of the mdio functions
00398 static int mdio_errno(void) {
00399         return mdio_errcode;
00400 }
00401 
00402 
00403 // Returns a textual message regarding an mdio error code
00404 static const char *mdio_errmsg(int n) {
00405         if (n < 0 || n > MDIO_MAX_ERRVAL) return (char *) "unknown error";
00406         else return mdio_errdescs[n];
00407 }
00408 
00409 
00410 // Sets the error code and returns an appropriate return value
00411 // for the calling function to return to its parent
00412 static int mdio_seterror(int code) {
00413         mdio_errcode = code;
00414         return code ? -1 : 0;
00415 }
00416 
00417 
00418 // Reads a line from the text file, strips leading/trailing whitespace
00419 // and newline, checks for errors, and returns the number of characters
00420 // in the string on success or -1 on error.
00421 static int mdio_readline(md_file *mf, char *buf, int n, int strip) {
00422         if (!buf || n < 1 || !mf) return mdio_seterror(MDIO_BADPARAMS);
00423 
00424         // Read the line
00425         fgets(buf, n, mf->f);
00426 
00427         // End of file reached?
00428         if (feof(mf->f)) return mdio_seterror(MDIO_EOF);
00429 
00430         // File I/O error?
00431         if (ferror(mf->f)) return mdio_seterror(MDIO_IOERROR);
00432 
00433         // Strip whitespace
00434         if (strip) strip_white(buf);
00435 
00436         return strlen(buf);
00437 }
00438 
00439 
00440 // Strips leading and trailing whitespace from a string. Tabs,
00441 // spaces, newlines and carriage returns are stripped. Example:
00442 // "\n   hello\t \r" becomes "hello".
00443 static int strip_white(char *buf) {
00444         int i, j, k;
00445 
00446         // Protect against NULL pointer
00447         if (!buf) return -1;
00448         if (!strlen(buf)) return -1;
00449 
00450         // Kill trailing whitespace first
00451         for (i = strlen(buf) - 1;
00452              buf[i] == ' ' || buf[i] == '\t' ||
00453              buf[i] == '\n' || buf[i] == '\r';
00454              i--)
00455                 buf[i] = 0;
00456 
00457         // Skip past leading whitespace
00458         for (i = 0; buf[i] == ' ' || buf[i] == '\t' ||
00459              buf[i] == '\n' || buf[i] == '\r'; i++);
00460         if (i) {
00461                 k = 0;
00462                 for (j = i; buf[j]; j++)
00463                         buf[k++] = buf[j];
00464                 buf[k] = 0;
00465         }
00466 
00467         return strlen(buf);
00468 }
00469 
00470 
00471 // Frees the memory allocated in a ts structure. The holderror
00472 // parameter defaults to zero. Programs that are calling this
00473 // function because of an error reported by another function should
00474 // set holderror so that mdio_tsfree() does not overwrite the error
00475 // code with mdio_seterror().
00476 static int mdio_tsfree(md_ts *ts, int holderror) {
00477         if (!ts) {
00478                 if (holderror) return -1;
00479                 else return mdio_seterror(MDIO_BADPARAMS);
00480         }
00481 
00482         if (ts->pos && ts->natoms > 0) free(ts->pos);
00483 
00484   if (ts->box) free(ts->box);
00485 
00486         if (holderror) return -1;
00487         else return mdio_seterror(MDIO_SUCCESS);
00488 }
00489 
00490 
00491 // Converts box basis vectors to A, B, C, alpha, beta, and gamma.  
00492 // Stores values in md_box struct, which should be allocated before calling
00493 // this function.
00494 static int mdio_readbox(md_box *box, float *x, float *y, float *z) {
00495   float A, B, C;
00496 
00497   if (!box) {
00498     return mdio_seterror(MDIO_BADPARAMS);
00499   }
00500 
00501   // A, B, C are the lengths of the x, y, z vectors, respectively
00502   A = sqrt( x[0]*x[0] + x[1]*x[1] + x[2]*x[2] ) * ANGS_PER_NM;
00503   B = sqrt( y[0]*y[0] + y[1]*y[1] + y[2]*y[2] ) * ANGS_PER_NM;
00504   C = sqrt( z[0]*z[0] + z[1]*z[1] + z[2]*z[2] ) * ANGS_PER_NM;
00505   if ((A<=0) || (B<=0) || (C<=0)) {
00506     /* Use zero-length box size and set angles to 90. */
00507     box->A = box->B = box->C = 0;
00508     box->alpha = box->beta = box->gamma = 90;
00509   } else {
00510     box->A = A;
00511     box->B = B;
00512     box->C = C;
00513   
00514     // gamma, beta, alpha are the angles between the x & y, x & z, y & z
00515     // vectors, respectively
00516     box->gamma = acos( (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])/(A*B) ) * 90.0/M_PI_2;
00517     box->beta = acos( (x[0]*z[0]+x[1]*z[1]+x[2]*z[2])/(A*C) ) * 90.0/M_PI_2;
00518     box->alpha = acos( (y[0]*z[0]+y[1]*z[1]+y[2]*z[2])/(B*C) ) * 90.0/M_PI_2; 
00519   }
00520   return mdio_seterror(MDIO_SUCCESS);
00521 }
00522 
00523 
00524 // Reads the header of a file (format independent)
00525 static int mdio_header(md_file *mf, md_header *mdh) {
00526         int n;
00527         if (!mf || !mdh) return mdio_seterror(MDIO_BADPARAMS);
00528         if (!mf->f) return mdio_seterror(MDIO_BADPARAMS);
00529 
00530         switch (mf->fmt) {
00531         case MDFMT_GRO:
00532                 if (gro_header(mf, mdh->title, MAX_MDIO_TITLE,
00533                 &mdh->timeval, &mdh->natoms, 1) < 0)
00534                         return -1;
00535                 return 0;
00536 
00537         case MDFMT_TRR:
00538                 if (trx_header(mf, 1) < 0) return -1;
00539                 mdh->natoms = mf->trx->natoms;
00540                 mdh->timeval = (float) mf->trx->t;
00541                 strncpy(mdh->title, mf->trx->title, MAX_MDIO_TITLE);
00542                 return 0;
00543 
00544         case MDFMT_G96:
00545                 if (g96_header(mf, mdh->title, MAX_MDIO_TITLE,
00546                 &mdh->timeval) < 0) return -1;
00547                 mdh->natoms = -1;
00548                 return 0;
00549 
00550         case MDFMT_XTC:
00551                 memset(mdh, 0, sizeof(md_header));
00552                 // Check magic number
00553                 if (xtc_int(mf, &n) < 0) return -1;
00554                 if (n != XTC_MAGIC) return mdio_seterror(MDIO_BADFORMAT);
00555 
00556                 // Get number of atoms
00557                 if (xtc_int(mf, &n) < 0) return -1;
00558                 mdh->natoms = n;
00559                 rewind(mf->f);
00560                 return 0;
00561 
00562         default:
00563                 return mdio_seterror(MDIO_UNKNOWNFMT);
00564         }
00565 }
00566 
00567 
00568 // Reads in a timestep from a file (format independent)
00569 static int mdio_timestep(md_file *mf, md_ts *ts) {
00570         if (!mf || !ts) return mdio_seterror(MDIO_BADPARAMS);
00571         if (!mf->f) return mdio_seterror(MDIO_BADPARAMS);
00572 
00573         switch (mf->fmt) {
00574         case MDFMT_GRO:
00575                 return gro_timestep(mf, ts);
00576 
00577         case MDFMT_TRR:
00578                 return trx_timestep(mf, ts);
00579 
00580         case MDFMT_G96:
00581                 return g96_timestep(mf, ts);
00582 
00583         case MDFMT_XTC:
00584                 return xtc_timestep(mf, ts);
00585 
00586         default:
00587                 return mdio_seterror(MDIO_UNKNOWNFMT);
00588         }
00589 }
00590 
00591 
00592 
00593 static int g96_header(md_file *mf, char *title, int titlelen, float *timeval) {
00594         char buf[MAX_G96_LINE + 1];
00595         char *p;
00596 
00597         // Check parameters
00598         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
00599 
00600         // The header consists of blocks. The title block
00601         // is mandatory, and a TIMESTEP block is optional.
00602         // Example:
00603         //
00604         // TITLE
00605         // Generated by trjconv :  t=  90.00000
00606         // more title info
00607         // .
00608         // .
00609         // .
00610         // END
00611         // .
00612         // .
00613         // .
00614 
00615         if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00616         if (strcasecmp(buf, "TITLE")) return mdio_seterror(MDIO_BADFORMAT);
00617 
00618         // Read in the title itself
00619         if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00620 
00621         // The timevalue can be included in the title string
00622         // after a "t=" prefix.
00623         if ((p = (char *) strstr(buf, "t="))) {
00624                 char *q = p;
00625                 *(q--) = 0;
00626 
00627                 // Skip the `t=' and strip whitespace from
00628                 // the resulting strings
00629                 p += 2;
00630                 strip_white(p);
00631                 strip_white(buf);
00632 
00633                 // Grab the timevalue from the title string
00634                 if (timeval) *timeval = (float) atof(p);
00635         }
00636         else {
00637                 // No timevalue - just copy the string and strip
00638                 // any leading/trailing whitespace
00639                 if (timeval) *timeval = 0;
00640                 strip_white(buf);
00641         }
00642 
00643         // Copy the title string
00644         if (title && titlelen) strncpy(title, buf, titlelen);
00645 
00646         // Now ignore subsequent title lines and get the END string
00647         while (strcasecmp(buf, "END"))
00648                 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00649 
00650         // Done!
00651         return mdio_seterror(MDIO_SUCCESS);
00652 }
00653 
00654 
00655 // Used to determine the number of atoms in a g96 file, because
00656 // VMD needs to know this for some reason.
00657 static int g96_countatoms(md_file *mf) {
00658         char buf[MAX_G96_LINE + 1];
00659         int natoms;
00660         int n;
00661         long fpos;
00662         float lastf;
00663 
00664         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
00665 
00666         fpos = ftell(mf->f);
00667 
00668         natoms = 0;
00669         for (;;) {
00670                 if (mdio_readline(mf, buf, MAX_G96_LINE + 1, 0) < 0)
00671                         break;
00672                 n = sscanf(buf, "%*6c%*6c%*6c%*6c %*f %*f %f", &lastf);
00673                 if (n == 1) natoms++;
00674                 else {
00675                         strip_white(buf);
00676                         if (!strcasecmp(buf, "END")) break;
00677                 }
00678         }
00679 
00680         fseek(mf->f, fpos, SEEK_SET);
00681         return natoms;
00682 }
00683 
00684 
00685 // Reads an atom line from the G96 file
00686 static int g96_rec(md_file *mf, md_atom *ma) {
00687         char buf[MAX_G96_LINE + 1];
00688         char atomnum[7];
00689         int n;
00690 
00691         // Check parameters
00692         if (!mf || !ma) return mdio_seterror(MDIO_BADPARAMS);
00693 
00694         // Read in a line, assuming it is an atom line
00695         do {
00696                 if (mdio_readline(mf, buf, MAX_G96_LINE + 1, 0) < 0) return -1;
00697         } while (buf[0] == '#' || strlen(buf) == 0);
00698 
00699         n = sscanf(buf, "%6c%6c%6c%6c %f %f %f",
00700                 ma->resid, ma->resname, ma->atomname, atomnum,
00701                 &ma->pos[0], &ma->pos[1], &ma->pos[2]);
00702         if (n == 7) {
00703                 atomnum[6] = 0;
00704                 ma->resid[6] = 0;
00705                 ma->resname[6] = 0;
00706                 ma->atomname[6] = 0;
00707 
00708                 strip_white(atomnum);
00709                 strip_white(ma->resid);
00710                 strip_white(ma->resname);
00711                 strip_white(ma->atomname);
00712 
00713                 ma->atomnum = atoi(atomnum);
00714 
00715                 ma->pos[0] *= ANGS_PER_NM;
00716                 ma->pos[1] *= ANGS_PER_NM;
00717                 ma->pos[2] *= ANGS_PER_NM;
00718 
00719                 return 0;
00720         }
00721 
00722         return mdio_seterror(MDIO_BADFORMAT);
00723 }
00724 
00725 
00726 // Reads a timestep from a G96 file and stores the data in
00727 // the generic md_ts structure. Returns 0 on success or a
00728 // negative number on error and sets mdio_errcode.
00729 static int g96_timestep(md_file *mf, md_ts *ts) {
00730         char            buf[MAX_G96_LINE + 1];
00731         char            stripbuf[MAX_G96_LINE + 1];
00732         float           pos[3], x[3], y[3], z[3], *currAtom;
00733         long            fpos;
00734         int             n, i, boxItems;
00735 
00736         // Check parameters
00737         if (!mf || !ts) return mdio_seterror(MDIO_BADPARAMS);
00738 
00739   // Allocate data space for the timestep, using the number of atoms
00740   // determined by open_g96_read().
00741         ts->pos = (float *) malloc(sizeof(float) * 3 * ts->natoms);
00742         if (!ts->pos) {
00743                 return mdio_seterror(MDIO_BADMALLOC);
00744         }
00745   currAtom = ts->pos;
00746 
00747         // The timesteps follow the header in a fixed block
00748         // format:
00749         //
00750         // TIMESTEP
00751         //         <step number> <time value>
00752         // END
00753         // POSITIONRED
00754         //     <x float> <y float> <z float>
00755         //     .         .         .
00756         //     .         .         .
00757         //     .         .         .
00758         // END
00759         // VELOCITYRED
00760         //     <x float> <y float> <z float>
00761         //     .         .         .
00762         //     .         .         .
00763         //     .         .         .
00764         // END
00765         // BOX
00766         //     <x float> <y float> <z float>
00767         // END
00768         //
00769         // -----
00770         //
00771         // The TIMESTEP, VELOCITY and BOX blocks are optional.
00772         // Floats are written in 15.9 precision.
00773         //
00774         // Reference: GROMACS 2.0 user manual
00775         //            http://rugmd4.chem.rug.nl/~gmx/online2.0/g96.html
00776 
00777         // First, look for an (optional) title block and skip it
00778         if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00779 
00780   if (!strcasecmp(buf, "TITLE")) {
00781     // skip over the text until we reach 'END'
00782     while (strcasecmp(buf, "END")) {
00783       if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00784     }
00785 
00786     // Read in the next line
00787     if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00788   }
00789 
00790         // Next, look for a timestep block
00791         if (!strcasecmp(buf, "TIMESTEP")) {
00792                 // Read in the value line
00793                 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00794 
00795                 // Extract the time value and the timestep index
00796                 n = sscanf(buf, "%d %f", &ts->step, &ts->time);
00797                 if (n != 2) return mdio_seterror(MDIO_BADFORMAT);
00798 
00799                 // Read the "END" line
00800                 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00801                 if (strcasecmp(buf, "END"))
00802                         return mdio_seterror(MDIO_BADFORMAT);
00803 
00804                 // Read in the next line
00805                 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00806         }
00807         else {
00808                 // No timestep specified -- set to zero
00809                 ts->step = 0;
00810                 ts->time = 0;
00811         }
00812 
00813         // At this point a POSITION or POSITIONRED block
00814         // is REQUIRED by the format
00815         if (!strcasecmp(buf, "POSITIONRED")) {
00816 
00817     // So now we read in some atoms
00818     i = 0;
00819                 while (i < ts->natoms) {
00820                         // Read in an atom
00821                         if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0)
00822                                 return -1;
00823  
00824       // We shouldn't reach the end yet
00825       if (!strcasecmp(buf, "END"))
00826         return mdio_seterror(MDIO_BADFORMAT);
00827 
00828                         // Get the x,y,z coordinates
00829                         n = sscanf(buf, "%f %f %f", &pos[0], &pos[1], &pos[2]);
00830       
00831       // Ignore improperly formatted lines
00832                         if (n == 3) {
00833                                 pos[0] *= ANGS_PER_NM;
00834                                 pos[1] *= ANGS_PER_NM;
00835                                 pos[2] *= ANGS_PER_NM;
00836 
00837                                 // Copy the atom data into the array
00838                                 memcpy(currAtom, pos, sizeof(float) * 3);
00839         currAtom += 3;
00840         i++;
00841                         }
00842                 }
00843         }
00844         else if (!strcasecmp(buf, "POSITION") || !strcasecmp(buf, "REFPOSITION")) {
00845                 /*
00846                 char resnum[7];
00847                 char resname[7];
00848                 char atomname[7];
00849                 char atomnum[7];
00850                 */
00851 
00852                 // So now we read in some atoms
00853     i = 0;
00854                 while (i < ts->natoms) {
00855                         // Read in the first line
00856                         if (mdio_readline(mf, buf, MAX_G96_LINE + 1, 0) < 0)
00857                                 return -1;
00858  
00859       // We shouldn't reach the end yet
00860       strcpy(stripbuf, buf);
00861       strip_white(stripbuf); 
00862       if (!strcasecmp(stripbuf, "END"))
00863         return mdio_seterror(MDIO_BADFORMAT);
00864 
00865                         // Get the x,y,z coordinates and name data
00866                         n = sscanf(buf, "%*6c%*6c%*6c%*6c %f %f %f",
00867                                 &pos[0], &pos[1], &pos[2]);
00868 
00869       // Ignore improperly formatted lines
00870                         if (n == 3) {
00871                                 pos[0] *= ANGS_PER_NM;
00872                                 pos[1] *= ANGS_PER_NM;
00873                                 pos[2] *= ANGS_PER_NM;
00874 
00875                                 // Copy the atom data into the linked list item
00876                                 memcpy(currAtom, pos, sizeof(float) * 3);
00877                                 currAtom += 3;
00878         i++;
00879                         }
00880                 }
00881         }
00882         else {
00883                 return mdio_seterror(MDIO_BADFORMAT);
00884         }
00885 
00886   // Read the END keyword
00887   if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0)
00888     return -1;
00889   if (strcasecmp(buf, "END"))
00890     return mdio_seterror(MDIO_BADFORMAT);
00891 
00892         // ... another problem: there may or may not be a VELOCITY
00893         // block or a BOX block, so we need to read one line beyond
00894         // the POSITION block to determine this. If neither VEL. nor
00895         // BOX are present we've read a line too far and infringed
00896         // on the next timestep, so we need to keep track of the
00897         // position now for a possible fseek() later to backtrack.
00898         fpos = ftell(mf->f);
00899 
00900         // Now we must read in the velocities and the box, if present
00901         if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) {
00902     // It's okay if we end the file here; any other errors need to be
00903     // reported.
00904     if (mdio_errcode == MDIO_EOF) 
00905       return mdio_seterror(MDIO_SUCCESS);
00906     else 
00907       return -1;
00908   }
00909 
00910         // Is there a velocity block present ?
00911         if (!strcasecmp(buf, "VELOCITY") || !strcasecmp(buf, "VELOCITYRED")) {
00912                 // Ignore all the coordinates - VMD doesn't use them
00913                 for (;;) {
00914                         if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0)
00915                                 return -1;
00916                         if (!strcasecmp(buf, "END")) break;
00917                 }
00918 
00919                 // Again, record our position because we may need
00920                 // to fseek here later if we read too far.
00921                 fpos = ftell(mf->f);
00922 
00923                 // Go ahead and read the next line.
00924                 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00925         }
00926 
00927         // Is there a box present ?
00928         if (!strcasecmp(buf, "BOX")) {
00929                 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00930     boxItems = sscanf(buf, " %f %f %f %f %f %f %f %f %f", 
00931                &x[0], &y[1], &z[2], &x[1], &x[2], &y[0], &y[2], &z[0], &z[1]);
00932     if (boxItems == 3) {
00933       x[1] = x[2] = 0;
00934       y[0] = y[2] = 0;
00935       z[0] = z[1] = 0;
00936     }
00937     else if (boxItems != 9) 
00938       return mdio_seterror(MDIO_BADFORMAT);
00939 
00940     // Allocate the box and convert the vectors.
00941     ts->box = (md_box *) malloc(sizeof(md_box));
00942     if (mdio_readbox(ts->box, x, y, z) < 0) {
00943       free(ts->box);
00944       ts->box = NULL;
00945       return mdio_seterror(MDIO_BADFORMAT);
00946     }
00947 
00948                 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) {
00949       free(ts->box);
00950       ts->box = NULL;
00951       return -1;
00952     }
00953                 if (strcasecmp(buf, "END")) {
00954       free(ts->box);
00955       ts->box = NULL;
00956                         return mdio_seterror(MDIO_BADFORMAT);
00957     }
00958         }
00959         else {
00960                 // We have read too far, so fseek back to the
00961                 // last known safe position so we don't return
00962                 // with the file pointer set infringing on the
00963                 // next timestep data.
00964                 fseek(mf->f, fpos, SEEK_SET);
00965         }
00966 
00967         // We're done!
00968         return mdio_seterror(MDIO_SUCCESS);
00969 }
00970 
00971 
00972 // Attempts to read header data from a GROMACS structure file
00973 // The GROMACS header format is as follows (fixed, 2 lines ASCII):
00974 // <title> [ n= <timevalue> ]
00975 //     <num atoms>
00976 static int gro_header(md_file *mf, char *title, int titlelen, float *timeval,
00977                int *natoms, int rewind) {
00978         char buf[MAX_GRO_LINE + 1];
00979         long fpos;
00980         char *p;
00981 
00982         // Check parameters
00983         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
00984 
00985         // Get the current file position for rewinding later
00986         fpos = ftell(mf->f);
00987 
00988         // The header consists of 2 lines - get the first line
00989         if (mdio_readline(mf, buf, MAX_GRO_LINE + 1) < 0) return -1;
00990 
00991         // The timevalue can be included in the title string
00992         // after a "t=" prefix.
00993         if ((p = (char *) strstr(buf, "t="))) {
00994                 char *q = p;
00995                 *(q--) = 0;
00996 
00997                 // Skip the `t=' and strip whitespace from
00998                 // the resulting strings
00999                 p += 2;
01000                 strip_white(p);
01001                 strip_white(buf);
01002 
01003                 // Grab the timevalue from the title string
01004                 if (timeval) *timeval = (float) atof(p);
01005         }
01006         else {
01007                 // No timevalue - just copy the string
01008                 if (timeval) *timeval = 0;
01009         }
01010 
01011         // Copy the title string
01012         if (title && titlelen) strncpy(title, buf, titlelen);
01013 
01014         // Get the second line and grab the number of atoms
01015         if (mdio_readline(mf, buf, MAX_GRO_LINE + 1) < 0) return -1;
01016 
01017         // Store the number of atoms
01018         if (natoms) if (!(*natoms = atoi(buf)))
01019                 return mdio_seterror(MDIO_BADFORMAT);
01020 
01021         // Now we rewind the file so that subsequent calls to
01022         // gro_timestep() will succeed. gro_timestep() requires
01023         // the header to be at the current file pointer.
01024         if (rewind) fseek(mf->f, fpos, SEEK_SET);
01025 
01026         // Done!
01027         return 0;
01028 }
01029 
01030 
01031 // Reads one atom record from a GROMACS file. Returns GMX_SUCCESS
01032 // on success or a negative number on error.
01033 //
01034 // Record format (one line, fixed):
01035 //    rrrrrRRRRRaaaaaAAAAA <x pos> <y pos> <z pos> <x vel> <y vel> <z vel>
01036 //
01037 //    r = residue number
01038 //    R = residue name
01039 //    a = atom name
01040 //    A = atom number
01041 //
01042 static int gro_rec(md_file *mf, md_atom *ma) {
01043         char    buf[MAX_GRO_LINE + 1];
01044         char    atomnum[6];
01045         int     n;
01046 
01047         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01048 
01049         do {
01050                 if (mdio_readline(mf, buf, MAX_GRO_LINE + 1, 0) < 0) return -1;
01051         } while (buf[0] == '#' || !strlen(buf));
01052 
01053         // Read in the fields
01054         n = sscanf(buf, "%5c%5c%5c%5c%f %f %f", ma->resid,
01055                 ma->resname, ma->atomname, atomnum, ma->pos,
01056                 &ma->pos[1], &ma->pos[2]);
01057         if (n != 7) return mdio_seterror(MDIO_BADFORMAT);
01058 
01059         // Null terminate the strings
01060         ma->resname[5] = 0;
01061         ma->atomname[5] = 0;
01062         ma->resid[5] = 0;
01063         atomnum[5] = 0;
01064 
01065         // Convert strings to numbers
01066         strip_white(atomnum);
01067         ma->atomnum = atoi(atomnum);
01068 
01069         // Convert nanometers to angstroms
01070         ma->pos[0] *= ANGS_PER_NM;
01071         ma->pos[1] *= ANGS_PER_NM;
01072         ma->pos[2] *= ANGS_PER_NM;
01073 
01074         // Strip leading and trailing whitespace
01075         strip_white(ma->atomname);
01076         strip_white(ma->resname);
01077         strip_white(ma->resid);
01078 
01079         return 0;
01080 }
01081 
01082 
01083 // Reads in a timestep from a .gro file. Ignores the data
01084 // not needed for a timestep, so is a little faster than
01085 // calling gro_rec() for each atom. Also reads in the
01086 // header block.
01087 //
01088 static int gro_timestep(md_file *mf, md_ts *ts) {
01089         char buf[MAX_GRO_LINE + 1];
01090         long coord;
01091         int i, n, boxItems;
01092   float x[3], y[3], z[3];
01093 
01094         if (!mf || !ts) return mdio_seterror(MDIO_BADPARAMS);
01095 
01096         if (gro_header(mf, NULL, 0, &ts->time, &ts->natoms, 0) < 0)
01097                 return -1;
01098         ts->pos = (float *) malloc(3 * sizeof(float) * ts->natoms);
01099         if (!ts->pos)
01100                 return mdio_seterror(MDIO_BADMALLOC);
01101 
01102         coord = 0;
01103         for (i = 0; i < ts->natoms; i++) {
01104                 if (mdio_readline(mf, buf, MAX_GRO_LINE + 1, 0) < 0) {
01105                         free(ts->pos);
01106                         return -1;
01107                 }
01108         
01109                 n = sscanf(buf, "%*5c%*5c%*5c%*5c%f %f %f",
01110                         &ts->pos[coord], &ts->pos[coord + 1],
01111                         &ts->pos[coord + 2]);
01112 
01113                 ts->pos[coord] *= ANGS_PER_NM;
01114                 ts->pos[coord + 1] *= ANGS_PER_NM;
01115                 ts->pos[coord + 2] *= ANGS_PER_NM;
01116 
01117                 if (n != 3) return mdio_seterror(MDIO_BADFORMAT);
01118                 coord += 3;
01119         }
01120 
01121         // Read the box, stored as three vectors representing its edges
01122         if (mdio_readline(mf, buf, MAX_GRO_LINE + 1, 0) < 0) {
01123                 free(ts->pos);
01124                 return -1;
01125         }
01126   boxItems = sscanf(buf, " %f %f %f %f %f %f %f %f %f", 
01127              &x[0], &y[1], &z[2], &x[1], &x[2], &y[0], &y[2], &z[0], &z[1]);
01128   // File may only include three scalars for the box information -- if
01129   // that's the case, the box is orthoganal.
01130   if (boxItems == 3) {
01131     x[1] = x[2] = 0;
01132     y[0] = y[2] = 0;
01133     z[0] = z[1] = 0;
01134   }
01135   else if (boxItems != 9) {
01136     free(ts->pos);
01137     return -1;
01138   }
01139 
01140   // Allocate the box and convert the vectors.
01141   ts->box = (md_box *) malloc(sizeof(md_box));
01142   if (mdio_readbox(ts->box, x, y, z) < 0) {
01143     free(ts->pos);
01144     free(ts->box);
01145     ts->box = NULL;
01146     return -1;
01147   }
01148 
01149         return 0;
01150 }
01151 
01152 
01153 // Attempts to read header data from a .trX trajectory file
01154 //
01155 // The .trX header format is as follows:
01156 //
01157 //      4 bytes         - magic number (0x07C9)
01158 //      ...
01159 //
01160 static int trx_header(md_file *mf, int rewind) {
01161         int magic;
01162         trx_hdr *hdr;
01163         long fpos;
01164 
01165         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01166 
01167         // In case we need to rewind
01168         fpos = ftell(mf->f);
01169 
01170         // We need to store some data to the trX header data
01171         // structure inside the md_file structure
01172         hdr = mf->trx;
01173         if (!mf->trx) return mdio_seterror(MDIO_BADPARAMS);
01174 
01175         // Read the magic number
01176         if (trx_int(mf, &magic) < 0) return -1;
01177         if (magic != TRX_MAGIC) {
01178                 // Try reverse endianism
01179                 swap4_aligned(&magic, 1);
01180                 if (magic != TRX_MAGIC) return mdio_seterror(MDIO_BADFORMAT);
01181 
01182                 // Enable byte swapping (actually works, too!)
01183                 mf->rev = 1;
01184         }
01185 
01186         // Read the version number. 
01187         // XXX. this is not the version number, but the storage size
01188         // of the following XDR encoded string.
01189         // the 'title' string is in fact the version identifier.
01190         // since VMD does not use any of that, it does no harm,
01191         // but is should still be fixed occasionally. AK 2005/01/08.
01192         if (trx_int(mf, &hdr->version) < 0) return -1;
01193 
01194         // Read in the title string
01195         if (trx_string(mf, hdr->title, MAX_TRX_TITLE) < 0)
01196                 return -1;
01197 
01198         // Read in some size data
01199         if (trx_int(mf, &hdr->ir_size) < 0) return -1;
01200         if (trx_int(mf, &hdr->e_size) < 0) return -1;
01201         if (trx_int(mf, &hdr->box_size) < 0) return -1;
01202         if (trx_int(mf, &hdr->vir_size) < 0) return -1;
01203         if (trx_int(mf, &hdr->pres_size) < 0) return -1;
01204         if (trx_int(mf, &hdr->top_size) < 0) return -1;
01205         if (trx_int(mf, &hdr->sym_size) < 0) return -1;
01206         if (trx_int(mf, &hdr->x_size) < 0) return -1;
01207         if (trx_int(mf, &hdr->v_size) < 0) return -1;
01208         if (trx_int(mf, &hdr->f_size) < 0) return -1;
01209         if (trx_int(mf, &hdr->natoms) < 0) return -1;
01210         if (trx_int(mf, &hdr->step) < 0) return -1;
01211         if (trx_int(mf, &hdr->nre) < 0) return -1;
01212 
01213         // Make sure there are atoms...
01214         if (!hdr->natoms) return mdio_seterror(MDIO_BADFORMAT);
01215 
01216         // Try to determine precision (float? double?)
01217         if (hdr->x_size) mf->prec = hdr->x_size / (hdr->natoms * 3);
01218         else if (hdr->v_size) mf->prec = hdr->v_size / (hdr->natoms * 3);
01219         else if (hdr->f_size) mf->prec = hdr->f_size / (hdr->natoms * 3);
01220         else return mdio_seterror(MDIO_BADPRECISION);
01221 
01222         if (mf->prec != sizeof(float) && mf->prec != sizeof(double)) {
01223                 // We have no data types this size! The
01224                 // file must've been generated on another
01225                 // platform
01226                 return mdio_seterror(MDIO_BADPRECISION);
01227         }
01228 
01229         // Read in timestep and lambda
01230         if (trx_real(mf, &hdr->t) < 0) return -1;
01231         if (trx_real(mf, &hdr->lambda) < 0) return -1;
01232 
01233         // Rewind if necessary
01234         if (rewind) fseek(mf->f, fpos, SEEK_SET);
01235 
01236         return 0;
01237 }
01238 
01239 
01240 // Reads in an integer and stores it in y. Returns GMX_SUCCESS
01241 // on success or a negative number on error.
01242 static int trx_int(md_file *mf, int *y) {
01243         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01244 
01245         // sanity check.
01246         if (sizeof(int) != 4) return mdio_seterror(MDIO_SIZEERROR);
01247 
01248         if (y) {
01249                 if (fread(y, 4, 1, mf->f) != 1)
01250                         return mdio_seterror(MDIO_IOERROR);
01251                 if (mf->rev) swap4_aligned(y, 1);
01252         }
01253         else if (fseek(mf->f, 4, SEEK_CUR) != 0)
01254                 return mdio_seterror(MDIO_IOERROR);
01255 
01256         return mdio_seterror(MDIO_SUCCESS);
01257 }
01258 
01259 
01260 // Reads in either a float or a double, depending on the
01261 // precision, and stores that number in y. Returns
01262 // GMX_SUCCESS on success or a negative number on error.
01263 static int trx_real(md_file *mf, float *y) {
01264         double x;
01265 
01266         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01267 
01268         switch (mf->prec) {
01269                 case sizeof(float):
01270                         if (!y) {
01271                                 if (fseek(mf->f, mf->prec, SEEK_CUR) != 0)
01272                                         return mdio_seterror(MDIO_IOERROR);
01273                         } else {
01274                                 if (fread(y, mf->prec, 1, mf->f) != 1)
01275                                         return mdio_seterror(MDIO_IOERROR);
01276                                 if (mf->rev) swap4_aligned(y, 1);
01277                         }
01278                         return mdio_seterror(MDIO_SUCCESS);
01279 
01280                 case sizeof(double):
01281                         if (!y) {
01282                                 if (fseek(mf->f, mf->prec, SEEK_CUR) != 0)
01283                                         return mdio_seterror(MDIO_IOERROR);
01284                         } else {
01285                                 if (fread(&x, mf->prec, 1, mf->f) != 1)
01286                                         return mdio_seterror(MDIO_IOERROR);
01287                                 if (mf->rev) swap8_aligned(&x, 1);
01288                                 *y = (float) x;
01289                         }
01290                         return mdio_seterror(MDIO_SUCCESS);
01291 
01292                 default:
01293                         return mdio_seterror(MDIO_BADPRECISION);
01294         }
01295 
01296 }
01297 
01298 
01299 // Reads in a real-valued vector (taking precision into account).
01300 // Stores the vector in vec, and returns GMX_SUCCESS on success
01301 // or a negative number on error.
01302 static int trx_rvector(md_file *mf, float *vec) {
01303         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01304 
01305         if (!vec) {
01306                 if (trx_real(mf, NULL) < 0) return -1;
01307                 if (trx_real(mf, NULL) < 0) return -1;
01308                 if (trx_real(mf, NULL) < 0) return -1;
01309                 return mdio_seterror(MDIO_SUCCESS);
01310         } else {
01311                 if (trx_real(mf, &vec[0]) < 0) return -1;
01312                 if (trx_real(mf, &vec[1]) < 0) return -1;
01313                 if (trx_real(mf, &vec[2]) < 0) return -1;
01314                 return mdio_seterror(MDIO_SUCCESS);
01315         }
01316 }
01317 
01318 
01319 // Reads in a string by first reading an integer containing the
01320 // string's length, then reading in the string itself and storing
01321 // it in str. If the length is greater than max, it is truncated
01322 // and the rest of the string is skipped in the file. Returns the
01323 // length of the string on success or a negative number on error.
01324 static int trx_string(md_file *mf, char *str, int max) {
01325         int size;
01326   size_t ssize;
01327 
01328         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01329 
01330         if (trx_int(mf, &size) < 0) return -1;
01331   ssize = (size_t)size;
01332 
01333         if (str && size <= max) {
01334                 if (fread(str, 1, size, mf->f) != ssize)
01335                         return mdio_seterror(MDIO_IOERROR);
01336                 str[size] = 0;
01337                 return size;
01338         } else if (str) {
01339                 if (fread(str, 1, max, mf->f) != ssize)
01340                         return mdio_seterror(MDIO_IOERROR);
01341                 if (fseek(mf->f, size - max, SEEK_CUR) != 0)
01342                         return mdio_seterror(MDIO_IOERROR);
01343                 str[max] = 0;
01344                 return max;
01345         } else {
01346                 if (fseek(mf->f, size, SEEK_CUR) != 0)
01347                         return mdio_seterror(MDIO_IOERROR);
01348                 return 0;
01349         }
01350 }
01351 
01352 
01353 // Reads in a timestep frame from the .trX file and returns the
01354 // data in a timestep structure. Returns NULL on error.
01355 static int trx_timestep(md_file *mf, md_ts *ts) {
01356         int i;
01357   float x[3], y[3], z[3];
01358         trx_hdr *hdr;
01359 
01360         if (!mf || !ts) return mdio_seterror(MDIO_BADPARAMS);
01361         if (mf->fmt != MDFMT_TRJ && mf->fmt != MDFMT_TRR)
01362                 return mdio_seterror(MDIO_WRONGFORMAT);
01363 
01364         // Read the header
01365         if (trx_header(mf) < 0) return -1;
01366 
01367         // We need some data from the trX header
01368         hdr = mf->trx;
01369         if (!hdr) return mdio_seterror(MDIO_BADPARAMS);
01370 
01371         if (hdr->box_size) { // XXX need to check value of box_size!!
01372                 if (trx_rvector(mf, x) < 0) return -1;
01373                 if (trx_rvector(mf, y) < 0) return -1;
01374                 if (trx_rvector(mf, z) < 0) return -1;
01375     // Allocate the box and convert the vectors.
01376     ts->box = (md_box *) malloc(sizeof(md_box));
01377     if (mdio_readbox(ts->box, x, y, z) < 0) {
01378       free(ts->box);
01379       ts->box = NULL;
01380       return -1;
01381     }
01382         }
01383 
01384         if (hdr->vir_size) {
01385                 if (trx_rvector(mf, NULL) < 0) return -1;
01386                 if (trx_rvector(mf, NULL) < 0) return -1;
01387                 if (trx_rvector(mf, NULL) < 0) return -1;
01388         }
01389 
01390         if (hdr->pres_size) {
01391                 if (trx_rvector(mf, NULL) < 0) return -1;
01392                 if (trx_rvector(mf, NULL) < 0) return -1;
01393                 if (trx_rvector(mf, NULL) < 0) return -1;
01394         }
01395 
01396         if (hdr->x_size) {
01397                 ts->pos = (float *) malloc(sizeof(float) * 3 * hdr->natoms);
01398                 if (!ts->pos) return mdio_seterror(MDIO_BADMALLOC);
01399 
01400                 ts->natoms = hdr->natoms;
01401 
01402                 for (i = 0; i < hdr->natoms; i++) {
01403                         if (trx_rvector(mf, &ts->pos[i * 3]) < 0) {
01404                                 mdio_tsfree(ts, 1);
01405                                 return -1;
01406                         }
01407                         ts->pos[i * 3] *= ANGS_PER_NM;
01408                         ts->pos[i * 3 + 1] *= ANGS_PER_NM;
01409                         ts->pos[i * 3 + 2] *= ANGS_PER_NM;
01410                 }
01411         }
01412 
01413         if (hdr->v_size) {
01414                 for (i = 0; i < hdr->natoms; i++) {
01415                         if (trx_rvector(mf, NULL) < 0) {
01416                                 mdio_tsfree(ts, 1);
01417                                 return -1;
01418                         }
01419                 }
01420         }
01421 
01422         if (hdr->f_size) {
01423                 for (i = 0; i < hdr->natoms; i++) {
01424                         if (trx_rvector(mf, NULL) < 0) {
01425                                 mdio_tsfree(ts, 1);
01426                                 return -1;
01427                         }
01428                 }
01429         }
01430 
01431         return mdio_seterror(MDIO_SUCCESS);
01432 }
01433 
01434 
01435 // writes an int in big endian. Returns GMX_SUCCESS
01436 // on success or a negative number on error.
01437 static int put_trx_int(md_file *mf, int y) {
01438       if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01439 
01440       // sanity check.
01441       if (sizeof(int) != 4) return mdio_seterror(MDIO_SIZEERROR);
01442 
01443       if (mf->rev) swap4_aligned(&y, 1);
01444       if (fwrite(&y, 4, 1, mf->f) != 1)
01445     return mdio_seterror(MDIO_IOERROR);
01446 
01447   return mdio_seterror(MDIO_SUCCESS);
01448 }
01449 
01450 // writes a real in big-endian. Returns GMX_SUCCESS
01451 // on success or a negative number on error.
01452 static int put_trx_real(md_file *mf, float y) {
01453       if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01454 
01455       if (mf->rev) swap4_aligned(&y, 1);
01456       if (fwrite(&y, 4, 1, mf->f) != 1)
01457         return mdio_seterror(MDIO_IOERROR);
01458 
01459       return mdio_seterror(MDIO_SUCCESS);
01460 }
01461 
01462 
01463 // writes an xdr encoded string. Returns GMX_SUCCESS
01464 // on success or a negative number on error.
01465 static int put_trx_string(md_file *mf, const char *s) {
01466         if (!mf || !s) return mdio_seterror(MDIO_BADPARAMS);
01467         
01468         // write: size of object, string length, string data
01469         size_t len = strlen(s);
01470         if ( put_trx_int(mf, len+1)
01471              || put_trx_int(mf, len)
01472              || (fwrite(s, len, 1, mf->f) != 1))
01473           return mdio_seterror(MDIO_IOERROR);
01474 
01475         return mdio_seterror(MDIO_SUCCESS);
01476 }
01477 
01478 
01479 // xtc_int() - reads an integer from an xtc file
01480 static int xtc_int(md_file *mf, int *i) {
01481         unsigned char c[4];
01482 
01483         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01484         // sanity check.
01485         if (sizeof(int) != 4) return mdio_seterror(MDIO_SIZEERROR);
01486 
01487         if (fread(c, 1, 4, mf->f) != 4) {
01488                 if (feof(mf->f)) return mdio_seterror(MDIO_EOF);
01489                 else if (ferror(mf->f)) return mdio_seterror(MDIO_IOERROR);
01490                 else return mdio_seterror(MDIO_UNKNOWNERROR);
01491         }
01492 
01493         if (i) *i = c[3] + (c[2] << 8) + (c[1] << 16) + (c[0] << 24);
01494         return mdio_seterror(MDIO_SUCCESS);
01495 }
01496 
01497 
01498 // xtc_float() - reads a float from an xtc file
01499 static int xtc_float(md_file *mf, float *f) {
01500         unsigned char c[4];
01501         int i;
01502 
01503         if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01504 
01505         if (fread(c, 1, 4, mf->f) != 4) {
01506                 if (feof(mf->f)) return mdio_seterror(MDIO_EOF);
01507                 else if (ferror(mf->f)) return mdio_seterror(MDIO_IOERROR);
01508                 else return mdio_seterror(MDIO_UNKNOWNERROR);
01509         }
01510 
01511         if (f) {
01512                 // By reading the number in as an integer and then
01513                 // copying it to a floating point number we can
01514                 // ensure proper endianness
01515                 i = c[3] + (c[2] << 8) + (c[1] << 16) + (c[0] << 24);
01516                 memcpy(f, &i, 4);
01517         }
01518         return mdio_seterror(MDIO_SUCCESS);
01519 }
01520 
01521 
01522 // xtc_data() - reads a specific amount of data from an xtc
01523 // file using the xdr format.
01524 static int xtc_data(md_file *mf, char *buf, int len) {
01525         if (!mf || len < 1) return mdio_seterror(MDIO_BADPARAMS);
01526   size_t slen = (size_t)len;
01527         if (buf) {
01528                 if (fread(buf, 1, slen, mf->f) != slen) {
01529                         if (feof(mf->f)) return mdio_seterror(MDIO_EOF);
01530                         if (ferror(mf->f)) return mdio_seterror(MDIO_IOERROR);
01531                         else return mdio_seterror(MDIO_UNKNOWNERROR);
01532                 }
01533                 if (len % 4) {
01534                         if (fseek(mf->f, 4 - (len % 4), SEEK_CUR)) {
01535                                 if (feof(mf->f)) return mdio_seterror(MDIO_EOF);
01536                                 if (ferror(mf->f)) return mdio_seterror(MDIO_IOERROR);
01537                                 else return mdio_seterror(MDIO_UNKNOWNERROR);
01538                         }
01539                 }
01540         }
01541         else {
01542                 int newlen;
01543                 newlen = len;
01544                 if (len % 4) newlen += (4 - (len % 4));
01545                 if (fseek(mf->f, newlen, SEEK_CUR)) {
01546                         if (feof(mf->f)) return mdio_seterror(MDIO_EOF);
01547                         if (ferror(mf->f)) return mdio_seterror(MDIO_IOERROR);
01548                         else return mdio_seterror(MDIO_UNKNOWNERROR);
01549                 }
01550         }
01551         return len;
01552 }
01553 
01554 
01555 // xtc_timestep() - reads a timestep from an .xtc file.
01556 static int xtc_timestep(md_file *mf, md_ts *ts) {
01557         int n;
01558         float f, x[3], y[3], z[3];
01559 
01560         int size = 0; // explicitly initialized to zero.
01561         float precision;
01562 
01563         if (!mf || !ts) return mdio_seterror(MDIO_BADPARAMS);
01564         if (!mf->f) return mdio_seterror(MDIO_BADPARAMS);
01565         if (mf->fmt != MDFMT_XTC) return mdio_seterror(MDIO_WRONGFORMAT);
01566 
01567         // Check magic number
01568         if (xtc_int(mf, &n) < 0) return -1;
01569         if (n != XTC_MAGIC) return mdio_seterror(MDIO_BADFORMAT);
01570 
01571         // Get number of atoms
01572         if (xtc_int(mf, &n) < 0) return -1;
01573         ts->natoms = n;
01574 
01575         // Get the simulation step
01576         if (xtc_int(mf, &n) < 0) return -1;
01577         ts->step = n;
01578 
01579         // Get the time value
01580         if (xtc_float(mf, &f) < 0) return -1;
01581         ts->time = f;
01582 
01583         // Read the basis vectors of the box
01584   if ( (xtc_float(mf, &x[0]) < 0) ||
01585        (xtc_float(mf, &x[1]) < 0) ||
01586        (xtc_float(mf, &x[2]) < 0) ||
01587        (xtc_float(mf, &y[0]) < 0) ||
01588        (xtc_float(mf, &y[1]) < 0) ||
01589        (xtc_float(mf, &y[2]) < 0) ||
01590        (xtc_float(mf, &z[0]) < 0) ||
01591        (xtc_float(mf, &z[1]) < 0) ||
01592        (xtc_float(mf, &z[2]) < 0) )
01593     return -1;
01594   // Allocate the box and convert the vectors.
01595   ts->box = (md_box *) malloc(sizeof(md_box));
01596   if (mdio_readbox(ts->box, x, y, z) < 0) {
01597     free(ts->box);
01598     ts->box = NULL;
01599     return -1;
01600   }
01601 
01602         ts->pos = (float *) malloc(sizeof(float) * 3 * ts->natoms);
01603         if (!ts->pos) return mdio_seterror(MDIO_BADMALLOC);
01604         n = xtc_3dfcoord(mf, ts->pos, &size, &precision);
01605         if (n < 0) return -1;
01606 
01607         /* Now we're left with the job of scaling... */
01608         for (n = 0; n < ts->natoms * 3; n++)
01609                 ts->pos[n] *= ANGS_PER_NM;
01610 
01611         return mdio_seterror(MDIO_SUCCESS);
01612 }
01613 
01614 
01616 // This algorithm is an implementation of the 3dfcoord algorithm
01617 // written by Frans van Hoesel (hoesel@chem.rug.nl) as part of the
01618 // Europort project in 1995.
01620 
01621 // integer table used in decompression
01622 static int xtc_magicints[] = {
01623         0, 0, 0, 0, 0, 0, 0, 0, 0,8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
01624         80, 101, 128, 161, 203, 256, 322, 406, 512, 645, 812, 1024, 1290,
01625         1625, 2048, 2580, 3250, 4096, 5060, 6501, 8192, 10321, 13003, 16384,
01626         20642, 26007, 32768, 41285, 52015, 65536, 82570, 104031, 131072,
01627         165140, 208063, 262144, 330280, 416127, 524287, 660561, 832255,
01628         1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304,
01629         5284491, 6658042, 8388607, 10568983, 13316085, 16777216 };
01630 
01631 #define FIRSTIDX 9
01632 /* note that magicints[FIRSTIDX-1] == 0 */
01633 #define LASTIDX (sizeof(xtc_magicints) / sizeof(*xtc_magicints))
01634 
01635 
01636 // returns the number of bits in the binary expansion of
01637 // the given integer.
01638 static int xtc_sizeofint(int size) {
01639         unsigned int num = 1;
01640   unsigned int ssize = (unsigned int)size;
01641         int nbits = 0;
01642 
01643         while (ssize >= num && nbits < 32) {
01644                 nbits++;
01645                 num <<= 1;
01646         }
01647         return nbits;
01648 }
01649 
01650 // calculates the number of bits a set of integers, when compressed,
01651 // will take up.
01652 static int xtc_sizeofints(int nints, unsigned int *sizes) {
01653         int i;
01654   unsigned int num;
01655         unsigned int nbytes, nbits, bytes[32], bytecnt, tmp;
01656         nbytes = 1;
01657         bytes[0] = 1;
01658         nbits = 0;
01659         for (i=0; i < nints; i++) {     
01660                 tmp = 0;
01661                 for (bytecnt = 0; bytecnt < nbytes; bytecnt++) {
01662                         tmp = bytes[bytecnt] * sizes[i] + tmp;
01663                         bytes[bytecnt] = tmp & 0xff;
01664                         tmp >>= 8;
01665                 }
01666                 while (tmp != 0) {
01667                         bytes[bytecnt++] = tmp & 0xff;
01668                         tmp >>= 8;
01669                 }
01670                 nbytes = bytecnt;
01671         }
01672         num = 1;
01673         nbytes--;
01674         while (bytes[nbytes] >= num) {
01675                 nbits++;
01676                 num *= 2;
01677         }
01678         return nbits + nbytes * 8;
01679 }
01680 
01681 // reads bits from a buffer.    
01682 static int xtc_receivebits(int *buf, int nbits) {
01683         int cnt, num; 
01684         unsigned int lastbits, lastbyte;
01685         unsigned char * cbuf;
01686         int mask = (1 << nbits) -1;
01687 
01688         cbuf = ((unsigned char *)buf) + 3 * sizeof(*buf);
01689         cnt = buf[0];
01690         lastbits = (unsigned int) buf[1];
01691         lastbyte = (unsigned int) buf[2];
01692 
01693         num = 0;
01694         while (nbits >= 8) {
01695                 lastbyte = ( lastbyte << 8 ) | cbuf[cnt++];
01696                 num |=  (lastbyte >> lastbits) << (nbits - 8);
01697                 nbits -=8;
01698         }
01699         if (nbits > 0) {
01700                 if (lastbits < (unsigned int)nbits) {
01701                         lastbits += 8;
01702                         lastbyte = (lastbyte << 8) | cbuf[cnt++];
01703                 }
01704                 lastbits -= nbits;
01705                 num |= (lastbyte >> lastbits) & ((1 << nbits) -1);
01706         }
01707         num &= mask;
01708         buf[0] = cnt;
01709         buf[1] = lastbits;
01710         buf[2] = lastbyte;
01711         return num; 
01712 }
01713 
01714 // decompresses small integers from the buffer
01715 static void xtc_receiveints(int *buf, const int nints, int nbits,
01716                         unsigned int *sizes, int *nums) {
01717         int bytes[32];
01718         int i, j, nbytes, p, num;
01719 
01720         bytes[1] = bytes[2] = bytes[3] = 0;
01721         nbytes = 0;
01722         while (nbits > 8) {
01723                 bytes[nbytes++] = xtc_receivebits(buf, 8);
01724                 nbits -= 8;
01725         }
01726         if (nbits > 0) {
01727                 bytes[nbytes++] = xtc_receivebits(buf, nbits);
01728         }
01729         for (i = nints-1; i > 0; i--) {
01730                 num = 0;
01731                 for (j = nbytes-1; j >=0; j--) {
01732                         num = (num << 8) | bytes[j];
01733                         p = num / sizes[i];
01734                         bytes[j] = p;
01735                         num = num - p * sizes[i];
01736                 }
01737                 nums[i] = num;
01738         }
01739         nums[0] = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
01740 }
01741 
01742 // function that actually reads and writes compressed coordinates    
01743 static int xtc_3dfcoord(md_file *mf, float *fp, int *size, float *precision) {
01744         static int *ip = NULL;
01745         static int oldsize;
01746         static int *buf;
01747 
01748         int minint[3], maxint[3], *lip;
01749         int smallidx;
01750         unsigned sizeint[3], sizesmall[3], bitsizeint[3], size3;
01751         int flag, k;
01752         int small, smaller, i, is_smaller, run;
01753         float *lfp;
01754         int tmp, *thiscoord,  prevcoord[3];
01755 
01756         int bufsize, lsize;
01757         unsigned int bitsize;
01758         float inv_precision;
01759 
01760 
01761         if (xtc_int(mf, &lsize) < 0) return -1;
01762 
01763         if (*size != 0 && lsize != *size) return mdio_seterror(MDIO_BADFORMAT);
01764 
01765         *size = lsize;
01766         size3 = *size * 3;
01767         if (*size <= 9) {
01768                 for (i = 0; i < *size; i++) {
01769                         if (xtc_float(mf, fp + (3 * i)) < 0) return -1;
01770                         if (xtc_float(mf, fp + (3 * i) + 1) < 0) return -1;
01771                         if (xtc_float(mf, fp + (3 * i) + 2) < 0) return -1;
01772                 }
01773                 return *size;
01774         }
01775         xtc_float(mf, precision);
01776         if (ip == NULL) {
01777                 ip = (int *)malloc(size3 * sizeof(*ip));
01778                 if (ip == NULL) return mdio_seterror(MDIO_BADMALLOC);
01779                 bufsize = (int) (size3 * 1.2);
01780                 buf = (int *)malloc(bufsize * sizeof(*buf));
01781                 if (buf == NULL) return mdio_seterror(MDIO_BADMALLOC);
01782                 oldsize = *size;
01783         } else if (*size > oldsize) {
01784                 ip = (int *)realloc(ip, size3 * sizeof(*ip));
01785                 if (ip == NULL) return mdio_seterror(MDIO_BADMALLOC);
01786                 bufsize = (int) (size3 * 1.2);
01787                 buf = (int *)realloc(buf, bufsize * sizeof(*buf));
01788                 if (buf == NULL) return mdio_seterror(MDIO_BADMALLOC);
01789                 oldsize = *size;
01790         }
01791         buf[0] = buf[1] = buf[2] = 0;
01792 
01793         xtc_int(mf, &(minint[0]));
01794         xtc_int(mf, &(minint[1]));
01795         xtc_int(mf, &(minint[2]));
01796 
01797         xtc_int(mf, &(maxint[0]));
01798         xtc_int(mf, &(maxint[1]));
01799         xtc_int(mf, &(maxint[2]));
01800                 
01801         sizeint[0] = maxint[0] - minint[0]+1;
01802         sizeint[1] = maxint[1] - minint[1]+1;
01803         sizeint[2] = maxint[2] - minint[2]+1;
01804         
01805         /* check if one of the sizes is to big to be multiplied */
01806         if ((sizeint[0] | sizeint[1] | sizeint[2] ) > 0xffffff) {
01807                 bitsizeint[0] = xtc_sizeofint(sizeint[0]);
01808                 bitsizeint[1] = xtc_sizeofint(sizeint[1]);
01809                 bitsizeint[2] = xtc_sizeofint(sizeint[2]);
01810                 bitsize = 0; /* flag the use of large sizes */
01811         } else {
01812                 bitsize = xtc_sizeofints(3, sizeint);
01813         }
01814 
01815         xtc_int(mf, &smallidx);
01816         smaller = xtc_magicints[FIRSTIDX > smallidx - 1 ? FIRSTIDX : smallidx - 1] / 2;
01817         small = xtc_magicints[smallidx] / 2;
01818         sizesmall[0] = sizesmall[1] = sizesmall[2] = xtc_magicints[smallidx] ;
01819 
01820         /* buf[0] holds the length in bytes */
01821 
01822         if (xtc_int(mf, &(buf[0])) < 0) return -1;
01823 
01824         if (xtc_data(mf, (char *) &buf[3], (int) buf[0]) < 0) return -1;
01825 
01826         buf[0] = buf[1] = buf[2] = 0;
01827 
01828         lfp = fp;
01829         inv_precision = 1.0f / (*precision);
01830         run = 0;
01831         i = 0;
01832         lip = ip;
01833         while (i < lsize) {
01834                 thiscoord = (int *)(lip) + i * 3;
01835 
01836                 if (bitsize == 0) {
01837                         thiscoord[0] = xtc_receivebits(buf, bitsizeint[0]);
01838                         thiscoord[1] = xtc_receivebits(buf, bitsizeint[1]);
01839                         thiscoord[2] = xtc_receivebits(buf, bitsizeint[2]);
01840                 } else {
01841                         xtc_receiveints(buf, 3, bitsize, sizeint, thiscoord);
01842                 }
01843 
01844                 i++;
01845                 thiscoord[0] += minint[0];
01846                 thiscoord[1] += minint[1];
01847                 thiscoord[2] += minint[2];
01848 
01849                 prevcoord[0] = thiscoord[0];
01850                 prevcoord[1] = thiscoord[1];
01851                 prevcoord[2] = thiscoord[2];
01852  
01853 
01854                 flag = xtc_receivebits(buf, 1);
01855                 is_smaller = 0;
01856                 if (flag == 1) {
01857                         run = xtc_receivebits(buf, 5);
01858                         is_smaller = run % 3;
01859                         run -= is_smaller;
01860                         is_smaller--;
01861                 }
01862                 if (run > 0) {
01863                         thiscoord += 3;
01864                         for (k = 0; k < run; k+=3) {
01865                                 xtc_receiveints(buf, 3, smallidx, sizesmall, thiscoord);
01866                                 i++;
01867                                 thiscoord[0] += prevcoord[0] - small;
01868                                 thiscoord[1] += prevcoord[1] - small;
01869                                 thiscoord[2] += prevcoord[2] - small;
01870                                 if (k == 0) {
01871                                         /* interchange first with second atom for better
01872                                          * compression of water molecules
01873                                          */
01874                                         tmp = thiscoord[0]; thiscoord[0] = prevcoord[0];
01875                                         prevcoord[0] = tmp;
01876                                         tmp = thiscoord[1]; thiscoord[1] = prevcoord[1];
01877                                         prevcoord[1] = tmp;
01878                                         tmp = thiscoord[2]; thiscoord[2] = prevcoord[2];
01879                                         prevcoord[2] = tmp;
01880                                         *lfp++ = prevcoord[0] * inv_precision;
01881                                         *lfp++ = prevcoord[1] * inv_precision;
01882                                         *lfp++ = prevcoord[2] * inv_precision;
01883                                 } else {
01884                                         prevcoord[0] = thiscoord[0];
01885                                         prevcoord[1] = thiscoord[1];
01886                                         prevcoord[2] = thiscoord[2];
01887                                 }
01888                                 *lfp++ = thiscoord[0] * inv_precision;
01889                                 *lfp++ = thiscoord[1] * inv_precision;
01890                                 *lfp++ = thiscoord[2] * inv_precision;
01891                         }
01892                 } else {
01893                         *lfp++ = thiscoord[0] * inv_precision;
01894                         *lfp++ = thiscoord[1] * inv_precision;
01895                         *lfp++ = thiscoord[2] * inv_precision;          
01896                 }
01897                 smallidx += is_smaller;
01898                 if (is_smaller < 0) {
01899                         small = smaller;
01900                         if (smallidx > FIRSTIDX) {
01901                                 smaller = xtc_magicints[smallidx - 1] /2;
01902                         } else {
01903                                 smaller = 0;
01904                         }
01905                 } else if (is_smaller > 0) {
01906                         smaller = small;
01907                         small = xtc_magicints[smallidx] / 2;
01908                 }
01909                 sizesmall[0] = sizesmall[1] = sizesmall[2] = xtc_magicints[smallidx] ;
01910         }
01911         return 1;
01912 }
01913 #endif

Generated on Wed Mar 22 13:15:30 2006 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002