@@ -692,13 +692,18 @@ static WordKeyValue Keyword[] = {
692692#define SCMP_LTHN 0x02
693693#define SCMP_RANG 0x03
694694#define SCMP_EQAL 0x04
695+ #define SCMP_GEQL 0x05
696+ #define SCMP_LEQL 0x06
695697
696698static WordKeyValue AtOper[] = {
697699 {" >" , SCMP_GTHN},
698700 {" <" , SCMP_LTHN},
699701 {" in" , SCMP_RANG},
700702 {" =" , SCMP_EQAL},
701- {" " , 0 }
703+ {" ==" , SCMP_EQAL},
704+ {" >=" , SCMP_GEQL},
705+ {" <=" , SCMP_LEQL},
706+ {" " , 0 },
702707};
703708
704709static short fcmp (float a, float b, int oper) {
@@ -709,6 +714,10 @@ static short fcmp(float a, float b, int oper) {
709714 return (a < b);
710715 case SCMP_EQAL:
711716 return fabs (a - b) < R_SMALL4;
717+ case SCMP_GEQL:
718+ return (a >= b);
719+ case SCMP_LEQL:
720+ return (a <= b);
712721 }
713722 printf (" ERROR: invalid operator %d\n " , oper);
714723 return false ;
@@ -8443,109 +8452,116 @@ static int SelectorSelect2(PyMOLGlobals * G, EvalElem * base, int state)
84438452 base->sele_calloc (I->Table .size ());
84448453 base->sele_err_chk_ptr (G);
84458454 switch (base->code ) {
8446- case SELE_XVLx:
8447- case SELE_YVLx:
8448- case SELE_ZVLx:
8449- oper = WordKey (G, AtOper, base[1 ].text (), 4 , ignore_case, &exact);
8450- switch (oper) {
8451- case SCMP_GTHN:
8452- case SCMP_LTHN:
8453- case SCMP_EQAL:
8454- if (sscanf (base[2 ].text (), " %f" , &comp1) != 1 )
8455- ok = ErrMessage (G, " Selector" , " Invalid Number" );
8456- break ;
8457- default :
8458- ok = ErrMessage (G, " Selector" , " Invalid Operator." );
8459- break ;
8460- }
8461- if (ok) {
8462- ObjectMolecule *obj;
8463- CoordSet *cs;
8464- int at, idx, s, s0 = 0 , sN = I->NCSet ;
8465-
8466- if (state != cStateAll) {
8467- s0 = (state < cStateAll) ? SceneGetState (G) : state;
8468- sN = s0 + 1 ;
8455+ case SELE_XVLx:
8456+ case SELE_YVLx:
8457+ case SELE_ZVLx:
8458+ oper = WordKey (G, AtOper, base[1 ].text (), 4 , ignore_case, &exact);
8459+ switch (oper) {
8460+ case SCMP_GTHN:
8461+ case SCMP_LTHN:
8462+ case SCMP_EQAL:
8463+ case SCMP_GEQL:
8464+ case SCMP_LEQL:
8465+ if (sscanf (base[2 ].text (), " %f" , &comp1) != 1 )
8466+ ok = ErrMessage (G, " Selector" , " Invalid Number" );
8467+ break ;
8468+ default :
8469+ ok = ErrMessage (G, " Selector" , " Invalid Operator." );
8470+ break ;
84698471 }
84708472
8471- for (a = cNDummyAtoms; a < I->Table .size (); a++)
8472- base[0 ].sele [a] = false ;
8473+ if (ok) {
8474+ ObjectMolecule *obj;
8475+ CoordSet *cs;
8476+ int at, idx, s, s0 = 0 , sN = I->NCSet ;
84738477
8474- for (s = s0; s < sN ; s++ ) {
8475- for (a = cNDummyAtoms; a < I-> Table . size (); a++) {
8476- if (base[ 0 ]. sele [a])
8477- continue ;
8478+ if (state != cStateAll ) {
8479+ s0 = (state < cStateAll) ? SceneGetState (G) : state;
8480+ sN = s0 + 1 ;
8481+ }
84788482
8479- obj = I->Obj [I->Table [a].model ];
8480- if (s >= obj->NCSet )
8481- continue ;
8483+ for (s = s0; s < sN ; s++) {
8484+ for (a = cNDummyAtoms; a < I->Table .size (); a++) {
8485+ if (base[0 ].sele [a])
8486+ continue ;
84828487
8483- at = I->Table [a].atom ;
8484- cs = obj->CSet [s];
8485- idx = cs->atmToIdx (at);
8486- if (idx < 0 )
8487- continue ;
8488+ obj = I->Obj [I->Table [a].model ];
8489+ if (s >= obj->NCSet )
8490+ continue ;
84888491
8489- idx *= 3 ;
8490- switch (base->code ) {
8491- case SELE_ZVLx:
8492- idx++;
8493- case SELE_YVLx:
8494- idx++;
8495- }
8492+ at = I->Table [a].atom ;
8493+ cs = obj->CSet [s];
8494+ idx = cs->atmToIdx (at);
8495+ if (idx < 0 )
8496+ continue ;
8497+
8498+ idx *= 3 ;
8499+ switch (base->code ) {
8500+ case SELE_ZVLx:
8501+ idx++;
8502+ case SELE_YVLx:
8503+ idx++;
8504+ case SELE_XVLx:
8505+ break ;
8506+ }
84968507
8497- base[0 ].sele [a] = fcmp (cs->Coord [idx], comp1, oper);
8508+ if (fcmp (cs->Coord [idx], comp1, oper)) {
8509+ base[0 ].sele [a] = true ;
8510+ } else {
8511+ base[0 ].sele [a] = false ;
8512+ }
8513+ }
84988514 }
84998515 }
8500- }
8501- break ;
8502- case SELE_PCHx:
8503- case SELE_FCHx:
8504- case SELE_BVLx:
8505- case SELE_QVLx:
8506- oper = WordKey (G, AtOper, base[1 ].text (), 4 , ignore_case, &exact);
8507- if (!oper) {
8508- ok = ErrMessage (G, " Selector" , " Invalid Operator." );
85098516 break ;
8510- }
8511- switch (oper) {
8512- case SCMP_GTHN:
8513- case SCMP_LTHN:
8514- case SCMP_EQAL:
8515- if (sscanf (base[2 ].text (), " %f" , &comp1) != 1 )
8516- ok = ErrMessage (G, " Selector" , " Invalid Number" );
8517+ case SELE_PCHx:
8518+ case SELE_FCHx:
8519+ case SELE_BVLx:
8520+ case SELE_QVLx:
8521+ oper = WordKey (G, AtOper, base[1 ].text (), 4 , ignore_case, &exact);
8522+ if (!oper) {
8523+ ok = ErrMessage (G, " Selector" , " Invalid Operator." );
8524+ break ;
85178525 }
8518- break ;
8519- default :
8520- ok = ErrMessage (G, " Selector" , " Invalid Operator." );
8521- break ;
8522- }
8523-
8524- if (ok) {
8525- for (a = cNDummyAtoms; a < I->Table .size (); a++) {
8526- at1 = I->Obj [I->Table [a].model ]->AtomInfo + I->Table [a].atom ;
8527- float atomValue;
8528- switch (base->code ) {
8529- case SELE_BVLx: atomValue = at1->bval ; break ;
8530- case SELE_PCHx: atomValue = at1->partialCharge ; break ;
8531- case SELE_FCHx: atomValue = at1->formalCharge ; break ;
8532- case SELE_QVLx: atomValue = at1->qval ; break ;
8533- default : {
8534- ErrMessage (G, " Selector" , " Invalid Operand." );
8535- return false ;
8536- }
8537- }
8538-
8539- if (fcmp (atomValue, comp1, oper)) {
8540- base[0 ].sele [a] = true ;
8541- c++;
8542- } else {
8543- base[0 ].sele [a] = false ;
8526+ switch (oper) {
8527+ case SCMP_GTHN:
8528+ case SCMP_LTHN:
8529+ case SCMP_EQAL:
8530+ case SCMP_GEQL:
8531+ case SCMP_LEQL:
8532+ if (sscanf (base[2 ].text (), " %f" , &comp1) != 1 )
8533+ ok = ErrMessage (G, " Selector" , " Invalid Number" );
8534+ break ;
8535+ default :
8536+ ok = ErrMessage (G, " Selector" , " Invalid Operator." );
8537+ break ;
8538+ }
8539+
8540+ if (ok) {
8541+ for (a = cNDummyAtoms; a < I->Table .size (); a++) {
8542+ at1 = I->Obj [I->Table [a].model ]->AtomInfo + I->Table [a].atom ;
8543+ float atomValue;
8544+ switch (base->code ) {
8545+ case SELE_BVLx: atomValue = at1->b ; break ;
8546+ case SELE_PCHx: atomValue = at1->partialCharge ; break ;
8547+ case SELE_FCHx: atomValue = at1->formalCharge ; break ;
8548+ case SELE_QVLx: atomValue = at1->q ; break ;
8549+ default : {
8550+ ErrMessage (G, " Selector" , " Invalid Operand." );
8551+ return false ;
8552+ }
8553+ }
8554+
8555+ if (fcmp (atomValue, comp1, oper)) {
8556+ base[0 ].sele [a] = true ;
8557+ c++;
8558+ } else {
8559+ base[0 ].sele [a] = false ;
8560+ }
85448561 }
85458562 }
8563+ break ;
85468564 }
8547- break ;
8548-
85498565
85508566 PRINTFD (G, FB_Selector)
85518567 " %s: %d atoms selected.\n " , __func__, c ENDFD;
@@ -9912,11 +9928,20 @@ std::vector<std::string> SelectorParse(PyMOLGlobals * G, const char *s)
99129928 case ' |' :
99139929 case ' (' :
99149930 case ' )' :
9931+ case ' %' :
9932+ r.emplace_back (1 , *p); /* add new word */
9933+ q = &r.back ();
9934+ w_flag = false ;
9935+ break ;
99159936 case ' >' :
99169937 case ' <' :
99179938 case ' =' :
9918- case ' %' :
9919- r.emplace_back (1 , *p); /* add new word */
9939+ if (*(p+1 ) == ' =' ) { /* handle >=, <=, == */
9940+ r.emplace_back (p, 2 );
9941+ p++;
9942+ } else {
9943+ r.emplace_back (1 , *p);
9944+ }
99209945 q = &r.back ();
99219946 w_flag = false ;
99229947 break ;
@@ -9936,13 +9961,22 @@ std::vector<std::string> SelectorParse(PyMOLGlobals * G, const char *s)
99369961 case ' |' :
99379962 case ' (' :
99389963 case ' )' :
9939- case ' >' :
9940- case ' <' :
9941- case ' =' :
99429964 case ' %' :
99439965 r.emplace_back (1 , *p); /* add new word */
99449966 q = &r.back ();
99459967 break ;
9968+ case ' >' :
9969+ case ' <' :
9970+ case ' =' :
9971+ if (*(p+1 ) == ' =' ) { /* handle >=, <=, == */
9972+ r.emplace_back (p, 2 );
9973+ p++;
9974+ } else {
9975+ r.emplace_back (1 , *p);
9976+ }
9977+ q = &r.back ();
9978+ w_flag = false ;
9979+ break ;
99469980 case ' ' :
99479981 break ;
99489982 case ' "' :
0 commit comments