Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
ir_graph_util.c
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines