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 /* 00037 * Originally ported from ipa/common/ip_graph.c 00038 * This module contains a routines to construct and manage graphs. 00039 * The edge and vertex lists of the graph grow as needed. 00040 * 00041 * There is a depth first vertex ordering mechanism along with 00042 * successor and predecessor graph iterators which will be needed for 00043 * the data flow iterative solver. 00044 * 00045 * ==================================================================== 00046 * ==================================================================== 00047 */ 00048 00049 #include <stdio.h> 00050 #include <assert.h> 00051 #include "ir_graph_util.h" 00052 00053 00054 /*------------------------------------------------------------------------*/ 00055 /* construct a graph, with the given number of vertices and edges */ 00056 /*------------------------------------------------------------------------*/ 00057 GRAPH* build_graph_u(VINDEX vertex_size, EINDEX edge_size, MEM_POOL* m) 00058 { 00059 GRAPH *g; 00060 int i; 00061 00062 00063 GR_ASSERT(vertex_size >= 0, "build_graph_u vertex_size < 0\n"); 00064 GR_ASSERT(edge_size >= 0, "build_graph_u edge_size < 0\n"); 00065 00066 g = (GRAPH*) MEM_POOL_Alloc(m, sizeof(GRAPH)); 00067 GR_ASSERT (g != 0, "build_graph_u g == 0\n"); 00068 bzero(g, sizeof(GRAPH)); 00069 00070 if (vertex_size != 0) /* build the vertices */ 00071 { 00072 GRAPH_v(g) = (VERTEX*) MEM_POOL_Alloc(m, sizeof(VERTEX)*vertex_size); 00073 GR_ASSERT (GRAPH_v(g) != 0, "build_graph_u graph_v(g) == 0\n"); 00074 bzero(GRAPH_v(g), sizeof(VERTEX)*vertex_size); 00075 } 00076 00077 if (edge_size != 0) /* build the edges */ 00078 { 00079 GRAPH_e(g) = (EDGE*) MEM_POOL_Alloc(m, sizeof(EDGE)*edge_size); 00080 GR_ASSERT (GRAPH_e(g) != 0, "build_graph_u graph_e(g) == 0\n"); 00081 bzero(GRAPH_e(g), sizeof(EDGE)*edge_size); 00082 } 00083 00084 /*----------------------------set up the vertices-------------------------*/ 00085 GRAPH_vcnt(g) = 0; /* used vertices */ 00086 00087 for (i = 0; i<vertex_size; ++i) 00088 { 00089 VERTEX_from(&GRAPH_v_i(g,i)) = i+1; /* set the linked list of free vertices */ 00090 VERTEX_fcnt(&GRAPH_v_i(g,i)) = -1; /* node is not being used */ 00091 } 00092 00093 /* last free vertex points to no entry */ 00094 VERTEX_from(&GRAPH_v_i(g,vertex_size-1)) = INVALID_VINDEX; 00095 GRAPH_vfree(g) = 0; /* free vertices = total added vertices */ 00096 GRAPH_vmax(g) = vertex_size; /* max vertices = new maximum */ 00097 00098 00099 /*----------------------------set up the edges----------------------------*/ 00100 GRAPH_ecnt(g) = 0; /* used edges */ 00101 for (i = 0; i<edge_size; ++i) 00102 { 00103 EDGE_nfrom(&GRAPH_e_i(g,i)) = i+1; /* set the linked list of free edges */ 00104 EDGE_from(&GRAPH_e_i(g,i)) = INVALID_VINDEX; /* edge is not being used */ 00105 } 00106 00107 /* last free edge points to no entry */ 00108 EDGE_nfrom(&GRAPH_e_i(g, edge_size-1)) = -1; 00109 GRAPH_efree(g) = 0; /* free edges */ 00110 GRAPH_emax(g) = edge_size; /* total edges */ 00111 00112 00113 GRAPH_root(g) = INVALID_VINDEX; /* no root */ 00114 GRAPH_m(g) = m; 00115 return g; 00116 } 00117 00118 00119 /*------------------------------------------------------------------------*/ 00120 /* construct a graph, in this case the graph utility handles the growth */ 00121 /* of the graph since the user has no clue about what the sizes should be */ 00122 /*------------------------------------------------------------------------*/ 00123 GRAPH* build_graph(MEM_POOL* m) 00124 { 00125 GRAPH *g; 00126 00127 g = (GRAPH*) MEM_POOL_Alloc(m, sizeof(GRAPH)); 00128 bzero(g, sizeof(GRAPH)); 00129 GR_ASSERT (g != 0, "build_graph g == 0\n"); 00130 00131 GRAPH_vcnt(g) = 0; /* total vertices */ 00132 GRAPH_ecnt(g) = 0; /* total edges */ 00133 GRAPH_vfree(g) = -1; /* free vertices */ 00134 GRAPH_efree(g) = -1; /* free edges */ 00135 GRAPH_root(g) = INVALID_VINDEX; /* no root */ 00136 GRAPH_m(g) = m; 00137 return g; 00138 } 00139 00140 /*------------------------------------------------------------------------*/ 00141 /* grow the graph, more vertices are needed, double it */ 00142 /*------------------------------------------------------------------------*/ 00143 static void grow_vertex(GRAPH *g) 00144 { 00145 VINDEX max, i; 00146 00147 MEM_POOL *m = GRAPH_m(g); 00148 00149 if (GRAPH_vmax(g) < 8) 00150 max = 16; 00151 else 00152 max = GRAPH_vmax(g)*2; /* set max to double current size */ 00153 00154 GR_ASSERT(max > GRAPH_vmax(g), "grow_vertex max <= GRAPH_vmax(g)\n"); 00155 00156 GRAPH_v(g) = (VERTEX*) MEM_POOL_Realloc(m,GRAPH_v(g),sizeof(VERTEX)*GRAPH_vmax(g), 00157 sizeof(VERTEX)*max); 00158 for (i = GRAPH_vmax(g); i<max; ++i) { 00159 VERTEX_from(&GRAPH_v_i(g,i)) = i+1; /* set the linked list of free vertices */ 00160 VERTEX_fcnt(&GRAPH_v_i(g,i)) = -1; /* node is not being used */ 00161 } 00162 00163 /* last free vertex points to no entry */ 00164 VERTEX_from(&GRAPH_v_i(g,max-1)) = INVALID_VINDEX; 00165 00166 GRAPH_vfree(g) = GRAPH_vmax(g); /* free vertices = total added vertices */ 00167 GRAPH_vmax(g) = max; /* max vertices = new maximum */ 00168 00169 } 00170 00171 /*------------------------------------------------------------------------*/ 00172 /* grow the graph, more edges are needed, double it */ 00173 /*------------------------------------------------------------------------*/ 00174 static void grow_edge(GRAPH *g) 00175 { 00176 EINDEX max, i, diff; 00177 MEM_POOL *m = GRAPH_m(g); 00178 00179 if (GRAPH_emax(g) < 8) 00180 max = 16; 00181 else 00182 max = GRAPH_emax(g)*2; /* set max to double current size */ 00183 00184 00185 GR_ASSERT(max > GRAPH_emax(g), "grow_edge graph_emax >= max\n"); 00186 GRAPH_e(g) = (EDGE*) MEM_POOL_Realloc(m,GRAPH_e(g), sizeof(EDGE)*GRAPH_emax(g), 00187 sizeof(EDGE)*max); 00188 /* diff = max - GRAPH_emax(g); */ 00189 /* bzero(&GRAPH_e_i(g,GRAPH_emax(g)), sizeof(EDGE)*(diff)); */ 00190 00191 for (i = GRAPH_emax(g); i<max; ++i) { 00192 EDGE_nfrom(&GRAPH_e_i(g,i)) = i+1; /* set the linked list of free edges */ 00193 EDGE_from(&GRAPH_e_i(g,i)) = INVALID_EINDEX; /* edge is not being used */ 00194 } 00195 00196 /* last free vertex points to no entry */ 00197 EDGE_nfrom(&GRAPH_e_i(g, max-1)) = INVALID_EINDEX; 00198 00199 GRAPH_efree(g) = GRAPH_emax(g); /* free edges = total added edges */ 00200 GRAPH_emax(g) = max; /* max edges = new maximum */ 00201 } 00202 00203 00204 /*------------------------------------------------------------------------*/ 00205 /* add a vertex containing user info. Return a unique vertex number */ 00206 /*------------------------------------------------------------------------*/ 00207 VINDEX add_vertex(GRAPH* g, void *user) 00208 { 00209 VINDEX new_vertex; 00210 MEM_POOL *m = GRAPH_m(g); 00211 00212 if (GRAPH_vfree(g) == -1) 00213 grow_vertex(g); 00214 00215 new_vertex = GRAPH_vfree(g); /* get the free vertex */ 00216 00217 /* set free vertex to next free vertex */ 00218 GRAPH_vfree(g) = VERTEX_from(&GRAPH_v_i(g,new_vertex)); 00219 00220 /* no edges yet */ 00221 VERTEX_from(&GRAPH_v_i(g,new_vertex)) = INVALID_EINDEX; 00222 VERTEX_to(&GRAPH_v_i(g,new_vertex)) = INVALID_EINDEX; 00223 00224 /* add user information */ 00225 VERTEX_user(&GRAPH_v_i(g,new_vertex)) = user; 00226 00227 /* no from and to counts */ 00228 VERTEX_fcnt(&GRAPH_v_i(g,new_vertex)) = 0; 00229 VERTEX_tcnt(&GRAPH_v_i(g,new_vertex)) = 0; 00230 00231 /* no level yet */ 00232 VERTEX_level(&GRAPH_v_i(g,new_vertex)) = -1; 00233 00234 /* increment vertex count */ 00235 GRAPH_vcnt(g)++; 00236 00237 return new_vertex; 00238 } 00239 00240 00241 /*----------------------------------------------------------------------*/ 00242 /* add an edge from vertex (from) to vertex (to) */ 00243 /* containing user info. Return a unique edge number */ 00244 /*----------------------------------------------------------------------*/ 00245 EINDEX add_edge(GRAPH *g, VINDEX from, VINDEX to, void *user) 00246 { 00247 EINDEX new_edge, e2; 00248 MEM_POOL *m = GRAPH_m(g); 00249 00250 GR_ASSERT(is_vertex(g,from), "add_edge is_vertex(g, from\n"); 00251 GR_ASSERT(is_vertex(g,from), "add_edge is_vertex(g, to\n"); 00252 00253 /* are there any free edges? */ 00254 if(GRAPH_efree(g) == -1) 00255 00256 /* grow the edge list if no free edges */ 00257 grow_edge(g); 00258 00259 /* get a free edge */ 00260 new_edge = GRAPH_efree(g); 00261 00262 /* reset the free edge pointer */ 00263 GRAPH_efree(g)= EDGE_nfrom(&GRAPH_e_i(g,new_edge)); 00264 00265 /* store the user information */ 00266 EDGE_user(&GRAPH_e_i(g,new_edge)) = user; 00267 00268 /* from vertex is = from */ 00269 EDGE_from(&GRAPH_e_i(g,new_edge)) = from; 00270 00271 /* to vertex is = to */ 00272 EDGE_to(&GRAPH_e_i(g,new_edge)) = to; 00273 00274 /* incr. from count for from vertex */ 00275 VERTEX_fcnt(&GRAPH_v_i(g,from))++; 00276 00277 /* incr. to count for to vertex */ 00278 VERTEX_tcnt(&GRAPH_v_i(g,to))++; 00279 00280 /* incr. total used edge count */ 00281 GRAPH_ecnt(g)++; 00282 00283 /* set up the list of from edges for the from vertex */ 00284 e2 = VERTEX_from(&GRAPH_v_i(g,from)); 00285 EDGE_nfrom(&GRAPH_e_i(g,new_edge)) = e2; 00286 VERTEX_from(&GRAPH_v_i(g,from)) = new_edge; 00287 00288 /* set up the list of to edges for the to vertex */ 00289 e2 = VERTEX_to(&GRAPH_v_i(g,to)); 00290 EDGE_nto(&GRAPH_e_i(g,new_edge)) = e2; 00291 VERTEX_to(&GRAPH_v_i(g,to)) = new_edge; 00292 00293 /* set the recursive edge field to be zero */ 00294 EDGE_etype(&GRAPH_e_i(g,new_edge)) = 0; 00295 00296 return new_edge; 00297 } 00298 00299 /*-----------------------------------------------------------------------*/ 00300 /* check to see if it is a valid vertex number */ 00301 /* if the vertex number is less than the total count and it exists */ 00302 /*-----------------------------------------------------------------------*/ 00303 BOOL is_vertex(GRAPH *g, VINDEX vertex) 00304 { 00305 return ( ( vertex < GRAPH_vmax(g) ) 00306 && ( VERTEX_fcnt(&GRAPH_v_i(g,vertex)) != INVALID_VINDEX ) ); 00307 } 00308 00309 /*-----------------------------------------------------------------------*/ 00310 /* get the next vertex */ 00311 /*-----------------------------------------------------------------------*/ 00312 VINDEX next_vertex(GRAPH *g, VINDEX vertex) 00313 { 00314 GR_ASSERT(is_vertex(g, vertex), "next_vertex is_vertex(g,vertex)\n"); 00315 00316 while (1) { 00317 if (is_vertex(g, ++vertex)) 00318 return vertex; 00319 else 00320 if (vertex >= GRAPH_vmax(g)) 00321 return INVALID_VINDEX; 00322 } 00323 } 00324 00325 /*---------------------------------------------------------------------*/ 00326 /* Delete a given edge */ 00327 /*---------------------------------------------------------------------*/ 00328 void delete_edge(GRAPH *g, EINDEX edge) 00329 { 00330 00331 VINDEX from_vertex, to_vertex; 00332 EINDEX next_edge, head_edge; 00333 00334 GR_ASSERT(is_edge(g, edge), "delete_edge is_edge\n"); 00335 00336 /* update the information for the from vertex */ 00337 /* get the from vertex */ 00338 from_vertex = EDGE_from(&GRAPH_e_i(g,edge)); 00339 00340 /* decrement from count */ 00341 VERTEX_fcnt(&GRAPH_v_i(g,from_vertex))--; 00342 00343 /* get the next edge in linked list */ 00344 next_edge = EDGE_nfrom(&GRAPH_e_i(g,edge)); 00345 00346 /* get the first edge in linked list */ 00347 head_edge = VERTEX_from(&GRAPH_v_i(g,from_vertex)); 00348 00349 /* if the head is set to edge */ 00350 if (head_edge == edge) 00351 00352 /* set it to next from edge */ 00353 VERTEX_from(&GRAPH_v_i(g,from_vertex)) = next_edge; 00354 00355 /* else walk the list of edges */ 00356 else 00357 { 00358 /* unlink the edge from listofedges */ 00359 while (EDGE_nfrom(&GRAPH_e_i(g,head_edge)) != edge) 00360 head_edge = EDGE_nfrom(&GRAPH_e_i(g,head_edge)); 00361 EDGE_nfrom(&GRAPH_e_i(g,head_edge)) = next_edge; 00362 } 00363 00364 /*---- update the information for the to vertex ----*/ 00365 00366 /* get the to vertex */ 00367 to_vertex = EDGE_to(&GRAPH_e_i(g,edge)); 00368 00369 /* decrement to count */ 00370 VERTEX_tcnt(&GRAPH_v_i(g,to_vertex))--; 00371 00372 /* get the next edge in linked list */ 00373 next_edge = EDGE_nto(&GRAPH_e_i(g,edge)); 00374 00375 /* get the first edge in linked list */ 00376 head_edge = VERTEX_to(&GRAPH_v_i(g,to_vertex)); 00377 00378 /* if head is set to edge */ 00379 if (head_edge == edge) 00380 /* set it to next to edge */ 00381 VERTEX_to(&GRAPH_v_i(g,to_vertex)) = next_edge; 00382 00383 else 00384 /* else walk the list of edges */ 00385 { 00386 /* unlink the edge from the list of to edges */ 00387 while (g->e[head_edge].nto != edge) 00388 head_edge = EDGE_nto(&GRAPH_e_i(g,head_edge)); 00389 EDGE_nto(&GRAPH_e_i(g,head_edge)) = next_edge; 00390 } 00391 00392 /* add the free edge to the linked list of free edges */ 00393 EDGE_nfrom(&GRAPH_e_i(g,edge)) = GRAPH_efree(g); 00394 EDGE_from(&GRAPH_e_i(g,edge)) = INVALID_VINDEX; 00395 GRAPH_efree(g) = edge; 00396 GRAPH_ecnt(g)--; /* decrement edge count */ 00397 } 00398 00399 /*---------------------------------------------------------------------*/ 00400 /* Delete a given vertex */ 00401 /*---------------------------------------------------------------------*/ 00402 void* delete_vertex(GRAPH *g, VINDEX vertex) 00403 { 00404 void *user; 00405 EINDEX from, nfrom, to, nto; 00406 00407 GR_ASSERT(is_vertex(g, vertex), "delete vertex is_vertex\n"); 00408 00409 user = VERTEX_user(&GRAPH_v_i(g,vertex)); 00410 00411 /* delete the from edges */ 00412 from = VERTEX_from(&GRAPH_v_i(g,vertex)); 00413 while (from != INVALID_EINDEX) 00414 { 00415 nfrom = EDGE_nfrom(&GRAPH_e_i(g,from)); 00416 delete_edge(g, from); 00417 from = nfrom; 00418 } 00419 00420 /* delete the to edges */ 00421 to = VERTEX_to(&GRAPH_v_i(g,vertex)); 00422 while (to != INVALID_EINDEX) 00423 { 00424 nto = EDGE_nto(&GRAPH_e_i(g,to)); 00425 delete_edge(g, to); 00426 to = nto; 00427 } 00428 00429 VERTEX_fcnt(&GRAPH_v_i(g,vertex)) = -1; 00430 VERTEX_from(&GRAPH_v_i(g,vertex)) = GRAPH_vfree(g); 00431 GRAPH_vfree(g) = vertex; 00432 GRAPH_vcnt(g)--; 00433 00434 return user; 00435 00436 } 00437 00438 /*---------------------------------------------------------------------*/ 00439 /* check to see if it is a valid edge */ 00440 /*---------------------------------------------------------------------*/ 00441 BOOL is_edge(GRAPH *g, EINDEX edge) 00442 { 00443 return ( ( edge < GRAPH_emax(g) ) 00444 && EDGE_from(&GRAPH_e_i(g,edge)) != INVALID_VINDEX ); 00445 } 00446 00447 /*---------------------------------------------------------------*/ 00448 /* get the user info attached to the vertex */ 00449 /*---------------------------------------------------------------*/ 00450 void* get_vertex(GRAPH *g, VINDEX vertex) 00451 { 00452 GR_ASSERT(is_vertex(g,vertex), "get_vertex\n"); 00453 00454 return (VERTEX_user(&GRAPH_v_i(g,vertex))); 00455 } 00456 00457 /*---------------------------------------------------------------*/ 00458 /* get the count of incoming edges */ 00459 /*---------------------------------------------------------------*/ 00460 int num_preds(GRAPH *g, VINDEX vertex) 00461 { 00462 GR_ASSERT(is_vertex(g,vertex), "num_preds is_vertex\n"); 00463 00464 return (VERTEX_tcnt(&GRAPH_v_i(g,vertex))); 00465 } 00466 00467 /*---------------------------------------------------------------*/ 00468 /* get the count of outgoing edges */ 00469 /*---------------------------------------------------------------*/ 00470 int num_succs(GRAPH *g, VINDEX vertex) 00471 { 00472 GR_ASSERT(is_vertex(g,vertex), "num_succs is_vertex\n"); 00473 00474 return (VERTEX_fcnt(&GRAPH_v_i(g,vertex))); 00475 } 00476 00477 /*---------------------------------------------------------------*/ 00478 /* get an edge given the vertices */ 00479 /*---------------------------------------------------------------*/ 00480 void* get_edge(GRAPH *g, VINDEX from, VINDEX to) 00481 { 00482 EINDEX e; 00483 00484 00485 GR_ASSERT(is_vertex(g, from), "get_edge is_vertex from\n"); 00486 GR_ASSERT(is_vertex(g, to), "get_edge is_vertex to\n"); 00487 00488 e = VERTEX_from(&GRAPH_v_i(g, from)); 00489 00490 while ( e != INVALID_EINDEX ) { 00491 if(EDGE_to(&GRAPH_e_i(g,e)) == to) 00492 break; 00493 e = (EDGE_nfrom(&GRAPH_e_i(g,e))); 00494 } 00495 return EDGE_user(&GRAPH_e_i(g,e)); 00496 } 00497 00498 /*---------------------------------------------------------------*/ 00499 /* get the count of edges from->to */ 00500 /*---------------------------------------------------------------*/ 00501 int 00502 edge_count(GRAPH* g, VINDEX from, VINDEX to) 00503 { 00504 int count= 0; 00505 EINDEX e; 00506 00507 GR_ASSERT(is_vertex(g, from), "edge_count is_vertex from\n"); 00508 GR_ASSERT(is_vertex(g, to), "edge_count is_vertex to\n"); 00509 00510 e = VERTEX_from(&GRAPH_v_i(g, from)); 00511 00512 while ( e != INVALID_EINDEX ) { 00513 if(EDGE_to(&GRAPH_e_i(g,e)) == to) 00514 ++count; 00515 e = (EDGE_nfrom(&GRAPH_e_i(g,e))); 00516 } 00517 return count; 00518 } 00519 00520 /*---------------------------------------------------------------*/ 00521 /* get an edge given the vertices */ 00522 /*---------------------------------------------------------------*/ 00523 void* 00524 get_edge_u(GRAPH *g, EINDEX e) 00525 { 00526 GR_ASSERT(is_edge(g, e), "get_edge_u is_edge\n"); 00527 00528 return EDGE_user(&GRAPH_e_i(g,e)); 00529 } 00530 00531 00532 /* set the edge user value */ 00533 void 00534 set_edge_u (GRAPH *g, EINDEX e, void *user) 00535 { 00536 EDGE_user(&GRAPH_e_i(g,e)) = user; 00537 } 00538 00539 /*---------------------------------------------------------------*/ 00540 /* initialize a vertex_iterator */ 00541 /*---------------------------------------------------------------*/ 00542 V_ITER* create_vertex_iter(GRAPH *g, VINDEX vertex, MEM_POOL* m) 00543 { 00544 V_ITER *v_i; 00545 VERTEX *v_ptr; 00546 v_i = (V_ITER*) MEM_POOL_Alloc(m, sizeof(V_ITER)); 00547 00548 00549 V_ITER_g(v_i) = g; 00550 V_ITER_c_v(v_i) = vertex; 00551 v_ptr = GRAPH_v(g); 00552 V_ITER_from_e(v_i) = VERTEX_from(&v_ptr[vertex]); 00553 V_ITER_to_e(v_i) = VERTEX_to(&v_ptr[vertex]); 00554 V_ITER_fcnt(v_i) = VERTEX_fcnt(&v_ptr[vertex]); 00555 V_ITER_tcnt(v_i) = VERTEX_tcnt(&v_ptr[vertex]); 00556 V_ITER_nfrom(v_i) = -1; 00557 V_ITER_nto(v_i) = -1; 00558 V_ITER_m(v_i) = m; 00559 return v_i; 00560 } 00561 00562 /*---------------------------------------------------------------*/ 00563 /* get first predeccessor */ 00564 /*---------------------------------------------------------------*/ 00565 VINDEX first_v_preds(V_ITER *v_i) 00566 { 00567 EINDEX e; 00568 VINDEX from; 00569 00570 /* get the first to edge */ 00571 if ( V_ITER_to_e(v_i) == INVALID_EINDEX ) 00572 { 00573 00574 MEM_POOL_FREE(V_ITER_m(v_i),v_i); 00575 00576 return INVALID_VINDEX; 00577 } 00578 00579 /* get the first to edge */ 00580 e = V_ITER_to_e(v_i); 00581 /* return it's from vertex */ 00582 from = EDGE_from(&GRAPH_e_i(V_ITER_g(v_i),e)); 00583 V_ITER_nto(v_i) = EDGE_nto(&GRAPH_e_i(V_ITER_g(v_i),e)); 00584 00585 /* store the current edge */ 00586 V_ITER_c_e(v_i) = e; 00587 return from; 00588 } 00589 00590 /*---------------------------------------------------------------*/ 00591 /* get next predeccessor */ 00592 /*---------------------------------------------------------------*/ 00593 VINDEX next_v_preds(V_ITER *v_i) 00594 { 00595 EINDEX e; 00596 VINDEX from; 00597 00598 /* get the next to edge */ 00599 if(V_ITER_nto(v_i) == -1) 00600 { 00601 00602 MEM_POOL_FREE(V_ITER_m(v_i),v_i); 00603 00604 return INVALID_VINDEX; 00605 } 00606 00607 /* get the next to edge */ 00608 e = V_ITER_nto(v_i); 00609 00610 /* return it's from vertex */ 00611 from = EDGE_from(&GRAPH_e_i(V_ITER_g(v_i), e)); 00612 V_ITER_nto(v_i) = EDGE_nto(&GRAPH_e_i(V_ITER_g(v_i),e)); 00613 00614 /* store the current edge */ 00615 V_ITER_c_e(v_i) = e; 00616 return from; 00617 } 00618 00619 /*---------------------------------------------------------------*/ 00620 /* get the first successor vertex */ 00621 /*---------------------------------------------------------------*/ 00622 VINDEX first_v_succs(V_ITER *v_i) 00623 { 00624 EINDEX e; 00625 VINDEX to; 00626 00627 /* get the first from edge */ 00628 if ( V_ITER_from_e(v_i) == INVALID_EINDEX ) 00629 { 00630 MEM_POOL_FREE(V_ITER_m(v_i),v_i); 00631 return INVALID_VINDEX; 00632 } 00633 00634 /* return it's to vertex */ 00635 e = V_ITER_from_e(v_i); 00636 to = EDGE_to(&GRAPH_e_i(V_ITER_g(v_i),e)); 00637 V_ITER_nfrom(v_i) = EDGE_nfrom(&GRAPH_e_i(V_ITER_g(v_i),e)); 00638 00639 /* store the current edge */ 00640 V_ITER_c_e(v_i) = e; 00641 return to; 00642 } 00643 00644 /*---------------------------------------------------------------*/ 00645 /* get the next successor vertex */ 00646 /*---------------------------------------------------------------*/ 00647 VINDEX next_v_succs(V_ITER *v_i) 00648 { 00649 EINDEX ei; 00650 VINDEX to; 00651 00652 /* get the next from edge */ 00653 if(V_ITER_nfrom(v_i) == -1) 00654 { 00655 MEM_POOL_FREE(V_ITER_m(v_i),v_i); 00656 00657 return INVALID_VINDEX; 00658 } 00659 00660 /* return it's to vertex */ 00661 ei = V_ITER_nfrom(v_i); 00662 to = EDGE_to(&GRAPH_e_i(V_ITER_g(v_i), ei)); 00663 V_ITER_nfrom(v_i) = EDGE_nfrom(&GRAPH_e_i(V_ITER_g(v_i),ei)); 00664 00665 /* store the current edge */ 00666 V_ITER_c_e(v_i) = ei; 00667 return to; 00668 } 00669 00670 /*---------------------------------------------------------------*/ 00671 /* get the level of the vertex */ 00672 /*---------------------------------------------------------------*/ 00673 int 00674 get_vertex_level(GRAPH* g, VINDEX v) 00675 { 00676 return (VERTEX_level(&GRAPH_v_i(g,v))); 00677 } 00678 00679 /*---------------------------------------------------------------*/ 00680 /* set the level of the vertex */ 00681 /*---------------------------------------------------------------*/ 00682 void 00683 set_vertex_level(GRAPH* g, VINDEX v, int level) 00684 { 00685 VERTEX_level(&GRAPH_v_i(g,v)) = level; 00686 } 00687 00688 00689 /* ==================================================================== 00690 * 00691 * Search 00692 * 00693 * Helper search function for depth first ordering, as described in the 00694 * dragon book, page 662. 00695 * 00696 * This function recursively searches the subgraph rooted at vertex v, 00697 * depth-first, finally adding v to the beginning of the node order 00698 * when it has added all its successors. The effect is that a vertex 00699 * will always precede all of its successors in the list, and will 00700 * always follow all of its predecessors (ignoring back-edges in the 00701 * graph). Therefore, both the resulting node order and its reversal 00702 * are topological sorts. 00703 * 00704 * When called, the DFN struct contains the vertexes already added 00705 * to the order, with DFN_first being the smallest index where a 00706 * vertex has been added. The search uses a work array of flags 00707 * (visit) to keep track of whether a vertex has already been visited. 00708 * 00709 * ==================================================================== 00710 */ 00711 00712 #define VISITED TRUE 00713 static char *Malloc_Mem_Pool; 00714 static int lvl; 00715 00716 static void 00717 Search ( GRAPH *g, VINDEX v, DFN *d, BOOL *visit, EINDEX ei ) 00718 { 00719 EINDEX edge; 00720 VINDEX vtx; 00721 V_ITER *v_iter; 00722 int tmp; 00723 00724 visit[v] = VISITED; /* Mark the vertex as visited */ 00725 set_vertex_level(g, v, lvl); 00726 00727 lvl++; 00728 /* Create a vertex iterator: */ 00729 v_iter = create_vertex_iter ( g, v, Malloc_Mem_Pool ); 00730 00731 for ( vtx=first_v_succs(v_iter); 00732 vtx != INVALID_VINDEX ; 00733 vtx=next_v_succs(v_iter) ) 00734 { 00735 /* Recursively search from vtx if it has not been visited: */ 00736 if ( !visit[vtx] ) { 00737 Search ( g, vtx, d, visit, V_ITER_c_e(v_iter) ); 00738 } 00739 } 00740 lvl--; 00741 00742 /* Add v to the order at DFN_first: */ 00743 --DFN_first(d); 00744 tmp = DFN_first(d); 00745 DFN_v_list_i ( d, tmp ) = v; 00746 00747 if (ei != INVALID_VINDEX) { 00748 void *u; 00749 00750 u = get_edge_u(g, ei); 00751 DFN_user_i(d, tmp) = u; 00752 } 00753 } 00754 00755 /* ==================================================================== 00756 * 00757 * Depth_First_Ordering 00758 * 00759 * Create a topological sort graph traversal order based on a depth 00760 * first ordering (see the dragon book, page 660). Such an order 00761 * helps to speed up iterative data flow algorithms and can also be 00762 * used to detect loops (i.e. back-edges in the graph). 00763 * 00764 * ==================================================================== 00765 */ 00766 00767 DFN * 00768 Depth_First_Ordering ( GRAPH *g, MEM_POOL* m ) 00769 { 00770 VINDEX vertex_count = GRAPH_vcnt(g); 00771 EINDEX edge_count = GRAPH_ecnt(g); 00772 int vertex_max = GRAPH_vmax(g); 00773 DFN *d; 00774 BOOL *visit; 00775 00776 /* Validate and trace: */ 00777 GR_ASSERT ( GRAPH_root(g) != INVALID_VINDEX, "Invalid root g for graph\n"); 00778 printf ("Depth_First_Ordering: vertex count = %d \n", vertex_count ); 00779 00780 /* Allocate the DFN struct: */ 00781 d = (DFN*) MEM_POOL_Alloc ( m, sizeof(DFN) ); 00782 GR_ASSERT(d != NULL, "Depth_First_Ordering: d" ); 00783 00784 DFN_v_list(d) = (VINDEX *) 00785 MEM_POOL_Alloc ( m, sizeof(VINDEX) * vertex_count ); 00786 GR_ASSERT(DFN_v_list(d) != NULL, "Depth_First_Ordering: list" ); 00787 00788 DFN_user(d) = (void *) 00789 MEM_POOL_Alloc ( m, sizeof(void *) * vertex_count ); 00790 GR_ASSERT(DFN_user(d) != NULL, "Depth_First_Ordering: user" ); 00791 00792 /* Allocate work array to keep track of visited vertices: */ 00793 visit = (BOOL *) MEM_POOL_Alloc ( m, sizeof(BOOL)*vertex_max ); 00794 GR_ASSERT ( visit != NULL, "Depth_First_Ordering: visit" ); 00795 00796 bzero ( visit, sizeof(BOOL)*vertex_max ); 00797 00798 /* Initialize the DFN struct -- set end and first to point beyond 00799 * the first element: 00800 */ 00801 DFN_first(d) = DFN_end(d) = vertex_count; 00802 00803 /* Go do the depth-first walk from the root: */ 00804 Search ( g, GRAPH_root(g), d, visit, INVALID_EINDEX ); 00805 00806 /* Free work array: */ 00807 MEM_POOL_FREE(m, visit); 00808 00809 return(d); 00810 } 00811 00812 00813 void Print_Pred(GRAPH *g, VINDEX v, void (*prn)()) 00814 { 00815 V_ITER *vi; 00816 VINDEX vtx; 00817 void * dummy = 0; 00818 int *u, total = 0; 00819 00820 vi = create_vertex_iter(g, v, dummy); 00821 00822 printf(" ["); 00823 for (vtx = first_v_preds(vi); 00824 vtx != INVALID_VINDEX; 00825 vtx = next_v_preds(vi)) { 00826 (*prn)(vtx); 00827 u = (int *)get_edge_u(g, V_ITER_c_e(vi)); 00828 GR_ASSERT(u, "user field in pred NULL"); 00829 printf("/%d ", *u); 00830 total += *u; 00831 } 00832 printf(" - total %d]", total); 00833 } 00834 00835 00836 void Print_DFN (DFN* d, GRAPH *g, void (*prn)(), void (*prn_c)() ) 00837 { 00838 VINDEX i, j; 00839 long *k; 00840 00841 printf ("Depth First Numbering: [%d..%d)\n",DFN_first(d), DFN_end(d) ); 00842 for ( i = DFN_first(d); i< DFN_end(d); i++ ) { 00843 for (j = 0; j < get_vertex_level(g,DFN_v_list_i(d,i)); j++) 00844 printf("+ "); 00845 (*prn)(DFN_v_list_i(d,i)); 00846 #if 0 00847 k = DFN_user_i(d,i); 00848 if (k) 00849 printf(" %d",*k); 00850 else 00851 printf(" ?"); 00852 #endif 00853 Print_Pred(g, DFN_v_list_i(d,i), prn); 00854 printf("\n"); 00855 } 00856 printf("\n"); 00857 } 00858 00859 /* ==================================================================== 00860 * 00861 * Free_DFN 00862 * 00863 * Free the memory used by a depth first numbering. Must be 00864 * called with the same MEM_POOL that was used to allocate it. 00865 * 00866 * ==================================================================== 00867 */ 00868 00869 void 00870 Free_DFN ( DFN* d, MEM_POOL* m ) 00871 { 00872 MEM_POOL_FREE ( m, DFN_v_list(d) ); 00873 MEM_POOL_FREE ( m, d ); 00874 } 00875