Browse Source

*** empty log message ***

David Rose 25 năm trước cách đây
mục cha
commit
d9abbba095

+ 3 - 1
panda/src/graph/allTransitionsWrapper.I

@@ -340,7 +340,9 @@ set_computed_verified(UpdateSeq now) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AllTransitionsWrapper::cached_compose
 //     Function: AllTransitionsWrapper::cached_compose
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Computes the composition of this wrapper's value with
+//               that indicated by value, using the cache as a helper,
+//               and stores the result in this wrapper.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void AllTransitionsWrapper::
 INLINE void AllTransitionsWrapper::
 cached_compose(const AllTransitionsWrapper &cache, 
 cached_compose(const AllTransitionsWrapper &cache, 

+ 17 - 7
panda/src/graph/nodeTransitionCacheEntry.I

@@ -274,7 +274,8 @@ invert_compose(const NodeTransitionCacheEntry &a,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodeTransitionCacheEntry::cached_compose
 //     Function: NodeTransitionCacheEntry::cached_compose
 //       Access: Public, Static
 //       Access: Public, Static
-//  Description: 
+//  Description: Sets this cache entry to the result of compose(a, b),
+//               as computed using the cache value as a hint.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE NodeTransitionCacheEntry NodeTransitionCacheEntry::
 INLINE NodeTransitionCacheEntry NodeTransitionCacheEntry::
 cached_compose(const NodeTransitionCacheEntry &a, 
 cached_compose(const NodeTransitionCacheEntry &a, 
@@ -282,8 +283,8 @@ cached_compose(const NodeTransitionCacheEntry &a,
 	       const NodeTransitionCacheEntry &b,
 	       const NodeTransitionCacheEntry &b,
 	       UpdateSeq now) {
 	       UpdateSeq now) {
 #ifndef NDEBUG
 #ifndef NDEBUG
-  if (wrt_cat.is_debug()) {
-    wrt_cat.debug()
+  if (wrt_cat.is_spam()) {
+    wrt_cat.spam()
       << "Composing:\n"
       << "Composing:\n"
       << "     a) " << a << " = " << a._computed << "\n"
       << "     a) " << a << " = " << a._computed << "\n"
       << " cache) " << cache << " = " << cache._computed << "\n"
       << " cache) " << cache << " = " << cache._computed << "\n"
@@ -291,22 +292,31 @@ cached_compose(const NodeTransitionCacheEntry &a,
   }
   }
 #endif
 #endif
   if (cache._computed == UpdateSeq::initial() ||
   if (cache._computed == UpdateSeq::initial() ||
+      (a._computed == UpdateSeq::initial() && 
+       b._computed == UpdateSeq::initial()) ||
       cache._computed < a._computed) {
       cache._computed < a._computed) {
+
+    // If the cache value has not yet been computed, or if the values
+    // in a and b are both empty, or if the cache is older than the
+    // source value (a), discard the cache and compute the composition
+    // directly.
     NodeTransitionCacheEntry result = compose(a, b);
     NodeTransitionCacheEntry result = compose(a, b);
     result.set_computed_verified(now);
     result.set_computed_verified(now);
 #ifndef NDEBUG
 #ifndef NDEBUG
-    if (wrt_cat.is_debug()) {
-      wrt_cat.debug() << "computed result is " << result << "\n";
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam() << "computed result is " << result << "\n";
     }
     }
 #endif
 #endif
     return result;
     return result;
 
 
   } else {
   } else {
+    // Otherwise, the cache value is recent and we can simply use it
+    // directly.
     NodeTransitionCacheEntry result = cache;
     NodeTransitionCacheEntry result = cache;
     result._verified = now;
     result._verified = now;
 #ifndef NDEBUG
 #ifndef NDEBUG
-    if (wrt_cat.is_debug()) {
-      wrt_cat.debug() << "cached result is " << result << "\n";
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam() << "cached result is " << result << "\n";
     }
     }
 #endif
 #endif
     return result;
     return result;

+ 3 - 1
panda/src/graph/nodeTransitionWrapper.I

@@ -231,7 +231,9 @@ set_computed_verified(UpdateSeq now) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodeTransitionWrapper::cached_compose
 //     Function: NodeTransitionWrapper::cached_compose
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Computes the composition of this wrapper's value with
+//               that indicated by value, using the cache as a helper,
+//               and stores the result in this wrapper.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void NodeTransitionWrapper::
 INLINE void NodeTransitionWrapper::
 cached_compose(const NodeTransitionWrapper &cache, 
 cached_compose(const NodeTransitionWrapper &cache, 

+ 3 - 1
panda/src/graph/nullTransitionWrapper.I

@@ -169,7 +169,9 @@ set_computed_verified(UpdateSeq) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NullTransitionWrapper::cached_compose
 //     Function: NullTransitionWrapper::cached_compose
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Computes the composition of this wrapper's value with
+//               that indicated by value, using the cache as a helper,
+//               and stores the result in this wrapper.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void NullTransitionWrapper::
 INLINE void NullTransitionWrapper::
 cached_compose(const NullTransitionWrapper &, 
 cached_compose(const NullTransitionWrapper &, 

+ 3 - 3
panda/src/graph/setTransitionHelpers.I

@@ -320,8 +320,8 @@ tmap_invert_compose(InputIterator1 first1, InputIterator1 last1,
 #ifndef NDEBUG
 #ifndef NDEBUG
 #define OUTPUT_CC_ELEM(desc, type) \
 #define OUTPUT_CC_ELEM(desc, type) \
 { \
 { \
-  if (wrt_cat.is_debug()) { \
-    wrt_cat.debug() << "in " << desc << ": " << (type) << "\n"; \
+  if (wrt_cat.is_spam()) { \
+    wrt_cat.spam() << "in " << desc << ": " << (type) << "\n"; \
   } \
   } \
 }
 }
 #else
 #else
@@ -332,7 +332,7 @@ tmap_invert_compose(InputIterator1 first1, InputIterator1 last1,
 //     Function: tmap_cached_compose_not_1
 //     Function: tmap_cached_compose_not_1
 //  Description: One of several support functions for
 //  Description: One of several support functions for
 //               tmap_cached_compose(), below, this handles the case
 //               tmap_cached_compose(), below, this handles the case
-//               of tmap_cached_compose() for an NodeTransition that
+//               of tmap_cached_compose() for a NodeTransition that
 //               is already known not to be present in list 1, but may
 //               is already known not to be present in list 1, but may
 //               be in one or both of lists 2 and 3.
 //               be in one or both of lists 2 and 3.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 237 - 43
panda/src/graph/wrt.I

@@ -35,6 +35,20 @@ get_cached_net_transition(NodeRelation *arc, Node *&root, UpdateSeq now,
     root = top_subtree;
     root = top_subtree;
     net = cur_cache;
     net = cur_cache;
 
 
+#ifndef NDEBUG
+    if (wrt_cat.is_debug()) {
+      wrt_cat.debug()
+	<< "get_cached_net_transition(" << *arc->get_child() << ", ";
+      if (root == (Node *)NULL) {
+	wrt_cat.debug(false) << "(top)";
+      } else {
+	wrt_cat.debug(false) << *root;
+      }
+      wrt_cat.debug(false)
+	<< ") is current as of " << now << "\n";
+    }
+#endif
+
   } else {
   } else {
     // This arc's cache hasn't recently been verified, and we need to
     // This arc's cache hasn't recently been verified, and we need to
     // verify it now.  This will entail at least walking up the scene
     // verify it now.  This will entail at least walking up the scene
@@ -78,6 +92,20 @@ get_cached_net_transition(NodeRelation *arc, Node *&root, UpdateSeq now,
       net.cached_compose(cur_cache, cur_value, now);
       net.cached_compose(cur_cache, cur_value, now);
       net.store_to_cache(arc, root);
       net.store_to_cache(arc, root);
     }
     }
+
+#ifndef NDEBUG
+    if (wrt_cat.is_debug()) {
+      wrt_cat.debug()
+	<< "get_cached_net_transition(" << *arc->get_child() << ", ";
+      if (root == (Node *)NULL) {
+	wrt_cat.debug(false) << "(top)";
+      } else {
+	wrt_cat.debug(false) << *root;
+      }
+      wrt_cat.debug(false)
+	<< ") is recomputed as of " << now << "\n";
+    }
+#endif
   }
   }
 }    
 }    
 
 
@@ -104,6 +132,13 @@ get_cached_net_transition(const Node *node,
   if (node == NULL) {
   if (node == NULL) {
     // the NULL node is by convention equivalent to the root.
     // the NULL node is by convention equivalent to the root.
     result.make_identity();
     result.make_identity();
+
+#ifndef NDEBUG
+    if (wrt_cat.is_debug()) {
+      wrt_cat.debug()
+	<< "get_cached_net_transition((top))\n";
+    }
+#endif
     return;
     return;
   }
   }
 
 
@@ -113,6 +148,13 @@ get_cached_net_transition(const Node *node,
   if (uri == node->_parents.end()) {
   if (uri == node->_parents.end()) {
     // This node has no parents.  Stop here.
     // This node has no parents.  Stop here.
     result.make_identity();
     result.make_identity();
+
+#ifndef NDEBUG
+    if (wrt_cat.is_debug()) {
+      wrt_cat.debug()
+	<< "get_cached_net_transition(" << *node << ") has no parents.\n";
+    }
+#endif
     return;
     return;
   }
   }
 
 
@@ -120,6 +162,13 @@ get_cached_net_transition(const Node *node,
   if (urp.empty()) {
   if (urp.empty()) {
     // Again, this node has no parents.
     // Again, this node has no parents.
     result.make_identity();
     result.make_identity();
+
+#ifndef NDEBUG
+    if (wrt_cat.is_debug()) {
+      wrt_cat.debug()
+	<< "get_cached_net_transition(" << *node << ") has no parents.\n";
+    }
+#endif
     return;
     return;
   }
   }
 
 
@@ -146,19 +195,19 @@ get_cached_net_transition(const Node *node,
 #ifndef NDEBUG
 #ifndef NDEBUG
       // No, it wasn't mentioned.  Issue a warning and use the first
       // No, it wasn't mentioned.  Issue a warning and use the first
       // one.
       // one.
-      if (graph_cat.is_warning()) {
-	graph_cat.warning()
+      if (wrt_cat.is_warning()) {
+	wrt_cat.warning()
 	  << *node << " has " << urp.size() << " parents; wrt() ambiguous.\n"
 	  << *node << " has " << urp.size() << " parents; wrt() ambiguous.\n"
 	  << "  parents are: ";
 	  << "  parents are: ";
 	UpRelationPointers::const_iterator urpi;
 	UpRelationPointers::const_iterator urpi;
 	urpi = urp.begin();
 	urpi = urp.begin();
-	graph_cat.warning(false) << *(*urpi)->get_parent();
+	wrt_cat.warning(false) << *(*urpi)->get_parent();
 	urpi++;
 	urpi++;
 	while (urpi != urp.end()) {  
 	while (urpi != urp.end()) {  
-	  graph_cat.warning(false) << ", " << *(*urpi)->get_parent();
+	  wrt_cat.warning(false) << ", " << *(*urpi)->get_parent();
 	  urpi++;
 	  urpi++;
 	}
 	}
-	graph_cat.warning(false) << "\n";
+	wrt_cat.warning(false) << "\n";
       }
       }
       if (ambiguous_wrt_abort) {
       if (ambiguous_wrt_abort) {
 	abort();
 	abort();
@@ -211,6 +260,10 @@ get_uncached_net_transition(const Node *node,
 			    TypeHandle graph_type) {
 			    TypeHandle graph_type) {
   if (node == NULL) {
   if (node == NULL) {
     // the NULL node is by convention equivalent to the root.
     // the NULL node is by convention equivalent to the root.
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "get_uncached_net_transition(top)" << *node;
+    }
     result.make_identity();
     result.make_identity();
     return;
     return;
   }
   }
@@ -220,6 +273,10 @@ get_uncached_net_transition(const Node *node,
 
 
   if (uri == node->_parents.end()) {
   if (uri == node->_parents.end()) {
     // This node has no parents.  Stop here.
     // This node has no parents.  Stop here.
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "get_uncached_net_transition(" << *node << ") has no parents.\n";
+    }
     result.make_identity();
     result.make_identity();
     return;
     return;
   }
   }
@@ -227,6 +284,10 @@ get_uncached_net_transition(const Node *node,
   const UpRelationPointers &urp = (*uri).second;
   const UpRelationPointers &urp = (*uri).second;
   if (urp.empty()) {
   if (urp.empty()) {
     // Again, this node has no parents.
     // Again, this node has no parents.
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "get_uncached_net_transition(" << *node << ") has no parents.\n";
+    }
     result.make_identity();
     result.make_identity();
     return;
     return;
   }
   }
@@ -254,19 +315,19 @@ get_uncached_net_transition(const Node *node,
 #ifndef NDEBUG
 #ifndef NDEBUG
       // No, it wasn't mentioned.  Issue a warning and use the first
       // No, it wasn't mentioned.  Issue a warning and use the first
       // one. 
       // one. 
-      if (graph_cat.is_warning()) {
-	graph_cat.warning()
+      if (wrt_cat.is_warning()) {
+	wrt_cat.warning()
 	  << *node << " has " << urp.size() << " parents; wrt() ambiguous.\n"
 	  << *node << " has " << urp.size() << " parents; wrt() ambiguous.\n"
 	  << "  parents are:";
 	  << "  parents are:";
 	UpRelationPointers::const_iterator urpi;
 	UpRelationPointers::const_iterator urpi;
 	urpi = urp.begin();
 	urpi = urp.begin();
-	graph_cat.warning(false) << *(*urpi)->get_parent();
+	wrt_cat.warning(false) << *(*urpi)->get_parent();
 	urpi++;
 	urpi++;
 	while (urpi != urp.end()) {  
 	while (urpi != urp.end()) {  
-	  graph_cat.warning(false) << ", " << *(*urpi)->get_parent();
+	  wrt_cat.warning(false) << ", " << *(*urpi)->get_parent();
 	  urpi++;
 	  urpi++;
 	}
 	}
-	graph_cat.warning(false) << "\n";
+	wrt_cat.warning(false) << "\n";
       }
       }
       if (ambiguous_wrt_abort) {
       if (ambiguous_wrt_abort) {
 	abort();
 	abort();
@@ -285,6 +346,19 @@ get_uncached_net_transition(const Node *node,
   next.extract_from(parent_arc);
   next.extract_from(parent_arc);
 
 
   result.compose_in_place(next);
   result.compose_in_place(next);
+
+  if (wrt_cat.is_spam()) {
+    wrt_cat.spam()
+      << "get_uncached_net_transition(" << *node;
+    InputIterator ri;
+    for (ri = arc_list_begin; ri != arc_list_end; ++ri) {
+      wrt_cat.spam(false) << ", " << *(*ri);
+    }
+    
+    wrt_cat.spam(false)
+      << "), " << urp.size() << " parents, is:\n";
+    result.write(wrt_cat.spam(false), 2);
+  }
 }
 }
 #endif
 #endif
 
 
@@ -307,10 +381,29 @@ cached_wrt_base(const Node *from,
 
 
   TransitionWrapper net_from_trans = TransitionWrapper::init_from(result);
   TransitionWrapper net_from_trans = TransitionWrapper::init_from(result);
 
 
+#ifndef NDEBUG
+  if (wrt_cat.is_debug()) {
+    wrt_cat.debug()
+      << "Computing wrt(";
+    if (from == (Node *)NULL) {
+      wrt_cat.debug(false) << "(top), ";
+    } else {
+      wrt_cat.debug(false) << *from << ", ";
+    }
+    if (to == (Node *)NULL) {
+      wrt_cat.debug(false) << "(top)";
+    } else {
+      wrt_cat.debug(false) << *to;
+    }
+    wrt_cat.debug(false)
+      << "), as of " << now << "\n";
+  }
+#endif
+
   get_cached_net_transition(from, from_arcs_begin, from_arcs_end, now,
   get_cached_net_transition(from, from_arcs_begin, from_arcs_end, now,
-		     net_from_trans, graph_type);
+			    net_from_trans, graph_type);
   get_cached_net_transition(to, to_arcs_begin, to_arcs_end, now,
   get_cached_net_transition(to, to_arcs_begin, to_arcs_end, now,
-		     result, graph_type);
+			    result, graph_type);
   
   
 #ifndef NDEBUG
 #ifndef NDEBUG
   if (paranoid_wrt) {
   if (paranoid_wrt) {
@@ -323,26 +416,26 @@ cached_wrt_base(const Node *from,
     get_uncached_net_transition(from, from_arcs_begin, from_arcs_end,
     get_uncached_net_transition(from, from_arcs_begin, from_arcs_end,
 				check_from_trans, graph_type);
 				check_from_trans, graph_type);
     if (check_from_trans.compare_to(net_from_trans) != 0) {
     if (check_from_trans.compare_to(net_from_trans) != 0) {
-      graph_cat.warning()
+      wrt_cat.warning()
 	<< "WRT cache from " << *from << " is invalid!\n"
 	<< "WRT cache from " << *from << " is invalid!\n"
 	<< "  cached value is:\n";
 	<< "  cached value is:\n";
-      net_from_trans.write(graph_cat.warning(false), 4);
-      graph_cat.warning(false)
+      net_from_trans.write(wrt_cat.warning(false), 4);
+      wrt_cat.warning(false)
 	<< "  should be:\n";
 	<< "  should be:\n";
-      check_from_trans.write(graph_cat.warning(false), 4);
+      check_from_trans.write(wrt_cat.warning(false), 4);
       net_from_trans = check_from_trans;
       net_from_trans = check_from_trans;
     }
     }
     
     
     get_uncached_net_transition(to, to_arcs_begin, to_arcs_end,
     get_uncached_net_transition(to, to_arcs_begin, to_arcs_end,
 				check_to_trans, graph_type);
 				check_to_trans, graph_type);
     if (check_to_trans.compare_to(result) != 0) {
     if (check_to_trans.compare_to(result) != 0) {
-      graph_cat.warning()
+      wrt_cat.warning()
 	<< "WRT cache to " << *to << " is invalid!\n"
 	<< "WRT cache to " << *to << " is invalid!\n"
 	<< "  cached value is:\n";
 	<< "  cached value is:\n";
-      result.write(graph_cat.warning(false), 4);
-      graph_cat.warning(false)
+      result.write(wrt_cat.warning(false), 4);
+      wrt_cat.warning(false)
 	<< "  should be:\n";
 	<< "  should be:\n";
-      check_to_trans.write(graph_cat.warning(false), 4);
+      check_to_trans.write(wrt_cat.warning(false), 4);
       result = check_to_trans;
       result = check_to_trans;
     }
     }
   }
   }
@@ -510,27 +603,58 @@ get_uncached_wrt_subtree(Node *node, Node *to, TransitionWrapper &result,
 
 
   if (uri == node->_parents.end()) {
   if (uri == node->_parents.end()) {
     // This node has no parents.  Stop here.
     // This node has no parents.  Stop here.
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "get_uncached_wrt_subtree(" << *node << ") has no parents.\n";
+    }
     result.make_identity();
     result.make_identity();
-    return to;
+    return (Node *)NULL;
   }
   }
 
 
   const UpRelationPointers &urp = (*uri).second;
   const UpRelationPointers &urp = (*uri).second;
   if (urp.empty()) {
   if (urp.empty()) {
     // Again, no parents.  Stop here.
     // Again, no parents.  Stop here.
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "get_uncached_wrt_subtree(" << *node << ") has no parents.\n";
+    }
     result.make_identity();
     result.make_identity();
-    return to;
+    return (Node *)NULL;
   }
   }
 
 
-  if (node == to) {
-    // We've reached our stopping point.  Stop here.
+  if (urp.size() != 1) {
+    // There are multiple parents, so stop here.
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "get_uncached_wrt_subtree(" << *node << ") has " << urp.size()
+	<< " parents.\n";
+    }
     result.make_identity();
     result.make_identity();
     return node;
     return node;
   }
   }
 
 
-  if (urp.size() != 1) {
-    // There are multiple parents, so stop here.
+  if (node == to) {
+    // We've reached our stopping point.  Stop here.
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "get_uncached_wrt_subtree(" << *node << ") is at stopping point.\n";
+    }
     result.make_identity();
     result.make_identity();
-    return node;
+
+    // Actually, we do need to keep walking up till we find the actual
+    // top of the instanced subtree, so we can return the correct
+    // pointer.
+    int num_parents = node->get_num_parents(graph_type);
+    while (num_parents == 1) {
+      node = node->get_parent(graph_type, 0)->get_parent();
+      num_parents = node->get_num_parents(graph_type);
+    }
+
+    if (num_parents == 0) {
+      return (Node *)NULL;
+    } else {
+      return node;
+    }
   }
   }
 
 
   const NodeRelation *parent_arc = *(urp.begin());
   const NodeRelation *parent_arc = *(urp.begin());
@@ -544,6 +668,19 @@ get_uncached_wrt_subtree(Node *node, Node *to, TransitionWrapper &result,
 
 
   result.compose_in_place(next);
   result.compose_in_place(next);
 
 
+  if (wrt_cat.is_spam()) {
+    wrt_cat.spam()
+      << "get_uncached_wrt_subtree(" << *node
+      << "), top at ";
+    if (stop == (Node *)NULL) {
+      wrt_cat.spam(false) << "(top)";
+    } else {
+      wrt_cat.spam(false) << *stop;
+    }
+    wrt_cat.spam(false) << " is:\n";
+    result.write(wrt_cat.spam(false), 2);
+  }
+
   return stop;
   return stop;
 }
 }
 
 
@@ -560,6 +697,19 @@ uncached_wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result,
 
 
   result.compose_in_place(next);
   result.compose_in_place(next);
 
 
+  if (wrt_cat.is_spam()) {
+    wrt_cat.spam()
+      << "uncached_wrt_subtree(" << *arc
+      << "), top at ";
+    if (stop == (Node *)NULL) {
+      wrt_cat.spam(false) << "(top)";
+    } else {
+      wrt_cat.spam(false) << *stop;
+    }
+    wrt_cat.spam(false) << " is:\n";
+    result.write(wrt_cat.spam(false), 2);
+  }
+
   return stop;
   return stop;
 }
 }
 
 
@@ -580,6 +730,20 @@ cached_wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result,
     // If the top of the subtree is the node we asked to wrt to,
     // If the top of the subtree is the node we asked to wrt to,
     // excellent!  Stop here.
     // excellent!  Stop here.
 
 
+#ifndef NDEBUG
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "cached_wrt_subtree(" << *arc << ", ";
+      if (to == (Node *)NULL) {
+	wrt_cat.spam(false) << "(top)";
+      } else {
+	wrt_cat.spam(false) << *to;
+      }
+      wrt_cat.spam(false) << ") stops at top, result is:\n";
+      result.write(wrt_cat.spam(false), 2);
+    }
+#endif
+
   } else {
   } else {
 
 
     // Otherwise, it must be the case that the node we want to wrt to is
     // Otherwise, it must be the case that the node we want to wrt to is
@@ -591,6 +755,20 @@ cached_wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result,
     
     
     // Save the result from the first pass.
     // Save the result from the first pass.
     TransitionWrapper net_from_trans = result;
     TransitionWrapper net_from_trans = result;
+
+#ifndef NDEBUG
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "cached_wrt_subtree(" << *arc << ", " << *to << ") stops at ";
+      if (top_subtree == (Node *)NULL) {
+	wrt_cat.spam(false) << "(top)";
+      } else {
+	wrt_cat.spam(false) << *top_subtree;
+      }
+      wrt_cat.spam() << ", first result is:\n";
+      result.write(wrt_cat.spam(false), 2);
+    }
+#endif
     
     
     // Now determine the net transition to the top of the subtree from
     // Now determine the net transition to the top of the subtree from
     // this arc.  It had better be the same subtree!
     // this arc.  It had better be the same subtree!
@@ -600,6 +778,22 @@ cached_wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result,
     
     
     // And now compute the actual wrt.
     // And now compute the actual wrt.
     result.invert_compose_in_place(net_from_trans);
     result.invert_compose_in_place(net_from_trans);
+
+#ifndef NDEBUG
+    if (wrt_cat.is_spam()) {
+      wrt_cat.spam()
+	<< "cached_wrt_subtree(" << *arc << ", " << *to << ") stops at ";
+      if (top_subtree == (Node *)NULL) {
+	wrt_cat.spam(false) << "(top)";
+      } else {
+	wrt_cat.spam(false) << *top_subtree;
+      }
+      wrt_cat.spam() << ", second result is:\n";
+      net_from_trans.write(wrt_cat.spam(false), 2);
+      wrt_cat.spam() << ", final result is:\n";
+      result.write(wrt_cat.spam(false), 2);
+    }
+#endif
   }
   }
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
@@ -611,46 +805,46 @@ cached_wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result,
       uncached_wrt_subtree(arc, to, check_trans, graph_type);
       uncached_wrt_subtree(arc, to, check_trans, graph_type);
 
 
     if (top_subtree_3 != top_subtree) {
     if (top_subtree_3 != top_subtree) {
-      graph_cat.warning()
+      wrt_cat.warning()
 	<< "WRT subtree cache from " << *arc->get_child() << " to ";
 	<< "WRT subtree cache from " << *arc->get_child() << " to ";
       if (to == (Node *)NULL) {
       if (to == (Node *)NULL) {
-	graph_cat.warning(false) << "(top)";
+	wrt_cat.warning(false) << "(top)";
       } else {
       } else {
-	graph_cat.warning(false) << *to;
+	wrt_cat.warning(false) << *to;
       }
       }
-      graph_cat.warning(false)
+      wrt_cat.warning(false)
 	<< " computes incorrect top_subtree!\n"
 	<< " computes incorrect top_subtree!\n"
 	<< "  computed ";
 	<< "  computed ";
       if (top_subtree == (Node *)NULL) {
       if (top_subtree == (Node *)NULL) {
-	graph_cat.warning(false) << "(top)\n";
+	wrt_cat.warning(false) << "(top)\n";
       } else {
       } else {
-	graph_cat.warning(false) << *top_subtree << "\n";
+	wrt_cat.warning(false) << *top_subtree << "\n";
       }
       }
-      graph_cat.warning(false)
+      wrt_cat.warning(false)
 	<< "  should be ";
 	<< "  should be ";
       if (top_subtree_3 == (Node *)NULL) {
       if (top_subtree_3 == (Node *)NULL) {
-	graph_cat.warning(false) << "(top)\n";
+	wrt_cat.warning(false) << "(top)\n";
       } else {
       } else {
-	graph_cat.warning(false) << *top_subtree_3 << "\n";
+	wrt_cat.warning(false) << *top_subtree_3 << "\n";
       }
       }
       top_subtree = top_subtree_3;
       top_subtree = top_subtree_3;
     }
     }
 
 
     if (check_trans.compare_to(result) != 0) {
     if (check_trans.compare_to(result) != 0) {
-      graph_cat.warning()
+      wrt_cat.warning()
 	<< "WRT subtree cache from " << *arc->get_child() << " to ";
 	<< "WRT subtree cache from " << *arc->get_child() << " to ";
       if (to == (Node *)NULL) {
       if (to == (Node *)NULL) {
-	graph_cat.warning(false) << "(top)";
+	wrt_cat.warning(false) << "(top)";
       } else {
       } else {
-	graph_cat.warning(false) << *to;
+	wrt_cat.warning(false) << *to;
       }
       }
-      graph_cat.warning(false)
+      wrt_cat.warning(false)
 	<< " is invalid!\n"
 	<< " is invalid!\n"
 	<< "  cached value is:\n";
 	<< "  cached value is:\n";
-      result.write(graph_cat.warning(false), 4);
-      graph_cat.warning(false)
+      result.write(wrt_cat.warning(false), 4);
+      wrt_cat.warning(false)
 	<< "  should be:\n";
 	<< "  should be:\n";
-      check_trans.write(graph_cat.warning(false), 4);
+      check_trans.write(wrt_cat.warning(false), 4);
       result = check_trans;
       result = check_trans;
     }
     }
   }
   }