00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define NOMINMAX 1 // prevent MSVS from defining min/max macros
00024
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <math.h>
00029
00030 #include "AtomParser.h"
00031 #include "y.tab.h"
00032 #include "ParseTree.h"
00033 #include "Inform.h"
00034 #include "JRegex.h"
00035 #include "AtomSel.h"
00036 #include "Timestep.h"
00037 #include "DrawMolecule.h"
00038 #include "SpatialSearch.h"
00039
00040 #include <vector>
00041 #include <algorithm>
00042
00043
00044
00045 #define case_compare_numeric_macro(switchcase, symbol) \
00046 case switchcase: \
00047 l->convert(SymbolTableElement::IS_FLOAT); \
00048 r->convert(SymbolTableElement::IS_FLOAT); \
00049 ldval = l->dval; \
00050 rdval = r->dval; \
00051 flg = flgs; \
00052 for (i=num-1; i>=0; i--) { \
00053 *flg &= (*ldval symbol *rdval); \
00054 ldval += lincr; rdval += rincr; flg++; \
00055 } \
00056 break;
00057
00058 #define case_compare_string_macro(switchcase, symbol) \
00059 case switchcase: \
00060 l->convert(SymbolTableElement::IS_STRING); \
00061 r->convert(SymbolTableElement::IS_STRING); \
00062 lsptr = l->sval; \
00063 rsptr = r->sval; \
00064 flg = flgs; \
00065 for (i=num-1; i>=0; i--) { \
00066 if (*flg) \
00067 *flg &= (strcmp(*lsptr, *rsptr) symbol 0); \
00068 lsptr += lincr; rsptr += rincr; flg++; \
00069 } \
00070 break;
00071
00072
00074 ParseTree::ParseTree(SymbolTable *parser, atomparser_node *parse_tree)
00075 {
00076 tree = parse_tree;
00077 table = parser;
00078 selected_array = NULL;
00079 num_selected = 0;
00080 context = NULL;
00081 }
00082
00083 ParseTree::~ParseTree(void) {
00084 if (selected_array != NULL)
00085 delete [] selected_array;
00086 delete tree;
00087 }
00088
00089 void ParseTree::eval_compare(atomparser_node *node, int num, int *flgs) {
00090 int i;
00091 double *ldval, *rdval;
00092 char **lsptr, **rsptr;
00093 int lincr, rincr;
00094 int *flg;
00095
00096
00097 symbol_data *l = eval(node->left, num, flgs);
00098 symbol_data *r = eval(node->right, num, flgs);
00099
00100
00101
00102
00103 lincr = l->num == num ? 1 : 0;
00104 rincr = r->num == num ? 1 : 0;
00105
00106 switch (node->ival) {
00107 case_compare_numeric_macro(NLT, < )
00108 case_compare_numeric_macro(NLE, <= )
00109 case_compare_numeric_macro(NEQ, == )
00110 case_compare_numeric_macro(NGE, >= )
00111 case_compare_numeric_macro(NGT, > )
00112 case_compare_numeric_macro(NNE, != )
00113
00114 case_compare_string_macro(SLT, < )
00115 case_compare_string_macro(SLE, <= )
00116 case_compare_string_macro(SEQ, == )
00117 case_compare_string_macro(SGE, >= )
00118 case_compare_string_macro(SGT, > )
00119 case_compare_string_macro(SNE, != )
00120
00121 case MATCH: {
00122 l->convert(SymbolTableElement::IS_STRING);
00123 r->convert(SymbolTableElement::IS_STRING);
00124 lsptr = l->sval;
00125 rsptr = r->sval;
00126 flg = flgs;
00127 JRegex *rgx = NULL;
00128 const char *first = *rsptr;
00129
00130 for (i=0; i<num; i++) {
00131 if (i==0 || strcmp(*rsptr, first)) {
00132 if (rgx)
00133 delete rgx;
00134 rgx = new JRegex(*rsptr);
00135 first = *rsptr;
00136 }
00137 if (rgx) {
00138 if (*flg)
00139 *flg &= (rgx->match(*lsptr, strlen(*lsptr)) != -1);
00140 } else {
00141 *flg = 0;
00142 }
00143 lsptr += lincr; rsptr += rincr; flg++;
00144 }
00145 if (rgx) {
00146 delete rgx;
00147 }
00148
00149 break;
00150 }
00151
00152 default:
00153 msgWarn << "ParseTree::eval_compare() missing operator!" << sendmsg;
00154 }
00155
00156 delete l;
00157 delete r;
00158 }
00159
00160
00161
00162 symbol_data * ParseTree::eval_mathop(atomparser_node *node, int num, int *flgs)
00163 {
00164 symbol_data *l = eval(node->left, num, flgs);
00165 symbol_data *r = eval(node->right, num, flgs);
00166
00167
00168
00169 int lincr = l->num == num ? (~0) : 0;
00170 int rincr = r->num == num ? (~0) : 0;
00171 l->convert(SymbolTableElement::IS_FLOAT);
00172 r->convert(SymbolTableElement::IS_FLOAT);
00173 symbol_data *tmp = new symbol_data(SymbolTableElement::IS_FLOAT, num);
00174 int i;
00175 const double *lval = l->dval;
00176 const double *rval = r->dval;
00177 double *tmpval = tmp->dval;
00178
00179
00180
00181
00182
00183
00184 switch (node->node_type) {
00185 case ADD:
00186 for (i=num-1; i>=0; i--) {
00187 if (flgs[i]) tmpval[i] = lval[lincr & i] + rval[rincr & i];
00188 }
00189 break;
00190 case SUB:
00191 for (i=num-1; i>=0; i--) {
00192 if (flgs[i]) tmpval[i] = lval[lincr & i] - rval[rincr & i];
00193 }
00194 break;
00195 case MULT:
00196 for (i=num-1; i>=0; i--) {
00197 if (flgs[i]) tmpval[i] = lval[lincr & i] * rval[rincr & i];
00198 }
00199 break;
00200 case DIV:
00201 for (i=num-1; i>=0; i--) {
00202 if (flgs[i]) tmpval[i] = lval[lincr & i] / rval[rincr & i];
00203 }
00204 break;
00205 case MOD:
00206 for (i=num-1; i>=0; i--) {
00207 if (flgs[i]) tmpval[i] = fmod(lval[lincr & i], rval[rincr & i]);
00208 }
00209 break;
00210 case EXP:
00211 for (i=num-1; i>=0; i--) {
00212 if (flgs[i]) tmpval[i] = pow(lval[lincr & i], rval[rincr & i]);
00213 }
00214 break;
00215 }
00216
00217 delete l;
00218 delete r;
00219 return tmp;
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 void ParseTree::eval_stringfctn(atomparser_node *node, int num, int *flgs) {
00232 int count = 0;
00233 atomparser_node *left;
00234
00235
00236 for (left = node->left; left != NULL; left = left->left) {
00237 count++;
00238 }
00239 if (count == 0)
00240 return;
00241
00242
00243 char **argv= (char **) calloc(1, count * sizeof(char *));
00244 int *types = new int[count];
00245 int i=0;
00246 for (left = node->left; left != NULL; left = left -> left, i++) {
00247
00248 switch (left->sele.st) {
00249 case RAW_STRING:
00250 types[i] = 0;
00251 argv[i] = (char *) ((const char *) left->sele.s);
00252 break;
00253
00254 case SQ_STRING:
00255 types[i] = 1;
00256 argv[i] = (char *) ((const char *) left->sele.s);
00257 break;
00258
00259 case DQ_STRING:
00260 types[i] = 2;
00261 argv[i] = (char *) ((const char *) left->sele.s);
00262 break;
00263 }
00264
00265 if (left->extra_type != -1) {
00266 types[i] += 3;
00267 }
00268 }
00269
00270
00271 int *tmp_flgs = new int[num];
00272 memcpy(tmp_flgs, flgs, num * sizeof(int));
00273 SymbolTableElement *elem = table->fctns.data(node->extra_type);
00274 elem->keyword_stringfctn(context, count, (const char **)argv, types, num, tmp_flgs);
00275
00276 for (i = num-1; i>=0; i--) {
00277 if (flgs[i]) flgs[i] = tmp_flgs[i];
00278 }
00279 delete [] tmp_flgs;
00280 delete [] types;
00281 free(argv);
00282 }
00283
00284 static void same_string(symbol_data *tmp, symbol_data *tmp2, int num,
00285 int *subselect, int *flgs) {
00286 hash_t hash;
00287 int i;
00288 hash_init(&hash, num);
00289
00290
00291 for (i=0; i<num; i++)
00292 if (subselect[i])
00293 hash_insert(&hash, tmp2->sval[i], 0);
00294
00295
00296
00297
00298 for (i=0; i<num; i++)
00299 if (flgs[i])
00300 flgs[i] = (hash_lookup(&hash, tmp->sval[i]) != HASH_FAIL);
00301
00302 hash_destroy(&hash);
00303 }
00304
00305 static void same_int(symbol_data *tmp, symbol_data *tmp2, int num,
00306 int *subselect, int *flgs) {
00307
00308
00309 int *int_table = NULL, int_min, int_max;
00310 int i;
00311 for (i=0; i<num; i++) if (subselect[i]) break;
00312 if (i==num) {
00313
00314 memset(flgs, 0, num*sizeof(int));
00315 return;
00316 }
00317 int_min = int_max = tmp2->ival[i];
00318 while (++i < num) {
00319 if (!subselect[i]) continue;
00320 int ival = tmp2->ival[i];
00321 if (ival > int_max)
00322 int_max = ival;
00323 if (ival < int_min)
00324 int_min = ival;
00325 }
00326 int_table = (int *) calloc(1+int_max-int_min,sizeof(int));
00327 for (i=0; i<num; i++) {
00328 if (subselect[i]) {
00329 int_table[tmp2->ival[i]-int_min] = 1;
00330 }
00331 }
00332
00333
00334 for (i=0; i<num; i++) {
00335 if (flgs[i]) {
00336 int ival = tmp->ival[i];
00337 if (ival >= int_min && ival <= int_max)
00338 flgs[i] = int_table[ival-int_min];
00339 else
00340 flgs[i] = 0;
00341 }
00342 }
00343 delete [] int_table;
00344 }
00345
00346 static void same_double(symbol_data *tmp, symbol_data *tmp2, int num,
00347 int *subselect, int *flgs) {
00348
00349
00350 hash_t hash;
00351 int i, n=0;
00352 for (i=0; i<num; i++) n += subselect[i];
00353 char *doublestring = new char[25*n];
00354 char *istring = doublestring;
00355 hash_init(&hash, n);
00356 for (i=0; i<num; i++)
00357 if (subselect[i]) {
00358 sprintf(istring,"%f", (double) tmp2->dval[i]);
00359 hash_insert(&hash, istring, 0);
00360 istring += 25;
00361 }
00362 char tmpstring[25];
00363 for (i=0; i<num; i++) {
00364 sprintf(tmpstring,"%f", (double) tmp->dval[i]);
00365 flgs[i] &= (hash_lookup(&hash, tmpstring) != HASH_FAIL);
00366 }
00367 hash_destroy(&hash);
00368 delete [] doublestring;
00369 }
00370
00371
00372
00373
00374
00375
00376 void ParseTree::eval_same(atomparser_node *node, int num, int *flgs) {
00377 int i;
00378 int *subselect = new int[num];
00379 for (i=0; i<num; subselect[i++]=1);
00380
00381
00382 if (eval(node->left, num, subselect)) {
00383 delete [] subselect;
00384 msgErr << "eval of a 'same' returned data when it shouldn't have"
00385 << sendmsg;
00386 return;
00387 }
00388
00389
00390
00391
00392 SymbolTableElement *elem = table->fctns.data(node->extra_type);
00393 SymbolTableElement::symtype has_type = elem->returns_a;
00394 symbol_data *tmp, *tmp2;
00395 tmp = new symbol_data(has_type, num);
00396 tmp2 = new symbol_data(has_type, num);
00397
00398
00399
00400 switch (has_type) {
00401 case SymbolTableElement::IS_INT:
00402 elem->keyword_int(context, num, tmp->ival, flgs);
00403 elem->keyword_int(context, num, tmp2->ival, subselect);
00404 same_int(tmp, tmp2, num, subselect, flgs);
00405 break;
00406
00407 case SymbolTableElement::IS_FLOAT:
00408 elem->keyword_double(context, num, tmp->dval, flgs);
00409 elem->keyword_double(context, num, tmp2->dval, subselect);
00410 same_double(tmp, tmp2, num, subselect, flgs);
00411 break;
00412
00413 case SymbolTableElement::IS_STRING:
00414 elem->keyword_string(context, num, (const char **)tmp->sval, flgs);
00415 elem->keyword_string(context, num, (const char **)tmp2->sval, subselect);
00416 same_string(tmp, tmp2, num, subselect, flgs);
00417 break;
00418 }
00419
00420 delete tmp;
00421 delete tmp2;
00422 delete [] subselect;
00423 }
00424
00425
00426
00427
00428 symbol_data *ParseTree::eval_key(atomparser_node *node, int num, int *flgs) {
00429
00430 SymbolTableElement *elem = table->fctns.data(node->extra_type);
00431 SymbolTableElement::symtype has_type = elem->returns_a;
00432 symbol_data *tmp;
00433 tmp = new symbol_data(has_type, num);
00434
00435 switch (has_type) {
00436 case SymbolTableElement::IS_INT:
00437 elem->keyword_int(context, num, tmp->ival, flgs);
00438 break;
00439 case SymbolTableElement::IS_FLOAT:
00440 elem->keyword_double(context, num, tmp->dval, flgs);
00441 break;
00442 case SymbolTableElement::IS_STRING:
00443 elem->keyword_string(context, num, (const char **)tmp->sval, flgs);
00444 break;
00445 }
00446
00447
00448
00449 int *int_table = NULL;
00450
00451 int int_min=0, int_max=0;
00452 int have_first=0;
00453 if (has_type == SymbolTableElement::IS_INT) {
00454 for (int i=0; i<num; i++) {
00455 if (!flgs[i])
00456 continue;
00457
00458 if (!have_first) {
00459 int_min = int_max = tmp->ival[i];
00460 have_first = 1;
00461 } else {
00462 const int ival = tmp->ival[i];
00463 if (ival > int_max)
00464 int_max = ival;
00465 if (ival < int_min)
00466 int_min = ival;
00467 }
00468 }
00469 int_table = (int *) calloc(1+int_max-int_min, sizeof(int));
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479 int *newflgs = new int[num];
00480 for (int i=num-1; i>=0; i--) {
00481 newflgs[i] = 0;
00482 }
00483
00484 if (node->left) {
00485 atomparser_node *left = node->left;
00486 while (left) {
00487 if (left->extra_type == -1) {
00488
00489 switch(has_type) {
00490 case SymbolTableElement::IS_INT:
00491 {
00492 int ival = atoi(left->sele.s);
00493 if (ival >= int_min && ival <= int_max)
00494 int_table[ival-int_min] = 1;
00495 }
00496 break;
00497
00498 case SymbolTableElement::IS_FLOAT:
00499 {
00500
00501 double dval = atof(left->sele.s);
00502 double delta = fabs(dval / 1000);
00503 double maxval = dval+delta;
00504 double minval = dval-delta;
00505 for (int i=num-1; i>=0; i--) {
00506 if (flgs[i])
00507 newflgs[i] |= (minval <= tmp->dval[i] && maxval >= tmp->dval[i]);
00508 }
00509 }
00510 break;
00511
00512 case SymbolTableElement::IS_STRING:
00513 {
00514 switch (left->sele.st) {
00515 case SQ_STRING:
00516 case RAW_STRING:
00517 {
00518 for (int i=num-1; i>=0; i--) {
00519
00520
00521
00522 if (flgs[i] && (tmp->sval[i] != NULL)) {
00523 newflgs[i] |= !strcmp(left->sele.s, tmp->sval[i]);
00524 }
00525 }
00526 }
00527 break;
00528
00529 case DQ_STRING:
00530 default:
00531 {
00532
00533
00534
00535
00536
00537
00538 JString temps = "^("+left->sele.s+")$";
00539 JRegex r(temps, 1);
00540 for (int i=num-1; i>=0; i--) {
00541 if (flgs[i]) newflgs[i] |= (r.match(tmp->sval[i],
00542 strlen(tmp->sval[i])) != -1);
00543 }
00544 }
00545 break;
00546 }
00547 }
00548 }
00549 } else {
00550 switch(has_type) {
00551 case SymbolTableElement::IS_INT:
00552 {
00553 int ltval = atoi(left->sele.s);
00554 int gtval = atoi(left->left->sele.s);
00555 if (ltval < int_min) ltval = int_min;
00556 if (gtval > int_max) gtval = int_max;
00557 for (int i=ltval-int_min; i<= gtval-int_min; i++)
00558 int_table[i] = 1;
00559 }
00560 break;
00561 case SymbolTableElement::IS_FLOAT:
00562 {
00563 double ltval = atof(left->sele.s);
00564 double gtval = atof(left->left->sele.s);
00565 for (int i=num-1; i>=0; i--) {
00566 if (flgs[i])
00567 newflgs[i] |= ((ltval <= tmp->dval[i]) && (gtval >= tmp->dval[i]));
00568 }
00569 }
00570 break;
00571 default:
00572 {
00573
00574 for (int i=num-1; i>=0; i--) {
00575 if (flgs[i])
00576 newflgs[i] |= (flgs[i] && strcmp(left->sele.s, tmp->sval[i]) <= 0
00577 && strcmp(left->left->sele.s, tmp->sval[i]) >= 0);
00578
00579 }
00580 }
00581 }
00582 left = left->left;
00583 }
00584 left = left->left;
00585 }
00586
00587
00588 if (has_type == SymbolTableElement::IS_INT) {
00589 for (int i=0; i<num; i++) {
00590 if (flgs[i])
00591 flgs[i] = int_table[tmp->ival[i]-int_min];
00592 }
00593 free(int_table);
00594 } else {
00595 for (int i=num-1; i>=0; i--) {
00596 if (flgs[i])
00597 flgs[i] = newflgs[i];
00598 }
00599 }
00600 delete [] newflgs;
00601 delete tmp;
00602 return NULL;
00603 } else {
00604
00605
00606
00607 delete [] newflgs;
00608 if (int_table) free(int_table);
00609 return tmp;
00610 }
00611 }
00612
00613
00614 void ParseTree::eval_single(atomparser_node *node, int num, int *flgs) {
00615
00616
00617 atomsel_ctxt *ctxt = (atomsel_ctxt *)context;
00618 ctxt->singleword = table->fctns.name(node->extra_type);
00619 table->fctns.data(node->extra_type)->keyword_single(context, num, flgs);
00620 }
00621
00622
00623 void ParseTree::eval_exwithin(atomparser_node *node, int num, int *flgs) {
00624 eval_within(node, num, flgs);
00625
00626
00627 int *others = new int[num];
00628 int i;
00629 for (i=0; i<num; others[i++] = 1);
00630
00631
00632 if (eval(node->left, num, others)) {
00633 delete [] others;
00634 msgErr << "eval of a 'within' returned data when it shouldn't have." << sendmsg;
00635 return;
00636 }
00637 for (i=0; i<num; i++) {
00638 if (others[i]) flgs[i] = 0;
00639 }
00640 delete [] others;
00641 }
00642
00643
00644
00645 static Timestep *selframe(DrawMolecule *atom_sel_mol, int which_frame) {
00646 switch (which_frame) {
00647 case AtomSel::TS_LAST: return atom_sel_mol->get_last_frame();
00648 case AtomSel::TS_NOW : return atom_sel_mol->current();
00649 default: {
00650 if (!atom_sel_mol->get_frame(which_frame)) {
00651 return atom_sel_mol->get_last_frame();
00652
00653 } else {
00654 return atom_sel_mol->get_frame(which_frame);
00655 }
00656 }
00657 }
00658 return NULL;
00659 }
00660
00661 void ParseTree::eval_pbwithin(atomparser_node *node, int num, int *flgs) {
00662
00663
00664 if ((float) node->dval <= 0.0f) {
00665 eval(node->left, num, flgs);
00666 return;
00667 }
00668
00669
00670
00671
00672 int i;
00673
00674
00675 ResizeArray<float> coords(3*2*num);
00676
00677
00678
00679 ResizeArray<int> others(2*num);
00680
00681
00682
00683
00684 ResizeArray<int> repflgs(2*num);
00685
00686
00687 ResizeArray<int> repindexes(num);
00688
00689
00690 atomsel_ctxt *ctxt = (atomsel_ctxt *)context;
00691 const Timestep *ts = selframe(ctxt->atom_sel_mol, ctxt->which_frame);
00692 if (!ts) {
00693 msgErr << "No timestep available for 'within' search!" << sendmsg;
00694 return;
00695 }
00696 for (i=0; i<num; ++i) others.append(1);
00697 if (eval(node->left, num, &others[0])) {
00698 msgErr << "eval of a 'within' returned data when it shouldn't have." << sendmsg;
00699 return;
00700 }
00701
00702
00703 const float * pos=ts->pos;
00704 for (i=0; i<num; i++) {
00705 coords.append(pos[0]);
00706 coords.append(pos[1]);
00707 coords.append(pos[2]);
00708 pos += 3;
00709 repflgs.append(flgs[i]);
00710 }
00711
00712
00713 float min[3], max[3];
00714 if (!find_minmax_selected(num, &others[0], ts->pos,
00715 min[0], min[1], min[2], max[0], max[1], max[2])) {
00716 memset(flgs, 0, num*sizeof(int));
00717 return;
00718 }
00719
00720
00721 const float cutoff = (float)node->dval;
00722 for (i=0; i<3; i++) {
00723 min[i] -= cutoff;
00724 max[i] += cutoff;
00725 }
00726
00727
00728 float A[3], B[3], C[3];
00729 ts->get_transform_vectors(A, B, C);
00730 for (i=-1; i<=1; i++) {
00731 float v1[3];
00732 vec_scale(v1, (float) i, A);
00733 for (int j=-1; j<=1; j++) {
00734 float v2[3];
00735 vec_scale(v2, (float) j, B);
00736 for (int k=-1; k<=1; k++) {
00737
00738 if (!i && !j && !k) continue;
00739 float v3[3];
00740 vec_scale(v3, (float) k, C);
00741 float vx = v1[0] + v2[0] + v3[0];
00742 float vy = v1[1] + v2[1] + v3[1];
00743 float vz = v1[2] + v2[2] + v3[2];
00744 pos = ts->pos;
00745 for (int ind=0; ind<num; ind++) {
00746 if (flgs[ind]) {
00747 const float x = pos[0] + vx;
00748 const float y = pos[1] + vy;
00749 const float z = pos[2] + vz;
00750 if (x>min[0] && x<=max[0] &&
00751 y>min[1] && y<=max[1] &&
00752 z>min[2] && z<=max[2]) {
00753 repindexes.append(ind);
00754 coords.append(x);
00755 coords.append(y);
00756 coords.append(z);
00757 repflgs.append(1);
00758 others.append(0);
00759 }
00760 }
00761 pos += 3;
00762 }
00763 }
00764 }
00765 }
00766
00767 find_within(&coords[0], &repflgs[0], &others[0], others.num(), cutoff);
00768
00769
00770 memcpy(flgs, &repflgs[0], num*sizeof(int));
00771
00772
00773 for (i=0; i<repindexes.num(); i++) {
00774 if (repflgs[num+i]) {
00775 flgs[repindexes[i]] = 1;
00776 }
00777 }
00778 }
00779
00780
00781 void ParseTree::eval_within(atomparser_node *node, int num, int *flgs) {
00782
00783 if ((float) node->dval > 0.0f) {
00784
00785 int *others = new int[num];
00786 int i;
00787 for (i=0; i<num; ++i)
00788 others[i] = 1;
00789
00790 if (eval(node->left, num, others)) {
00791 delete [] others;
00792 msgErr << "eval of a 'within' returned data when it shouldn't have." << sendmsg;
00793 return;
00794 }
00795
00796
00797 atomsel_ctxt *ctxt = (atomsel_ctxt *)context;
00798 Timestep *ts = selframe(ctxt->atom_sel_mol, ctxt->which_frame);
00799 if (!ts) {
00800 msgErr << "No timestep available for 'within' search!" << sendmsg;
00801 return;
00802 }
00803
00804 find_within(ts->pos, flgs, others, num, (float) node->dval);
00805
00806 delete [] others;
00807 } else {
00808
00809
00810 eval(node->left, num, flgs);
00811 }
00812 }
00813
00814
00815 void ParseTree::eval_within_bonds(atomparser_node *node, int num, int *flgs) {
00816 atomsel_ctxt *ctxt = (atomsel_ctxt *)context;
00817 int *others = new int[num];
00818
00819 int i;
00820 for (i=0; i<num; ++i)
00821 others[i] = 1;
00822
00823 if (eval(node->left, num, others)) {
00824 delete [] others;
00825 msgErr << "eval of a 'within' returned data when it shouldn't have." << sendmsg;
00826 return;
00827 }
00828
00829
00830 int *bondedsel = new int[num];
00831 memcpy(bondedsel, others, num*sizeof(int));
00832
00833
00834 int bonddepth;
00835 for (bonddepth=0; bonddepth<node->ival; bonddepth++) {
00836
00837 for (i=0; i<num; i++) {
00838 if (bondedsel[i]) {
00839 MolAtom *atom = ctxt->atom_sel_mol->atom(i);
00840 int j;
00841 for (j=0; j<atom->bonds; j++) {
00842 others[atom->bondTo[j]] = 1;
00843 }
00844 }
00845 }
00846
00847
00848 memcpy(bondedsel, others, num*sizeof(int));
00849 }
00850
00851 for (i=0; i<num; ++i)
00852 if (bondedsel[i] && flgs[i])
00853 flgs[i] = 1;
00854 else
00855 flgs[i] = 0;
00856
00857 delete [] bondedsel;
00858 delete [] others;
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870 namespace {
00871 struct PointDistance {
00872 float o;
00873 int i;
00874 PointDistance() {}
00875 PointDistance(float o_, int i_) : o(o_), i(i_) {}
00876 bool operator<(const PointDistance& p) const {
00877 return o<p.o;
00878 }
00879 };
00880 }
00881
00882 void ParseTree::eval_k_nearest(atomparser_node *node, int num, int *flgs) {
00883 atomsel_ctxt *ctxt = (atomsel_ctxt *)context;
00884 const Timestep *ts = selframe(ctxt->atom_sel_mol, ctxt->which_frame);
00885 if (!ts) {
00886 msgErr << "No timestep available for 'nearest' search!" << sendmsg;
00887 return;
00888 }
00889 const int N = node->ival;
00890 int i;
00891
00892
00893 std::vector<int> others(num);
00894 for (i=0; i<num; ++i) others[i] = 1;
00895 if (eval(node->left, num, &others[0])) {
00896 msgErr << "eval of a 'within' returned data when it shouldn't have." << sendmsg;
00897 return;
00898 }
00899
00900
00901 for (i=0; i<num; i++) if (others[i]) break;
00902 if (i==num) {
00903 memset(flgs,0,num*sizeof(*flgs));
00904 return;
00905 }
00906
00907 std::vector<PointDistance> distances;
00908 for (i=0; i<num; i++) {
00909 if (others[i] || !flgs[i]) continue;
00910 #if 1
00911 float d2=1e37f;
00912 #else
00913 float d2=std::numeric_limits<float>::max();
00914 #endif
00915 for (int j=0; j<num; j++) {
00916 if (!others[j]) continue;
00917 float d2_j=distance2(ts->pos+3*i, ts->pos+3*j);
00918 if (d2_j<d2) d2=d2_j;
00919 }
00920 distances.push_back(PointDistance(d2,i));
00921 }
00922 std::sort(distances.begin(), distances.end());
00923 int n=N;
00924 if (n>distances.size()) n=distances.size();
00925 memset(flgs,0,num*sizeof(*flgs));
00926 for (i=0; i<n; i++) {
00927 flgs[distances[i].i]=1;
00928 }
00929 }
00930
00931
00932
00933
00934
00935 void ParseTree::find_rings(int num, int *flgs, int *others,
00936 int minringsize, int maxringsize) {
00937 #ifdef VMDWITHCARBS
00938 int i;
00939
00940
00941
00942
00943 atomsel_ctxt *ctxt = (atomsel_ctxt *)context;
00944 ctxt->atom_sel_mol->find_small_rings_and_links(5, maxringsize);
00945 SmallRing *ring;
00946 memset(flgs, 0, num*sizeof(int));
00947 for (i=0; i < ctxt->atom_sel_mol->smallringList.num(); i++) {
00948 ring = ctxt->atom_sel_mol->smallringList[i];
00949 int N = ring->num();
00950 if (N >= minringsize && N <= maxringsize) {
00951 int j;
00952 for (j=0; j<N; j++) {
00953 int ind = (*ring)[j];
00954 flgs[ind] = others[ind];
00955 }
00956 }
00957 }
00958 #else
00959 memset(flgs, 0, num*sizeof(int));
00960 #endif
00961 }
00962
00963
00964 void ParseTree::eval_maxringsize(atomparser_node *node, int num, int *flgs) {
00965
00966 int *others = new int[num];
00967 int i;
00968 for (i=0; i<num; ++i)
00969 others[i] = 1;
00970
00971 if (eval(node->left, num, others)) {
00972 delete [] others;
00973 msgErr << "eval of a 'maxringsize' returned data when it shouldn't have." << sendmsg;
00974 return;
00975 }
00976
00977 find_rings(num, flgs, others, 1, node->ival);
00978
00979 delete [] others;
00980 }
00981
00982
00983 void ParseTree::eval_ringsize(atomparser_node *node, int num, int *flgs) {
00984
00985 int *others = new int[num];
00986 int i;
00987 for (i=0; i<num; ++i)
00988 others[i] = 1;
00989
00990 if (eval(node->left, num, others)) {
00991 delete [] others;
00992 msgErr << "eval of a 'ringsize' returned data when it shouldn't have." << sendmsg;
00993 return;
00994 }
00995
00996 find_rings(num, flgs, others, node->ival, node->ival);
00997
00998 delete [] others;
00999 }
01000
01001
01002
01003
01004 symbol_data *ParseTree::eval(atomparser_node *node, int num, int *flgs) {
01005 int i;
01006 int *flg1, *flg2;
01007 symbol_data *tmp;
01008 switch(node->node_type) {
01009 case AND:
01010 eval(node->left, num, flgs);
01011 eval(node->right, num, flgs);
01012 return NULL;
01013
01014 case NOT:
01015 flg1 = new int[num];
01016 memcpy(flg1, flgs, num*sizeof(int));
01017
01018 eval(node->left, num, flg1);
01019
01020 for (i=num-1; i>=0; i--) {
01021 if (flgs[i])
01022 flgs[i] = !flg1[i];
01023 }
01024 delete [] flg1;
01025 break;
01026
01027 case OR:
01028 flg1 = new int[num];
01029 memcpy(flg1, flgs, num*sizeof(int));
01030 eval(node->left, num, flg1);
01031 flg2 = new int[num];
01032 memcpy(flg2, flgs, num*sizeof(int));
01033 eval(node->right, num, flg2);
01034 for (i=num-1; i>=0; i--) {
01035 flgs[i] = flgs[i] && (flg1[i] || flg2[i]);
01036 }
01037 delete [] flg1;
01038 delete [] flg2;
01039 break;
01040
01041 case FLOATVAL:
01042 tmp = new symbol_data(SymbolTableElement::IS_FLOAT, 1);
01043 tmp->dval[0] = node->dval;
01044 return tmp;
01045
01046 case INTVAL:
01047 tmp = new symbol_data(SymbolTableElement::IS_INT, 1);
01048 tmp->ival[0] = node->ival;
01049 return tmp;
01050
01051 case STRWORD:
01052 tmp = new symbol_data(SymbolTableElement::IS_STRING, 1);
01053 tmp->sval[0] = (char *)(const char *)node->sele.s;
01054 return tmp;
01055
01056 case KEY:
01057 return eval_key(node, num, flgs);
01058
01059 case STRFCTN:
01060 eval_stringfctn(node, num, flgs);
01061 break;
01062
01063 case FUNC:
01064 {
01065
01066
01067
01068 symbol_data *inp = eval(node->left, num, flgs);
01069 inp->convert(SymbolTableElement::IS_FLOAT);
01070
01071
01072 symbol_data *ret = new symbol_data(SymbolTableElement::IS_FLOAT, num);
01073 SymbolTableElement *elem = table->fctns.data(node->extra_type);
01074
01075
01076
01077
01078 if (inp->num == num) {
01079 for (i=0; i<num; i++)
01080 ret->dval[i] = elem->fctn(inp->dval[i]);
01081 } else {
01082
01083
01084 double d = elem->fctn(inp->dval[0]);
01085 for (i=0; i<num; i++)
01086 ret->dval[i] = d;
01087 }
01088 delete inp;
01089 return ret;
01090 }
01091
01092 case ADD:
01093 case SUB:
01094 case MULT:
01095 case MOD:
01096 case EXP:
01097 case DIV:
01098 return eval_mathop(node, num, flgs);
01099
01100 case UMINUS:
01101 tmp = eval(node->left, num, flgs);
01102 tmp->convert(SymbolTableElement::IS_FLOAT);
01103 for (i=0; i<tmp->num; i++) {
01104 tmp->dval[i] = -tmp->dval[i];
01105 }
01106 return tmp;
01107
01108 case COMPARE:
01109 eval_compare(node, num, flgs);
01110 break;
01111
01112 case WITHIN:
01113 eval_within(node, num, flgs);
01114 break;
01115
01116 case EXWITHIN:
01117 eval_exwithin(node, num, flgs);
01118 break;
01119
01120 case PBWITHIN:
01121 eval_pbwithin(node, num, flgs);
01122 break;
01123
01124 #if defined(NEAREST)
01125 case NEAREST:
01126 eval_k_nearest(node, num, flgs);
01127 break;
01128 #endif
01129
01130 #if defined(WITHINBONDS)
01131 case WITHINBONDS:
01132 eval_within_bonds(node, num, flgs);
01133 break;
01134 #endif
01135
01136 #if defined(MAXRINGSIZE)
01137 case MAXRINGSIZE:
01138 eval_maxringsize(node, num, flgs);
01139 break;
01140 #endif
01141
01142 #if defined(RINGSIZE)
01143 case RINGSIZE:
01144 eval_ringsize(node, num, flgs);
01145 break;
01146 #endif
01147
01148 case SAME:
01149 eval_same(node, num, flgs);
01150 break;
01151
01152 case SINGLE:
01153 eval_single(node, num, flgs);
01154 break;
01155
01156 default:
01157 msgWarn << "ParseTree::eval() unknown node type: " << node->node_type << sendmsg;
01158 break;
01159 }
01160
01161 return NULL;
01162 }
01163
01164
01165
01166 void ParseTree::eval_find_recursion(atomparser_node *node, int *found,
01167 hash_t *hash) {
01168
01169
01170
01171 switch (node->node_type) {
01172 case AND:
01173 case OR:
01174 eval_find_recursion(node->left, found, hash);
01175 eval_find_recursion(node->right, found, hash);
01176
01177
01178 break;
01179
01180 case NOT:
01181 case UMINUS:
01182 case WITHIN:
01183 case EXWITHIN:
01184 case SAME:
01185 case FUNC:
01186 eval_find_recursion(node->left, found, hash);
01187 break;
01188
01189 case SINGLE:
01190 {
01191 const char *thisword = table->fctns.name(node->extra_type);
01192 const char *macro = table->get_custom_singleword(thisword);
01193 if (macro) {
01194 if (hash_insert(hash, thisword, 0) != HASH_FAIL) {
01195 *found = 1;
01196 } else {
01197 ParseTree *subtree = table->parse(macro);
01198 if (subtree != NULL) {
01199 eval_find_recursion(subtree->tree, found, hash);
01200 delete subtree;
01201 } else {
01202
01203
01204
01205
01206 msgErr << "ParseTree) internal processing error, NULL "
01207 << "subtree value while checking recursion" << sendmsg;
01208 }
01209 hash_delete(hash, thisword);
01210 }
01211 }
01212 }
01213 break;
01214 }
01215 }
01216
01217
01218
01219 int ParseTree::find_recursion(const char *head) {
01220 hash_t hash;
01221 hash_init(&hash, 10);
01222 hash_insert(&hash, head, 0);
01223 int found = 0;
01224 eval_find_recursion(tree, &found, &hash);
01225 hash_destroy(&hash);
01226 return found;
01227 }
01228
01229
01230
01231
01232
01233 int ParseTree::evaluate(int num_atoms, int *flgs) {
01234 int num = num_atoms;
01235 if (!tree || num < 0 ) {
01236 return 0;
01237 }
01238
01239
01240 for (int i=0; i<num; i++) {
01241 flgs[i] = 1;
01242 }
01243
01244
01245 symbol_data *retdat = eval(tree, num, flgs);
01246 if (retdat) {
01247 msgErr << "Atom selection returned data when it shouldn't\n" << sendmsg;
01248 delete retdat;
01249 }
01250
01251 return 1;
01252 }
01253
01254
01255
01256 void symbol_data::make_space(void) {
01257 free_space();
01258 switch(type) {
01259 case SymbolTableElement::IS_FLOAT:
01260 dval = new double[num];
01261 break;
01262
01263 case SymbolTableElement::IS_INT:
01264 ival = new int[num];
01265 break;
01266
01267 case SymbolTableElement::IS_STRING:
01268 sval = new char *[num];
01269 memset(sval, 0, num*sizeof(char *));
01270 break;
01271 }
01272 }
01273
01274
01275
01276 void symbol_data::free_space(void) {
01277 switch (type) {
01278 case SymbolTableElement::IS_FLOAT:
01279 if (dval)
01280 delete [] dval;
01281 dval = NULL;
01282 break;
01283
01284 case SymbolTableElement::IS_INT:
01285 if (ival)
01286 delete [] ival;
01287 ival = NULL;
01288 break;
01289
01290 case SymbolTableElement::IS_STRING:
01291 if (sval) {
01292
01293 if (free_sval)
01294 for (int i=0; i<num; i++) free(sval[i]);
01295
01296 delete [] sval;
01297 sval = NULL;
01298 }
01299 free_sval = 0;
01300 break;
01301
01302 default:
01303 msgErr << "Unknown data type " << (int)type
01304 << " in symbol_data::free_space" << sendmsg;
01305 }
01306 }
01307
01308
01309
01310 symbol_data::symbol_data(SymbolTableElement::symtype new_type, int new_num) {
01311 type = new_type;
01312 num = new_num;
01313 dval = NULL;
01314 ival = NULL;
01315 sval = NULL;
01316 free_sval = 0;
01317 make_space();
01318 }
01319
01320
01321 symbol_data::~symbol_data(void) {
01322 free_space();
01323 }
01324
01325
01326 void symbol_data::convert(SymbolTableElement::symtype totype) {
01327
01328 if (totype == type)
01329 return;
01330
01331
01332 if (totype == SymbolTableElement::IS_FLOAT) {
01333 double *tmp = new double[num];
01334 if (type == SymbolTableElement::IS_INT) {
01335 for (int i=num-1; i>=0; i--) {
01336 tmp[i] = (double) ival[i];
01337 }
01338 } else {
01339 for (int i=num-1; i>=0; i--) {
01340
01341
01342
01343
01344
01345
01346
01347
01348 if (sval[i] != NULL) {
01349 tmp[i] = atof(sval[i]);
01350 } else {
01351 for (int j=num-1; j>=0; j--) {
01352 tmp[i] = 0.0f;
01353 }
01354 msgErr << "ParseTree) internal processing error, NULL string value "
01355 << "while converting to floating point" << sendmsg;
01356 break;
01357 }
01358 }
01359 }
01360 free_space();
01361 type = totype;
01362 dval = tmp;
01363 return;
01364 }
01365
01366
01367 if (totype == SymbolTableElement::IS_STRING) {
01368 char **tmp = new char*[num];
01369 memset(tmp, 0, num*sizeof(char *));
01370 char s[100];
01371 if (type == SymbolTableElement::IS_INT) {
01372 for (int i=num-1; i>=0; i--) {
01373 sprintf(s, "%ld", (long) ival[i]);
01374 tmp[i] = strdup(s);
01375 }
01376 } else {
01377 for (int i=num-1; i>=0; i--) {
01378 sprintf(s, "%f", (double) dval[i]);
01379 tmp[i] = strdup(s);
01380 }
01381 }
01382 free_space();
01383 type = totype;
01384 sval = tmp;
01385 free_sval = TRUE;
01386 return;
01387 }
01388
01389
01390 if (totype == SymbolTableElement::IS_INT) {
01391 int *tmp = new int[num];
01392 if (type == SymbolTableElement::IS_FLOAT) {
01393 for (int i=num-1; i>=0; i--) {
01394 tmp[i] = (int) dval[i];
01395 }
01396 } else {
01397 for (int i=num-1; i>=0; i--) {
01398
01399
01400
01401
01402
01403
01404
01405
01406 if (sval[i] != NULL) {
01407 tmp[i] = atoi(sval[i]);
01408 } else {
01409 for (int j=num-1; j>=0; j--) {
01410 tmp[i] = 0;
01411 }
01412 msgErr << "ParseTree) internal processing error, NULL string value "
01413 << "while converting to integer" << sendmsg;
01414 break;
01415 }
01416 }
01417 }
01418 free_space();
01419 type = totype;
01420 ival = tmp;
01421 return;
01422 }
01423 }
01424