Use ordinal pre-sorting rather than on-the-fly compares
[sbp.git] / src / edu / berkeley / sbp / Reduction.java
index e845764..684fbf8 100644 (file)
@@ -22,6 +22,7 @@ final class Reduction implements Comparable<Reduction> {
         this.result = result;
         this.phase = target;
         this.node = node;
+        target.reductionQueue.add(this);
     }
 
     public void perform() {
@@ -30,36 +31,30 @@ final class Reduction implements Comparable<Reduction> {
         node.finish(position, result, phase);
     }
 
-    public String toString() { return position+""; }
-
     public int compareTo(Reduction r) {
         int ret = compareTo0(r);
-        if (ret == 0) {
-            Walk.Cache cache = node.state().cache();
-            if (canKill(cache, position, r.position) && canKill(cache, r.position, position)) throw new Error();
-            if      (canKill(cache, position,   r.position)) ret =  1;
-            else if (canKill(cache, r.position, position)) ret = -1;
-            if      (canNeed(cache, position,   r.position)) ret =  1;
-            else if (canNeed(cache, r.position, position)) ret = -1;
-        }
-        return -1 * ret;
+        if (ret != 0) return -1 * ret;
+        return (position.ord - r.position.ord);
     }
 
-    private boolean isRightNullable(Walk.Cache c, Position p) {
+    private static boolean isRightNullable(Walk.Cache c, Position p) {
         if (p.isLast()) return true;
         if (!c.possiblyEpsilon(p.element())) return false;
         return isRightNullable(c, p.next());
     }
 
-    public boolean canKill(Walk.Cache cache, Position mep, Position himp) {
+    public static boolean canKill(Walk.Cache cache, Position mep, Position himp) {
         if (!isRightNullable(cache, mep))  return false;
         if (!isRightNullable(cache, himp)) return false;
         Sequence me  = mep.owner();
         Sequence him = himp.owner();
+        Boolean b = me.canKill.get(him);
+        if (b!=null) return b;
         for(Sequence killer : him.hates()) {
             HashSet<Sequence> eq2 = new Walk.EquivalentTo(killer, cache).walk();
-            if (eq2.contains(me)) return true;
+            if (eq2.contains(me)) { me.canKill.put(him, true); return true; }
         }
+        me.canKill.put(him, false);
         return false;
     }
 
@@ -78,15 +73,18 @@ final class Reduction implements Comparable<Reduction> {
     public int pos() { return targetPhase()==null ? 0 : targetPhase().pos; }
     public GSS.Phase targetPhase() { return node.phase(); }
 
-    public boolean canNeed(Walk.Cache cache, Position mep, Position himp) {
+    public static boolean canNeed(Walk.Cache cache, Position mep, Position himp) {
         if (!isRightNullable(cache, mep))  return false;
         if (!isRightNullable(cache, himp)) return false;
         Sequence me  = mep.owner();
         Sequence him = himp.owner();
+        Boolean b = me.canNeed.get(him);
+        if (b!=null) return b;
         for(Sequence needer : him.needs()) {
             HashSet<Sequence> eq2 = new Walk.EquivalentTo(needer, cache).walk();
-            if (eq2.contains(me)) return true;
+            if (eq2.contains(me)) { me.canNeed.put(him, true); return true; }
         }
+        me.canNeed.put(him, false);
         return false;
     }
 }