Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 // Generic graph library 00037 // 00038 // It consists three components: 00039 // -- a graph container, 00040 // -- a definition of graph iterator, 00041 // -- and algorithms accessing using only the graph iterator. 00042 // 00043 // 00044 // Graph Container: 00045 // 00046 // digraph<NODE, EDGE> -- a directed graph of NODE and EDGE. 00047 // node/edge are shorthand for digraph<NODE,EDGE>::node, 00048 // and digraph<NODE,EDGE>::edge respectively. 00049 // 00050 // node *add_node() -- add a uninitialized node to the directed graph. 00051 // node *add_node(NODE v) -- add a node to the directed graph. 00052 // edge *add_edge(node *tail, node *head) -- add an edge (tail, head) to the graph. 00053 // void delete_edge(edge *e) -- delete an edge. 00054 // void delete_node(node *n) -- delete a node. 00055 // void delete_node_and_edge(node *n) -- delete a node and its succ/pred edges. 00056 // 00057 // node_set_iter -- iterates all nodes in the graph 00058 // succ_node_iter -- successor node forward iterator 00059 // succ_edge_iter -- successor edge forward iterator 00060 // pred_node_iter -- predecessor node forward iterator 00061 // pred_edge_iter -- predecessor edge forward iterator 00062 // 00063 // node_set_iter node_set_begin() -- returns an iterator pointing at the 00064 // beginning of the node set sequence. 00065 // node_set_iter node_set_end() -- returns an iterator pointing at the 00066 // end of the node set sequence. 00067 // 00068 // succ_node_iter succ_node_begin(node *v) 00069 // -- returns the beginning of the successor node* sequence. 00070 // succ_node_iter succ_node_end(node *v) 00071 // -- returns the end of the successor node* sequence. 00072 // 00073 // similiar definitions for {succ,pred}_{node,edge}_{begin,end}(). 00074 // 00075 // digraph<NODE, EDGE>::edge 00076 // node *head(); // the head node of the edge 00077 // node *tail(); // the tail node of the edge 00078 // 00079 // 00080 // Graph Iterator : 00081 // 00082 // The graph iterator is the interface between the graph container and 00083 // the graph algorithms. The iterator is indeed a graph node. 00084 // 00085 // It could be divided into several classes: 00086 // node_graph_iterator, node_edge_graph_iterator 00087 // 00088 // Operations defined on the node_graph iterator: 00089 // succ_node_begin(), succ_node_end(), 00090 // pred_node_begin(), pred_node_end(). 00091 // 00092 // Operations defined on the node_edge_graph iterator, 00093 // in addition to the on supported by node_graph iterator: 00094 // succ_edge_begin(), succ_edge_end(), 00095 // pred_edge_begin(), pred_edge_end(). 00096 // 00097 // 00098 // Graph Algorithms: 00099 // 00100 // directed graph Traversal: 00101 // preorder_iter<GRAPH, ITERATOR, VISITED> 00102 // postorder_iter<GRAPH, ITERATOR, VISITED> 00103 // depth_first_iter<GRAPH, ITERATOR, VISITED> 00104 // breath_first_iter<GRAPH, ITERATOR, VISITED> 00105 // 00106 // where ITERATOR contains the direction of graph traversal. 00107 // If ITERATOR is pred_node_iter, it performs the traversal on G as if 00108 // it is traversaling a graph G' where edges in G' are inverted edges from G. 00109 // 00110 // where VISITED is a set keeping track of the state of the traversal. 00111 // (the set of nodes have been visited). The default is set<GRAPH::node*>. 00112 // It could be replaced using a bitset of bool vector if there is a unique-id 00113 // associated with each node*. 00114 // 00115 // dep_order_iter<GRAPH, SUCC_ITERATOR, PRED_ITERATOR, VISITED> 00116 // 1. a node is made ready after all of its successor are visited or 00117 // it has no succ. 00118 // 2. ready nodes are processed in FIFO order. 00119 // Note that the order is defined for a DAG, but not defined for cyclic graph. 00120 // 00121 // tree Traversal: 00122 // preorder_tree_iter<TREE, ITERATOR> 00123 // postorder_tree_iter<TREE, ITERATOR> 00124 // depth_first_tree_iter<TREE, ITERATOR> 00125 // breath_first_tree_iter<TREE, ITERATOR> 00126 // 00127 // TO DO: 00128 // * add allocator 00129 // * decide if succ_node_begin() and succ_node_end() should be 00130 // a member function of digraph or node. 00131 // * complete the iterators: traits, ... 00132 // * implement dominator tree algorithm. 00133 // 00134 // 00135 00136 #ifndef __GRAPH_H 00137 #define __GRAPH_H 00138 00139 #include <hash_set.h> 00140 #include <vector.h> 00141 #include <stack.h> 00142 #include <bvector.h> 00143 #include <set.h> 00144 00145 template <class NODE, class EDGE> struct digraph_node; 00146 template <class NODE, class EDGE> struct digraph_edge; 00147 template <class NODE, class EDGE> struct digraph; 00148 template <class DIGRAPH> struct succ_node_iter; 00149 template <class DIGRAPH> struct succ_edge_iter; 00150 template <class DIGRAPH> struct pred_node_iter; 00151 template <class DIGRAPH> struct pred_edge_iter; 00152 00153 00154 template <class NODE, class EDGE> 00155 struct digraph_edge { 00156 typedef digraph_node<NODE, EDGE> digraph_node; 00157 00158 EDGE edge; 00159 digraph_node *head; 00160 digraph_node *tail; 00161 digraph_edge *next_succ; 00162 digraph_edge *next_pred; 00163 00164 digraph_edge<NODE, EDGE>(digraph_node *v, digraph_node *w) : 00165 tail(v),head(w),next_succ(0),next_pred(0),edge() {} 00166 }; 00167 00168 00169 template <class NODE, class EDGE> 00170 struct digraph_node { 00171 typedef digraph_edge<NODE, EDGE> digraph_edge; 00172 typedef digraph<NODE, EDGE> digraph; 00173 typedef succ_node_iter<digraph> succ_node_iter; 00174 typedef pred_node_iter<digraph> pred_node_iter; 00175 00176 NODE node; 00177 int n_succ; 00178 int n_pred; 00179 digraph_edge *first_succ; 00180 digraph_edge *first_pred; 00181 00182 void add_succ(digraph_edge *e) { ++n_succ; e->next_succ = first_succ; first_succ = e; } 00183 void add_pred(digraph_edge *e) { ++n_pred; e->next_pred = first_pred; first_pred = e; } 00184 00185 void delete_succ_edge(digraph_edge *e) { 00186 if (first_succ == e) { 00187 e = e->next_succ; 00188 return; 00189 } 00190 for (digraph_edge *t = e; t->next_succ != e; t = t->next_succ); 00191 if (t->next_succ == e) 00192 t->next_succ = e->next_succ; 00193 } 00194 00195 void delete_pred_edge(digraph_edge *e) { 00196 if (first_pred == e) { 00197 e = e->next_pred; 00198 return; 00199 } 00200 for (digraph_edge *t = e; t->next_pred != e; t = t->next_pred); 00201 if (t->next_pred == e) 00202 t->next_pred = e->next_pred; 00203 } 00204 00205 succ_node_iter succ_node_begin() const 00206 { succ_node_iter s; s.cur = first_succ; return s; } 00207 00208 succ_node_iter succ_node_end() const 00209 { succ_node_iter s; s.cur = 0; return s; } 00210 00211 pred_node_iter pred_node_begin() const 00212 { pred_node_iter s; s.cur = first_pred; return s; } 00213 00214 pred_node_iter pred_node_end() const 00215 { pred_node_iter s; s.cur = 0; return s; } 00216 00217 digraph_node<NODE, EDGE>(NODE v) { 00218 node = v; n_succ = n_pred = 0; first_succ = first_pred = 0; } 00219 00220 digraph_node<NODE, EDGE>() { 00221 n_succ = n_pred = 0; first_succ = first_pred = 0; } 00222 }; 00223 00224 00225 template <class X> 00226 struct ptr_hash 00227 { 00228 size_t operator()(const X* s) const { return reinterpret_cast<size_t>(s); } 00229 }; 00230 00231 template <class NODE, class EDGE> 00232 struct digraph { 00233 typedef digraph<NODE, EDGE> self; 00234 typedef digraph_node<NODE, EDGE> node; 00235 typedef digraph_edge<NODE, EDGE> edge; 00236 typedef succ_edge_iter<self> succ_edge_iter; 00237 typedef succ_node_iter<self> succ_node_iter; 00238 typedef pred_edge_iter<self> pred_edge_iter; 00239 typedef pred_node_iter<self> pred_node_iter; 00240 typedef hash_set<node*, ptr_hash<node> > node_set_type; 00241 typedef node_set_type::iterator node_set_iter; 00242 00243 node_set_type node_set; 00244 00245 node_set_iter node_set_begin() { return node_set.begin(); } 00246 node_set_iter node_set_end() { return node_set.end(); } 00247 00248 node *add_node(NODE v) { 00249 node *p = new node(v); 00250 node_set.insert(p); 00251 return p; 00252 } 00253 00254 node *add_node() { 00255 node *p = new node(); 00256 node_set.insert(p); 00257 return p; 00258 } 00259 00260 edge *add_edge(node *v, node *w) { 00261 edge *e = new edge(v, w); 00262 v->add_succ(e); 00263 w->add_pred(e); 00264 return e; 00265 } 00266 00267 void delete_edge(edge *e) { 00268 e->tail->delete_succ_edge(e); 00269 e->head->delete_pred_edge(e); 00270 delete e; 00271 } 00272 00273 void delete_node(node *v) { 00274 node_set.erase(v); 00275 delete v; 00276 } 00277 00278 void delete_node_and_edge(node *v) { 00279 while (v->first_succ) 00280 v->delete_succ_edge(v->first_succ); 00281 while (v->first_pred) 00282 v->delete_succ_edge(v->first_pred); 00283 delete_node(v); 00284 } 00285 00286 edge *find_edge(node *v, node *w); 00287 node *head(edge *e); 00288 node *tail(edge *e); 00289 00290 succ_node_iter succ_node_begin(node *v) const 00291 { succ_node_iter s; s.cur = v->first_succ; return s; } 00292 00293 succ_node_iter succ_node_end(node *v) const 00294 { succ_node_iter s; s.cur = 0; return s; } 00295 00296 pred_node_iter pred_node_begin(node *v) const 00297 { pred_node_iter s; s.cur = v->first_succ; return s; } 00298 00299 pred_node_iter pred_node_end(node *v) const 00300 { pred_node_iter s; s.cur = 0; return s; } 00301 00302 succ_edge_iter succ_edge_begin(node *v) const 00303 { succ_edge_iter s; s.cur = v->first_succ; return s; } 00304 00305 succ_edge_iter succ_edge_end(node *v) const 00306 { succ_edge_iter s; s.cur = 0; return s; } 00307 00308 pred_edge_iter pred_edge_begin(node *v) const 00309 { pred_edge_iter s; s.cur = v->first_succ; return s; } 00310 00311 pred_edge_iter pred_edge_end(node *v) const 00312 { pred_edge_iter s; s.cur = 0; return s; } 00313 }; 00314 00315 00316 00317 template <class DIGRAPH> 00318 struct succ_node_iter { 00319 typedef DIGRAPH::node node; 00320 typedef DIGRAPH::edge edge; 00321 typedef succ_node_iter<DIGRAPH> self; 00322 00323 edge *cur; 00324 00325 self operator ++(int) { self tmp = *this; cur = cur->next_succ; return tmp; } 00326 self &operator ++() { cur = cur->next_succ; return *this; } 00327 node *operator *() { return cur->head; } 00328 friend bool operator ==(const self& x, const self& y) { return x.cur == y.cur; } 00329 00330 self begin(node *v) const { self s; s.cur = v->first_succ; return s; } 00331 self end(node *v) const { self s; s.cur = 0; return s; } 00332 }; 00333 00334 00335 template <class DIGRAPH> 00336 struct succ_edge_iter { 00337 typedef DIGRAPH::node node; 00338 typedef DIGRAPH::edge edge; 00339 typedef succ_edge_iter<DIGRAPH> self; 00340 00341 edge *cur; 00342 00343 self operator ++(int) { self tmp = *this; cur = cur->next_succ; return tmp; } 00344 self& operator ++() { cur = cur->next_succ; return *this; } 00345 edge *operator *() { return cur; } 00346 friend bool operator ==(const self& x, const self& y) { return x.cur == y.cur; } 00347 00348 self begin(node *v) const { self s; s.cur = v->first_succ; return s; } 00349 self end(node *v) const { self s; s.cur = 0; return s; } 00350 }; 00351 00352 00353 template <class DIGRAPH> 00354 struct pred_node_iter { 00355 typedef DIGRAPH::node node; 00356 typedef DIGRAPH::edge edge; 00357 typedef pred_node_iter<DIGRAPH> self; 00358 00359 edge *cur; 00360 00361 self operator ++(int) { self tmp = *this; cur = cur->next_pred; return tmp; } 00362 self& operator ++() { cur = cur->next_pred; return *this; } 00363 node *operator *() { return cur->tail; } 00364 friend bool operator ==(const self& x, const self& y) { return x.cur == y.cur; } 00365 00366 self begin(node *v) const { self s; s.cur = v->first_pred; return s; } 00367 self end(node *v) const { self s; s.cur = 0; return s; } 00368 }; 00369 00370 00371 template <class DIGRAPH> 00372 struct pred_edge_iter { 00373 typedef DIGRAPH::node node; 00374 typedef DIGRAPH::edge edge; 00375 typedef pred_edge_iter<DIGRAPH> self; 00376 00377 edge *cur; 00378 00379 self operator ++(int) { self tmp = *this; cur = cur->next_pred; return tmp; } 00380 self& operator ++() { cur = cur->next_pred; return *this; } 00381 edge *operator *() { return cur; } 00382 friend bool operator ==(const self& x, const self& y) { return x.cur == y.cur; } 00383 00384 self begin(node *v) const { self s; s.cur = v->first_pred; return s; } 00385 self end(node *v) const { self s; s.cur = 0; return s; } 00386 }; 00387 00388 00389 // preorder graph iterator 00390 template <class GRAPH, class ITERATOR = GRAPH::succ_node_iter, class VISITED = set<GRAPH::node*> > 00391 struct preorder_iter { 00392 typedef preorder_iter<GRAPH, ITERATOR, VISITED> self; 00393 stack<ITERATOR> state; 00394 VISITED visited_set; 00395 00396 ITERATOR cur; 00397 00398 bool visited(GRAPH::node *v) { return visited_set.find(v) != visited_set.end(); } 00399 void set_visited(GRAPH::node *v) { visited_set.insert(v); } 00400 00401 self &operator ++() { 00402 GRAPH::node *n = *cur; 00403 if (cur.begin(n) != cur.end(n)) { 00404 ITERATOR t = cur.begin(n); 00405 while (t != t.end(0) && visited(*t)) 00406 ++t; 00407 if (t != t.end(0)) { 00408 set_visited(*t); 00409 ++cur; 00410 state.push(cur); 00411 cur = t; 00412 return *this; 00413 } 00414 } 00415 ++cur; 00416 while (true) { 00417 while (cur != cur.end(0) && visited(*cur)) 00418 ++cur; 00419 if (cur != cur.end(0)) break; 00420 while (cur == cur.end(0) && !state.empty()) { 00421 cur = state.top(); 00422 state.pop(); 00423 } 00424 if (cur == cur.end(0)) break; 00425 } 00426 if (cur != cur.end(0)) 00427 set_visited(*cur); 00428 return *this; 00429 } 00430 self operator ++(int) { self tmp = *this; ++cur; return tmp; } 00431 void set_cur(GRAPH::node *v) { 00432 cur.cur = new GRAPH::edge(v,v); 00433 set_visited(*cur); 00434 } 00435 bool empty() { return cur == cur.end(0); } 00436 GRAPH::node *operator *() { return *cur; } 00437 00438 preorder_iter<GRAPH, ITERATOR, VISITED>() {}; 00439 preorder_iter<GRAPH, ITERATOR, VISITED>(GRAPH::node *v) { set_cur(v); }; 00440 }; 00441 00442 00443 template <class GRAPH, class ITERATOR = GRAPH::succ_node_iter, class VISITED = set<GRAPH::node*> > 00444 struct postorder_iter { 00445 typedef postorder_iter<GRAPH, ITERATOR, VISITED> self; 00446 stack<ITERATOR> state; 00447 VISITED visited_set; 00448 00449 ITERATOR cur; 00450 00451 bool visited(GRAPH::node *v) { return visited_set.find(v) != visited_set.end(); } 00452 void set_visited(GRAPH::node *v) { visited_set.insert(v); } 00453 00454 self &operator ++() { 00455 ++cur; 00456 while (cur != cur.end(0) && visited(*cur)) 00457 ++cur; 00458 if (cur == cur.end(0)) { 00459 if (!state.empty()) { 00460 cur = state.top(); 00461 state.pop(); 00462 return *this; 00463 } 00464 } else { 00465 GRAPH::node *n = *cur; 00466 while (cur.begin(n) != cur.end(n)) { 00467 ITERATOR t = cur.begin(n); 00468 while (t != t.end(0) && visited(*t)) 00469 ++t; 00470 if (t != t.end(0)) { 00471 set_visited(*t); 00472 set_visited(*cur); 00473 state.push(cur); 00474 cur = t; 00475 } else 00476 break; 00477 n = *cur; 00478 } 00479 } 00480 if (cur != cur.end(0)) 00481 set_visited(*cur); 00482 return *this; 00483 } 00484 self operator ++(int) { self tmp = *this; ++cur; return tmp; } 00485 void set_cur(GRAPH::node *v) { 00486 cur.cur = new GRAPH::edge(v,v); 00487 GRAPH::node *n = *cur; 00488 set_visited(v); 00489 while (cur.begin(n) != cur.end(n)) { 00490 ITERATOR t = cur.begin(n); 00491 while (t != t.end(0) && visited(*t)) 00492 ++t; 00493 if (t != t.end(0)) { 00494 set_visited(*t); 00495 set_visited(*cur); 00496 state.push(cur); 00497 cur = t; 00498 } else 00499 break; 00500 n = *cur; 00501 } 00502 if (cur != cur.end(0)) 00503 set_visited(*cur); 00504 } 00505 bool empty() { return cur == cur.end(0); } 00506 GRAPH::node *operator *() { return *cur; } 00507 00508 postorder_iter<GRAPH, ITERATOR, VISITED>() {}; 00509 postorder_iter<GRAPH, ITERATOR, VISITED>(GRAPH::node *v) { set_cur(v); }; 00510 }; 00511 00512 00513 template <class GRAPH, class ITERATOR = GRAPH::succ_node_iter, class VISITED = set<GRAPH::node*> > 00514 struct depth_first_iter : preorder_iter<GRAPH, ITERATOR, VISITED> { 00515 depth_first_iter<GRAPH, ITERATOR, VISITED>(GRAPH::node *v) { set_cur(v); }; 00516 }; 00517 00518 00519 template <class GRAPH, class ITERATOR = GRAPH::succ_node_iter, class VISITED = set<GRAPH::node*> > 00520 struct breath_first_iter { 00521 typedef breath_first_iter<GRAPH, ITERATOR, VISITED> self; 00522 deque<ITERATOR> state; 00523 VISITED visited_set; 00524 00525 bool visited(GRAPH::node *v) { return visited_set.find(v) != visited_set.end(); } 00526 void set_visited(GRAPH::node *v) { visited_set.insert(v); } 00527 00528 self &operator ++() { 00529 if (state.empty()) return *this; 00530 ITERATOR cur = state.front(); 00531 state.pop_front(); 00532 ITERATOR t; 00533 GRAPH::node *n = *cur; 00534 for (t = cur.begin(n); t != cur.end(n); ++t) { 00535 if (!visited(*t)) { 00536 state.push_back(t); 00537 set_visited(*t); 00538 } 00539 } 00540 return *this; 00541 } 00542 self operator ++(int) { self tmp = *this; ++cur; return tmp; } 00543 void set_cur(GRAPH::node *v) { 00544 ITERATOR t; 00545 t.cur = new GRAPH::edge(v,v); 00546 set_visited(*t); 00547 state.push_back(t); 00548 } 00549 bool empty() { return state.empty(); } 00550 GRAPH::node *operator *() { return *(state.front()); } 00551 00552 breath_first_iter<GRAPH, ITERATOR, VISITED>() {}; 00553 breath_first_iter<GRAPH, ITERATOR, VISITED>(GRAPH::node *v) { set_cur(v); }; 00554 }; 00555 00556 00557 template <class GRAPH, 00558 class SUCC_ITERATOR = GRAPH::succ_node_iter, 00559 class PRED_ITERATOR = GRAPH::pred_node_iter, 00560 class VISITED = set<GRAPH::node*> > 00561 struct dep_order_iter { 00562 typedef dep_order_iter<GRAPH, SUCC_ITERATOR, PRED_ITERATOR, VISITED> self; 00563 deque<GRAPH::node *> state; 00564 VISITED visited_set; 00565 00566 bool visited(GRAPH::node *v) { return visited_set.find(v) != visited_set.end(); } 00567 void set_visited(GRAPH::node *v) { visited_set.insert(v); } 00568 00569 private: 00570 bool all_succ_visited(GRAPH::node *n) { 00571 SUCC_ITERATOR t; 00572 for (t = n->succ_node_begin(); t != n->succ_node_end(); ++t) { 00573 if (!visited(*t)) 00574 return false; 00575 } 00576 return true; 00577 } 00578 00579 public: 00580 00581 self &operator ++() { 00582 if (state.empty()) return *this; 00583 GRAPH::node *n = state.front(); 00584 state.pop_front(); 00585 set_visited(n); 00586 00587 PRED_ITERATOR t; 00588 for (t = n->pred_node_begin(); t != n->pred_node_end(); ++t) { 00589 if (!visited(*t) && all_succ_visited(*t)) { 00590 state.push_back(*t); 00591 set_visited(*t); 00592 } 00593 } 00594 return *this; 00595 } 00596 self operator ++(int) { self tmp = *this; ++cur; return tmp; } 00597 bool empty() { return state.empty(); } 00598 GRAPH::node *operator *() { return state.front(); } 00599 00600 void make_ready(GRAPH::node *n) { 00601 state.push_back(n); 00602 set_visited(n); 00603 } 00604 00605 dep_order_iter<GRAPH, SUCC_ITERATOR, PRED_ITERATOR, VISITED>(GRAPH *g) { 00606 GRAPH::node_set_iter iter; 00607 for (iter = g->node_set_begin(); iter != g->node_set_end(); ++iter) { 00608 if (all_succ_visited(*iter)) { 00609 state.push_back(*iter); 00610 set_visited(*iter); 00611 } 00612 } 00613 } 00614 }; 00615 00616 00617 template <class TREE> 00618 struct never_visited { 00619 TREE::node *find(TREE::node *n) { return 0; } 00620 TREE::node *end() { return 0; } 00621 void insert(TREE::node *n) { } 00622 }; 00623 00624 00625 template <class TREE, class ITERATOR> 00626 struct preorder_tree_iter : 00627 preorder_iter<TREE, ITERATOR, never_visited<TREE> > {}; 00628 00629 template <class TREE, class ITERATOR> 00630 struct postorder_tree_iter : 00631 postorder_iter<TREE, ITERATOR, never_visited<TREE> > {}; 00632 00633 template <class TREE, class ITERATOR> 00634 struct depth_first_tree_iter : 00635 depth_first_iter<TREE, ITERATOR, never_visited<TREE> > {}; 00636 00637 template <class TREE, class ITERATOR> 00638 struct breath_first_tree_iter : 00639 breath_first_iter<TREE, ITERATOR, never_visited<TREE> > {}; 00640 00641 00642 #endif /* __GRAPH_H */ 00643 00644 // Local Variables: 00645 // mode:C++ 00646 // End: