Revision: 20432
          http://sourceforge.net/p/jmol/code/20432
Author:   hansonr
Date:     2015-04-05 03:33:28 +0000 (Sun, 05 Apr 2015)
Log Message:
-----------
Jmol.___JmolVersion="14.3.13_2015.04.05" 

code: rewriting FOR loop code to enhance performance

new feature: for (var i FROM [a, b]) {...}
  -- same as for (var i = a; i <= b; i++) when a < b
  -- same as for (var i = a; i >= b; i--) when a > b
  -- much more efficient

bug fix: for (var i in hashArray) {....}  broken (also in 14.2; not fixed there)

Modified Paths:
--------------
    trunk/Jmol/src/org/jmol/script/ContextToken.java
    trunk/Jmol/src/org/jmol/script/ScriptEval.java
    trunk/Jmol/src/org/jmol/viewer/Jmol.properties

Modified: trunk/Jmol/src/org/jmol/script/ContextToken.java
===================================================================
--- trunk/Jmol/src/org/jmol/script/ContextToken.java    2015-04-03 01:41:00 UTC 
(rev 20431)
+++ trunk/Jmol/src/org/jmol/script/ContextToken.java    2015-04-05 03:33:28 UTC 
(rev 20432)
@@ -28,7 +28,7 @@
 
 class ContextToken extends T {
   Map<String, SV> contextVariables;
-
+  SV[] loopVars;
   static ContextToken newContext(boolean isOpen) {
     ContextToken ct = (isOpen ? newCmd(T.push, "{") : newCmd(T.pop, "}"));
     ct.intValue = 0;

Modified: trunk/Jmol/src/org/jmol/script/ScriptEval.java
===================================================================
--- trunk/Jmol/src/org/jmol/script/ScriptEval.java      2015-04-03 01:41:00 UTC 
(rev 20431)
+++ trunk/Jmol/src/org/jmol/script/ScriptEval.java      2015-04-05 03:33:28 UTC 
(rev 20432)
@@ -2088,7 +2088,14 @@
       lineEnd = Integer.MAX_VALUE;
     if (aatoken == null)
       return true;
-    boolean allowJSInterrupt = (isJS && !fromFunc && useThreads());
+    if (!tQuiet) {
+      tQuiet = (vwr.getInt(T.showscript) < 0);
+    }
+    boolean allowJSInterrupt = (
+        isJS 
+        && !fromFunc 
+        && useThreads() 
+        && vwr.getInt(T.showscript) >= 0);
     commandLoop(allowJSInterrupt);
     if (chk)
       return true;
@@ -2108,7 +2115,7 @@
     return true;
   }
 
-  private void commandLoop(boolean allowInterrupt) throws ScriptException {
+  private void commandLoop(boolean allowJSInterrupt) throws ScriptException {
     String lastCommand = "";
     boolean isForCheck = false; // indicates the stage of the for command loop
     Lst<T[]> vProcess = null;
@@ -2124,7 +2131,7 @@
     }
 
     for (; pc < aatoken.length && pc < pcEnd; pc++) {
-      if (allowInterrupt) {
+      if (allowJSInterrupt) {
         // every 1 s check for interruptions
         if (!executionPaused && System.currentTimeMillis() - lastTime > 1000) {
           pc--;
@@ -2144,7 +2151,8 @@
       }
 
       if (debugScript && !chk)
-        Logger.info("Command " + pc + (thisContext == null ? "" : " path=" + 
thisContext.contextPath));
+        Logger.info("Command " + pc
+            + (thisContext == null ? "" : " path=" + thisContext.contextPath));
       theToken = (aatoken[pc].length == 0 ? null : aatoken[pc][0]);
       // when checking scripts, we can't check statments
       // containing @{...}
@@ -2158,7 +2166,7 @@
                 .tokAttr(theToken.tok, T.flowCommand)))
           vwr.addCommand(lastCommand = cmdLine);
       }
-      if (!chk) {
+      if (!chk && allowJSInterrupt) {
         String script = vwr.getInsertedCommand();
         if (!"".equals(script))
           runScript(script);
@@ -2206,28 +2214,38 @@
       if (theToken == null)
         continue;
       int tok = theToken.tok;
-      if (T.tokAttr(tok, T.flowCommand)) {
-        isForCheck = cmdFlow(tok, isForCheck, vProcess);
-        if (theTok == T.process)
-          vProcess = null; // "end process"        
-      } else if (tok == T.process){
+      switch (tok) {
+      case T.set:
+        cmdSet();
+        continue;
+      case T.forcmd:
+        isForCheck = cmdFor(tok, isForCheck);
+        continue;
+      case T.process:
         pushContext((ContextToken) theToken, "PROCESS");
         if (parallelProcessor != null)
           vProcess = new Lst<T[]>();
-      } else {
+        continue;
+      default:
+        if (T.tokAttr(tok, T.flowCommand)) {
+          isForCheck = cmdFlow(tok, isForCheck, vProcess);
+          if (theTok == T.process)
+            vProcess = null; // "end process"
+          continue;
+        }
         processCommand(tok);
+        setCursorWait(false);
+        if (executionStepping) {
+          executionPaused = (isCommandDisplayable(pc + 1));
+        }
       }
-      setCursorWait(false);
-      // at end because we could use continue to avoid it
-      if (executionStepping) {
-        executionPaused = (isCommandDisplayable(pc + 1));
-      }
     }
   }
 
-  public void terminateAfterStep() {
-    pc = pcEnd;
-  }
+//  public void terminateAfterStep() {
+//    pc = pcEnd;
+//  }
+  
   private void processCommand(int tok) throws ScriptException {
     if (T.tokAttr(theToken.tok, T.shapeCommand)) {
       processShapeCommand(tok);
@@ -2408,9 +2426,6 @@
     case T.save:
       cmdSave();
       break;
-    case T.set:
-      cmdSet();
-      break;
     case T.script:
       cmdScript(T.script, null, null);
       break;
@@ -3387,13 +3402,199 @@
     vwr.setMotionFixedAtoms(bs);
   }
 
+  @SuppressWarnings("unchecked")
+  private boolean cmdFor(int tok, boolean isForCheck) throws ScriptException {
+    ContextToken cmdToken = (ContextToken) theToken;
+    int pt = st[0].intValue;
+    SV[] loopVars = cmdToken.loopVars;
+    pt = st[0].intValue;
+    int[] pts = new int[2];
+    Object bsOrList = null;
+    SV forVal = null;
+    SV forVar = null;
+    int inTok = 0;
+    boolean isOK = true;
+    boolean isMinusMinus = false;
+    int j = 0;
+    String key = null;
+    if (isForCheck && loopVars != null) {
+      tok = T.in;
+      // i in x, already initialized
+      forVar = loopVars[0];
+      forVal = loopVars[1];
+      bsOrList = loopVars[1].value;
+      // nth time through
+      j = ++forVal.intValue;
+      if (forVar.isModified()) {
+        isOK = false;
+      } else if (forVal.tok == T.integer) {
+        // values are stored in value as [i1 i2]
+        isMinusMinus = (j < 0);
+        int i1 = ((int[]) bsOrList)[0];
+        int i2 = ((int[]) bsOrList)[1];
+        isOK = (i1 != i2 && (i2 < i1) == isMinusMinus);
+        if (isOK)
+          forVar.intValue = ((int[]) bsOrList)[0] = i1 + (isMinusMinus ? -1 : 
1); 
+        j = -1;
+      } else if (forVal.tok == T.varray) {
+        isOK = (j <= ((Lst<SV>) bsOrList).size());
+        if (isOK)
+          forVar.setv(SV.selectItemVar(forVal));
+        j = -1;
+      } else {
+        isBondSet = bsOrList instanceof BondSet;
+        j = ((BS) bsOrList).nextSetBit(j);
+        isOK = (j >= 0);
+      }
+    } else {
+
+      // for (i = 1; i < 3; i = i + 1);
+      // for (var i = 1; i < 3; i = i + 1);
+      // for (;;;);
+      // for (var x in {...}) { xxxxx }
+      // for (var x in y) { xxxx }
+      for (int i = 1, nSkip = 0; i < slen && j < 2; i++) {
+        switch (tok = tokAt(i)) {
+        case T.semicolon:
+          if (nSkip > 0)
+            nSkip--;
+          else
+            pts[j++] = i;
+          break;
+        case T.in:
+        case T.from:
+          key = paramAsStr(i - 1);
+          nSkip -= 2;
+          if (tokAt(++i) == T.expressionBegin || tokAt(i) == T.bitset) {
+            inTok = T.bitset;
+            bsOrList = atomExpressionAt(i);
+            if (isBondSet)
+              bsOrList = BondSet.newBS((BS) bsOrList, null);
+            isOK = (((BS) bsOrList).nextSetBit(0) >= 0);
+          } else {
+            Lst<SV> what = parameterExpressionList(-i, 1, false);
+            if (what == null || what.size() < 1)
+              invArg();
+            SV vl = what.get(0);
+            switch (inTok = vl.tok) {
+            case T.bitset:
+              bsOrList = SV.getBitSet(vl, false);
+              isOK = (((BS) bsOrList).nextSetBit(0) >= 0);
+              break;
+            case T.varray:
+              Lst<SV> v = vl.getList();
+              j = v.size();
+              isOK = (j > 0);
+              if (isOK && tok == T.from) {
+                int[] i12 = new int[] {SV.iValue(v.get(0)), SV.iValue(v.get(j 
- 1)) };
+                isMinusMinus = (i12[1] < i12[0]);
+                bsOrList = i12;
+                tok = T.in;
+                inTok = T.integer;
+              } else {
+                bsOrList = v;
+              }
+              break;
+            case T.hash:
+              Map<String, SV> m = vl.getMap();
+              int n = m.keySet().size();
+              isOK = (n > 0);
+              if (isOK) {
+                String[] keys = new String[n];
+                m.keySet().toArray(keys);
+                Arrays.sort(keys);
+                bsOrList = keys;
+              }
+              break;
+            default:
+              invArg();
+            }
+          }
+          i = iToken;
+          break;
+        case T.select:
+          nSkip += 2;
+          break;
+        }
+      }
+      if (key == null) {
+        if (isForCheck) {
+          j = (bsOrList == null ? pts[1] + 1 : 2);
+        } else {
+          pushContext(cmdToken, "FOR");
+          j = 2;
+        }
+        if (tokAt(j) == T.var)
+          j++;
+        key = paramAsStr(j);
+        isMinusMinus = key.equals("--") || key.equals("++");
+        if (isMinusMinus)
+          key = paramAsStr(++j);
+      }
+      if (isOK)
+        if (tok == T.in) {
+          // start of FOR (i in x) block
+          pushContext(cmdToken, "FOR");
+          forVar = getForVar(key);
+          forVar.setModified(false);
+          if (inTok == T.integer) {
+            // for (i from [0 31])
+            forVar.tok = T.integer;
+            forVar.intValue = ((int[]) bsOrList)[0];
+            forVal = SV.newV(T.integer, bsOrList);
+            forVal.intValue = (isMinusMinus ? Integer.MIN_VALUE : 0);
+            j = -1;
+          } else {
+            forVal = SV.getVariable(bsOrList);
+            if (inTok == T.bitset) {
+              j = ((BS) bsOrList).nextSetBit(0);
+            } else {
+              forVal.intValue = 1;
+              forVar.setv(SV.selectItemVar(forVal));
+              j = -1;
+            }
+          }
+          if (loopVars == null)
+            loopVars = cmdToken.loopVars = new SV[2];
+          loopVars[0] = forVar;
+          loopVars[1] = forVal;
+        } else {
+          if (T.tokAttr(tokAt(j), T.misc)
+              || (forVal = getContextVariableAsVariable(key)) != null) {
+            if (!isMinusMinus && getToken(++j).tok != T.opEQ)
+              invArg();
+            if (isMinusMinus)
+              j -= 2;
+            setVariable(++j, slen - 1, key, false);
+          }
+          isOK = parameterExpressionBoolean(pts[0] + 1, pts[1]);
+        }
+    }
+    if (isOK && tok == T.in && j >= 0) {
+      forVal.intValue = j;
+      forVar.tok = T.bitset;
+      if (isBondSet) {
+        forVar.value = new BondSet();
+        ((BondSet) forVar.value).set(j);
+      } else {
+        forVar.value = BSUtil.newAndSetBit(j);
+      }
+    }
+    pt++;
+    if (!isOK)
+      popContext(true, false);
+    isForCheck = false;
+    if (!isOK && !chk)
+      pc = Math.abs(pt) - 1;
+    return isForCheck;
+  }
+
   private boolean cmdFlow(int tok, boolean isForCheck, Lst<T[]> vProcess)
       throws ScriptException {
     ContextToken ct;
-    int pt;
-    pt = st[0].intValue;
+    int pt = st[0].intValue;
     boolean isDone = (pt < 0 && !chk);
-    boolean isOK = true;
+    boolean continuing = true;
     int ptNext = 0;
     switch (tok) {
     case T.function:
@@ -3407,7 +3608,7 @@
       pushContext(ct, "CATCH");
       if (!isDone && ct.name0 != null)
         contextVariables.put(ct.name0, ct.contextVariables.get(ct.name0));
-      isOK = !isDone;
+      continuing = !isDone;
       st[0].intValue = -Math.abs(pt);
       break;
     case T.switchcmd:
@@ -3418,11 +3619,11 @@
       case 0:
         // done
         ptNext = -ptNext;
-        isOK = false;
+        continuing = false;
         break;
       case -1:
         // skip this case
-        isOK = false;
+        continuing = false;
         break;
       case 1:
         // do this one
@@ -3434,11 +3635,11 @@
       break;
     case T.ifcmd:
     case T.elseif:
-      isOK = (!isDone && parameterExpressionBoolean(1, 0));
+      continuing = (!isDone && parameterExpressionBoolean(1, 0));
       if (chk)
         break;
       ptNext = Math.abs(aatoken[Math.abs(pt)][0].intValue);
-      ptNext = (isDone || isOK ? -ptNext : ptNext);
+      ptNext = (isDone || continuing ? -ptNext : ptNext);
       aatoken[Math.abs(pt)][0].intValue = ptNext;
       if (tok == T.catchcmd)
         aatoken[pc][0].intValue = -pt; // reset to "done" state
@@ -3480,122 +3681,6 @@
       if (slen > 1)
         intParameter(checkLast(1));
       break;
-    case T.forcmd:
-      // for (i = 1; i < 3; i = i + 1);
-      // for (var i = 1; i < 3; i = i + 1);
-      // for (;;;);
-      // for (var x in {...}) { xxxxx }
-      // for (var x in y) { xxxx }
-      T cmdToken = theToken;
-      int[] pts = new int[2];
-      int j = 0;
-      Object bsOrList = null;
-      String key = null;
-      for (int i = 1, nSkip = 0; i < slen && j < 2; i++) {
-        switch (tok = tokAt(i)) {
-        case T.semicolon:
-          if (nSkip > 0)
-            nSkip--;
-          else
-            pts[j++] = i;
-          break;
-        case T.in:
-          key = paramAsStr(i - 1);
-          if (isForCheck) {
-            i = slen;
-            continue;
-          }
-          nSkip -= 2;
-          if (tokAt(++i) == T.expressionBegin || tokAt(i) == T.bitset) {
-            bsOrList = atomExpressionAt(i);
-            if (isBondSet)
-              bsOrList = BondSet.newBS((BS) bsOrList, null);
-          } else {
-            Lst<SV> what = parameterExpressionList(-i, 1, false);
-            if (what == null || what.size() < 1)
-              invArg();
-            SV vl = what.get(0);
-            switch (vl.tok) {
-            case T.bitset:
-              bsOrList = SV.getBitSet(vl, false);
-              break;
-            case T.varray:
-              bsOrList = vl.getList();
-              break;
-            case T.hash:
-              Map<String, SV> m = vl.getMap();
-              String[] keys = new String[m.keySet().size()];
-              Arrays.sort(keys);
-              bsOrList = m.keySet().toArray(keys);
-              break;
-            default:
-              invArg();
-            }
-          }
-          i = iToken;
-          break;
-        case T.select:
-          nSkip += 2;
-          break;
-        }
-      }
-      boolean isMinusMinus = false;
-      if (key == null) {
-        if (isForCheck) {
-          j = (bsOrList == null ? pts[1] + 1 : 2);
-        } else {
-          pushContext((ContextToken) cmdToken, "FOR");
-          j = 2;
-        }
-        if (tokAt(j) == T.var)
-          j++;
-        key = paramAsStr(j);
-        isMinusMinus = key.equals("--") || key.equals("++");
-        if (isMinusMinus)
-          key = paramAsStr(++j);
-      }
-      SV v = null;
-      if (tok == T.in || T.tokAttr(tokAt(j), T.misc)
-          || (v = getContextVariableAsVariable(key)) != null) {
-        if (tok != T.in && !isMinusMinus && getToken(++j).tok != T.opEQ)
-          invArg();
-        if (tok == T.in) {
-          isOK = true;
-          if (!isForCheck)
-            pushContext((ContextToken) cmdToken, "FOR");
-          SV t = getForVar(key);
-          v = getForVar(key + "/value");
-          if (isForCheck) {
-            if (t.isModified())
-              isOK = false;
-            else if (v.tok == T.varray)
-              isOK = (++v.intValue <= v.getList().size());
-            else if (((BS) v.value).nextSetBit((j = ((BS) v.value)
-                .nextSetBit(0)) + 1) < 0)
-              isOK = false;
-            else
-              ((BS) v.value).clear(j);
-          } else {
-            v.setv(SV.getVariable(bsOrList instanceof BS ? BSUtil
-                .copy((BS) bsOrList) : bsOrList));
-            v.intValue = 1;
-            t.setModified(false);
-          }
-          if (isOK)
-            t.setv(SV.selectItemVar(v));
-        } else {
-          if (isMinusMinus)
-            j -= 2;
-          setVariable(++j, slen - 1, key, false);
-        }
-      }
-      if (tok != T.in)
-        isOK = parameterExpressionBoolean(pts[0] + 1, pts[1]);
-      pt++;
-      if (!isOK)
-        popContext(true, false);
-      isForCheck = false;
-      break;
     case T.end: // function, if, for, while, catch, switch
       switch (getToken(checkLast(1)).tok) {
       case T.trycmd:
@@ -3604,13 +3689,13 @@
           return false;
         runFunctionAndRet(trycmd, "try", null, null, true, true, true);
         return false;
-      case T.catchcmd:
-        popContext(true, false);
-        break;
       case T.function:
       case T.parallel:
         vwr.addFunction((ScriptFunction) theToken.value);
         return isForCheck;
+      case T.catchcmd:
+        popContext(true, false);
+        break;
       case T.process:
         addProcess(vProcess, pt, pc);
         popContext(true, false);
@@ -3621,17 +3706,20 @@
           for (; pt < pc; pt++)
             if ((tok = aatoken[pt][0].tok) != T.defaultcmd && tok != T.casecmd)
               break;
-          isOK = (pc == pt);
+          continuing = (pc == pt);
         }
         break;
+      case T.ifcmd:
+        break;
+      case T.forcmd:
+      case T.whilecmd:
+        continuing = false;
+        isForCheck = true;
+        break;
       }
-      if (isOK)
-        isOK = (theTok == T.catchcmd || theTok == T.process
-            || theTok == T.ifcmd || theTok == T.switchcmd);
-      isForCheck = (theTok == T.forcmd || theTok == T.whilecmd);
       break;
     }
-    if (!isOK && !chk)
+    if (!continuing && !chk)
       pc = Math.abs(pt) - 1;
     return isForCheck;
   }

Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2015-04-03 01:41:00 UTC 
(rev 20431)
+++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2015-04-05 03:33:28 UTC 
(rev 20432)
@@ -14,8 +14,19 @@
 
 TODO: remove HTML5 dependency on synchronous file loading (check SCRIPT 
command for problems)
 
-Jmol.___JmolVersion="14.3.13_2015.04.02" 
+Jmol.___JmolVersion="14.3.13_2015.04.05" 
 
+code: rewriting FOR loop code to enhance performance
+
+new feature: for (var i FROM [a, b]) {...}
+  -- same as for (var i = a; i <= b; i++) when a < b
+  -- same as for (var i = a; i >= b; i--) when a > b
+  -- much more efficient
+
+bug fix: for (var i in hashArray) {....}  broken (also in 14.2; not fixed 
there)
+
+JmolVersion="14.3.13_2015.04.02" 
+
 bug fix: [3 4 5].min should give integer 3, not decimal 3.0 (same with .max)
 
 JmolVersion="14.3.13_2015.04.01b" 

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
Jmol-commits mailing list
Jmol-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jmol-commits

Reply via email to