00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
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
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;
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
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
00111
00112
00113 typedef struct {
00114 int version;
00115 char title[MAX_TRX_TITLE + 1];
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;
00124 int v_size;
00125 int f_size;
00126 int natoms;
00127 int step;
00128 int nre;
00129 float t;
00130 float lambda;
00131 } trx_hdr;
00132
00133
00134
00135
00136 typedef struct {
00137 FILE * f;
00138 int fmt;
00139 int prec;
00140 int rev;
00141 trx_hdr * trx;
00142
00143 } md_file;
00144
00145
00146
00147 typedef struct {
00148 char title[MAX_MDIO_TITLE + 1];
00149 int natoms;
00150 float timeval;
00151 } md_header;
00152
00153
00154
00155 typedef struct {
00156 float A, B, C, alpha, beta, gamma;
00157 } md_box;
00158
00159
00160
00161 typedef struct {
00162 float *pos;
00163
00164
00165
00166 int natoms;
00167 int step;
00168 float time;
00169 md_box *box;
00170 } md_ts;
00171
00172
00173
00174 typedef struct {
00175 char resid[7];
00176 char resname[7];
00177 int atomnum;
00178 char atomname[7];
00179 float pos[3];
00180
00181 } md_atom;
00182
00183
00184
00185
00186
00187
00188
00189 static md_file *mdio_open(const char *, const int, const int=MDIO_READ);
00190
00191
00192 static int mdio_close(md_file *);
00193
00194
00195
00196 static int mdio_header(md_file *, md_header *);
00197 static int mdio_timestep(md_file *, md_ts *);
00198
00199
00200
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
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
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
00223 static int xtc_int(md_file *, int *);
00224 static int xtc_float(md_file *, float *);
00225
00226
00227
00228
00229 static int xtc_timestep(md_file *, md_ts *);
00230 static int xtc_3dfcoord(md_file *, float *, int *, float *);
00231
00232
00233
00234 static int mdio_errno(void);
00235 static const char *mdio_errmsg(int);
00236 static int mdio_seterror(int);
00237
00238
00239
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
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
00284
00285
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
00295 mf = (md_file *) malloc(sizeof(md_file));
00296 if (!mf) {
00297 mdio_seterror(MDIO_BADMALLOC);
00298 return NULL;
00299 }
00300
00301
00302 memset(mf, 0, sizeof(md_file));
00303
00304
00305 if (!fmt) {
00306 char *p;
00307 int n;
00308
00309
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
00318 for (n = 1; mdio_fmtexts[n]; n++)
00319 if (!strcasecmp(p, mdio_fmtexts[n])) break;
00320
00321
00322 if (!mdio_fmtexts[n]) {
00323 free(mf);
00324 mdio_seterror(MDIO_UNKNOWNFMT);
00325 return NULL;
00326 }
00327
00328
00329 mf->fmt = n;
00330 }
00331 else {
00332 mf->fmt = fmt;
00333 }
00334
00335
00336
00337 switch (mf->fmt) {
00338 case MDFMT_GRO:
00339 case MDFMT_G96:
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:
00348
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:
00357
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
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
00379 mdio_seterror(MDIO_SUCCESS);
00380 return mf;
00381 }
00382
00383
00384
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
00391 if (mf->trx) free(mf->trx);
00392 free(mf);
00393 return mdio_seterror(MDIO_SUCCESS);
00394 }
00395
00396
00397
00398 static int mdio_errno(void) {
00399 return mdio_errcode;
00400 }
00401
00402
00403
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
00411
00412 static int mdio_seterror(int code) {
00413 mdio_errcode = code;
00414 return code ? -1 : 0;
00415 }
00416
00417
00418
00419
00420
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
00425 fgets(buf, n, mf->f);
00426
00427
00428 if (feof(mf->f)) return mdio_seterror(MDIO_EOF);
00429
00430
00431 if (ferror(mf->f)) return mdio_seterror(MDIO_IOERROR);
00432
00433
00434 if (strip) strip_white(buf);
00435
00436 return strlen(buf);
00437 }
00438
00439
00440
00441
00442
00443 static int strip_white(char *buf) {
00444 int i, j, k;
00445
00446
00447 if (!buf) return -1;
00448 if (!strlen(buf)) return -1;
00449
00450
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
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
00472
00473
00474
00475
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
00492
00493
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
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
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
00515
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
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
00553 if (xtc_int(mf, &n) < 0) return -1;
00554 if (n != XTC_MAGIC) return mdio_seterror(MDIO_BADFORMAT);
00555
00556
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
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
00598 if (!mf) return mdio_seterror(MDIO_BADPARAMS);
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
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
00619 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00620
00621
00622
00623 if ((p = (char *) strstr(buf, "t="))) {
00624 char *q = p;
00625 *(q--) = 0;
00626
00627
00628
00629 p += 2;
00630 strip_white(p);
00631 strip_white(buf);
00632
00633
00634 if (timeval) *timeval = (float) atof(p);
00635 }
00636 else {
00637
00638
00639 if (timeval) *timeval = 0;
00640 strip_white(buf);
00641 }
00642
00643
00644 if (title && titlelen) strncpy(title, buf, titlelen);
00645
00646
00647 while (strcasecmp(buf, "END"))
00648 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00649
00650
00651 return mdio_seterror(MDIO_SUCCESS);
00652 }
00653
00654
00655
00656
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
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
00692 if (!mf || !ma) return mdio_seterror(MDIO_BADPARAMS);
00693
00694
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
00727
00728
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
00737 if (!mf || !ts) return mdio_seterror(MDIO_BADPARAMS);
00738
00739
00740
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
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00779
00780 if (!strcasecmp(buf, "TITLE")) {
00781
00782 while (strcasecmp(buf, "END")) {
00783 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00784 }
00785
00786
00787 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00788 }
00789
00790
00791 if (!strcasecmp(buf, "TIMESTEP")) {
00792
00793 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00794
00795
00796 n = sscanf(buf, "%d %f", &ts->step, &ts->time);
00797 if (n != 2) return mdio_seterror(MDIO_BADFORMAT);
00798
00799
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
00805 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00806 }
00807 else {
00808
00809 ts->step = 0;
00810 ts->time = 0;
00811 }
00812
00813
00814
00815 if (!strcasecmp(buf, "POSITIONRED")) {
00816
00817
00818 i = 0;
00819 while (i < ts->natoms) {
00820
00821 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0)
00822 return -1;
00823
00824
00825 if (!strcasecmp(buf, "END"))
00826 return mdio_seterror(MDIO_BADFORMAT);
00827
00828
00829 n = sscanf(buf, "%f %f %f", &pos[0], &pos[1], &pos[2]);
00830
00831
00832 if (n == 3) {
00833 pos[0] *= ANGS_PER_NM;
00834 pos[1] *= ANGS_PER_NM;
00835 pos[2] *= ANGS_PER_NM;
00836
00837
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
00847
00848
00849
00850
00851
00852
00853 i = 0;
00854 while (i < ts->natoms) {
00855
00856 if (mdio_readline(mf, buf, MAX_G96_LINE + 1, 0) < 0)
00857 return -1;
00858
00859
00860 strcpy(stripbuf, buf);
00861 strip_white(stripbuf);
00862 if (!strcasecmp(stripbuf, "END"))
00863 return mdio_seterror(MDIO_BADFORMAT);
00864
00865
00866 n = sscanf(buf, "%*6c%*6c%*6c%*6c %f %f %f",
00867 &pos[0], &pos[1], &pos[2]);
00868
00869
00870 if (n == 3) {
00871 pos[0] *= ANGS_PER_NM;
00872 pos[1] *= ANGS_PER_NM;
00873 pos[2] *= ANGS_PER_NM;
00874
00875
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
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
00893
00894
00895
00896
00897
00898 fpos = ftell(mf->f);
00899
00900
00901 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) {
00902
00903
00904 if (mdio_errcode == MDIO_EOF)
00905 return mdio_seterror(MDIO_SUCCESS);
00906 else
00907 return -1;
00908 }
00909
00910
00911 if (!strcasecmp(buf, "VELOCITY") || !strcasecmp(buf, "VELOCITYRED")) {
00912
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
00920
00921 fpos = ftell(mf->f);
00922
00923
00924 if (mdio_readline(mf, buf, MAX_G96_LINE + 1) < 0) return -1;
00925 }
00926
00927
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
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
00961
00962
00963
00964 fseek(mf->f, fpos, SEEK_SET);
00965 }
00966
00967
00968 return mdio_seterror(MDIO_SUCCESS);
00969 }
00970
00971
00972
00973
00974
00975
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
00983 if (!mf) return mdio_seterror(MDIO_BADPARAMS);
00984
00985
00986 fpos = ftell(mf->f);
00987
00988
00989 if (mdio_readline(mf, buf, MAX_GRO_LINE + 1) < 0) return -1;
00990
00991
00992
00993 if ((p = (char *) strstr(buf, "t="))) {
00994 char *q = p;
00995 *(q--) = 0;
00996
00997
00998
00999 p += 2;
01000 strip_white(p);
01001 strip_white(buf);
01002
01003
01004 if (timeval) *timeval = (float) atof(p);
01005 }
01006 else {
01007
01008 if (timeval) *timeval = 0;
01009 }
01010
01011
01012 if (title && titlelen) strncpy(title, buf, titlelen);
01013
01014
01015 if (mdio_readline(mf, buf, MAX_GRO_LINE + 1) < 0) return -1;
01016
01017
01018 if (natoms) if (!(*natoms = atoi(buf)))
01019 return mdio_seterror(MDIO_BADFORMAT);
01020
01021
01022
01023
01024 if (rewind) fseek(mf->f, fpos, SEEK_SET);
01025
01026
01027 return 0;
01028 }
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
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
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
01060 ma->resname[5] = 0;
01061 ma->atomname[5] = 0;
01062 ma->resid[5] = 0;
01063 atomnum[5] = 0;
01064
01065
01066 strip_white(atomnum);
01067 ma->atomnum = atoi(atomnum);
01068
01069
01070 ma->pos[0] *= ANGS_PER_NM;
01071 ma->pos[1] *= ANGS_PER_NM;
01072 ma->pos[2] *= ANGS_PER_NM;
01073
01074
01075 strip_white(ma->atomname);
01076 strip_white(ma->resname);
01077 strip_white(ma->resid);
01078
01079 return 0;
01080 }
01081
01082
01083
01084
01085
01086
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
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
01129
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
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
01154
01155
01156
01157
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
01168 fpos = ftell(mf->f);
01169
01170
01171
01172 hdr = mf->trx;
01173 if (!mf->trx) return mdio_seterror(MDIO_BADPARAMS);
01174
01175
01176 if (trx_int(mf, &magic) < 0) return -1;
01177 if (magic != TRX_MAGIC) {
01178
01179 swap4_aligned(&magic, 1);
01180 if (magic != TRX_MAGIC) return mdio_seterror(MDIO_BADFORMAT);
01181
01182
01183 mf->rev = 1;
01184 }
01185
01186
01187
01188
01189
01190
01191
01192 if (trx_int(mf, &hdr->version) < 0) return -1;
01193
01194
01195 if (trx_string(mf, hdr->title, MAX_TRX_TITLE) < 0)
01196 return -1;
01197
01198
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
01214 if (!hdr->natoms) return mdio_seterror(MDIO_BADFORMAT);
01215
01216
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
01224
01225
01226 return mdio_seterror(MDIO_BADPRECISION);
01227 }
01228
01229
01230 if (trx_real(mf, &hdr->t) < 0) return -1;
01231 if (trx_real(mf, &hdr->lambda) < 0) return -1;
01232
01233
01234 if (rewind) fseek(mf->f, fpos, SEEK_SET);
01235
01236 return 0;
01237 }
01238
01239
01240
01241
01242 static int trx_int(md_file *mf, int *y) {
01243 if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01244
01245
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
01261
01262
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
01300
01301
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
01320
01321
01322
01323
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
01354
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
01365 if (trx_header(mf) < 0) return -1;
01366
01367
01368 hdr = mf->trx;
01369 if (!hdr) return mdio_seterror(MDIO_BADPARAMS);
01370
01371 if (hdr->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
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
01436
01437 static int put_trx_int(md_file *mf, int y) {
01438 if (!mf) return mdio_seterror(MDIO_BADPARAMS);
01439
01440
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
01451
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
01464
01465 static int put_trx_string(md_file *mf, const char *s) {
01466 if (!mf || !s) return mdio_seterror(MDIO_BADPARAMS);
01467
01468
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
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
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
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
01513
01514
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
01523
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
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;
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
01568 if (xtc_int(mf, &n) < 0) return -1;
01569 if (n != XTC_MAGIC) return mdio_seterror(MDIO_BADFORMAT);
01570
01571
01572 if (xtc_int(mf, &n) < 0) return -1;
01573 ts->natoms = n;
01574
01575
01576 if (xtc_int(mf, &n) < 0) return -1;
01577 ts->step = n;
01578
01579
01580 if (xtc_float(mf, &f) < 0) return -1;
01581 ts->time = f;
01582
01583
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
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
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
01617
01618
01620
01621
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
01633 #define LASTIDX (sizeof(xtc_magicints) / sizeof(*xtc_magicints))
01634
01635
01636
01637
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
01651
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
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
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
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
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;
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
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
01872
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