/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/dotgen/fastgr.c

Go to the documentation of this file.
00001 /* $Id: fastgr.c,v 1.3 2005/03/14 23:14:37 erg Exp $ $Revision: 1.3 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 
00018 #include "dot.h"
00019 
00020 
00021 /*
00022  * operations on the fast internal graph.
00023  */
00024 
00025 static edge_t *ffe(node_t * u, elist uL, node_t * v, elist vL)
00026 {
00027     int i;
00028     edge_t *e;
00029 
00030     if ((uL.size > 0) && (vL.size > 0)) {
00031         if (uL.size < vL.size) {
00032             for (i = 0; (e = uL.list[i]); i++)
00033                 if (e->head == v)
00034                     break;
00035         } else {
00036             for (i = 0; (e = vL.list[i]); i++)
00037                 if (e->tail == u)
00038                     break;
00039         }
00040     } else
00041         e = 0;
00042     return e;
00043 }
00044 
00045 edge_t *find_fast_edge(node_t * u, node_t * v)
00046 {
00047     return ffe(u, ND_out(u), v, ND_in(v));
00048 }
00049 
00050 static node_t*
00051 find_fast_node(graph_t * g, node_t * n)
00052 {
00053     node_t *v;
00054     for (v = GD_nlist(g); v; v = ND_next(v))
00055         if (v == n)
00056             break;
00057     return v;
00058 }
00059 
00060 edge_t *find_flat_edge(node_t * u, node_t * v)
00061 {
00062     return ffe(u, ND_flat_out(u), v, ND_flat_in(v));
00063 }
00064 
00065 /* safe_list_append - append e to list L only if e not already a member */
00066 static void 
00067 safe_list_append(edge_t * e, elist * L)
00068 {
00069     int i;
00070 
00071     for (i = 0; i < L->size; i++)
00072         if (e == L->list[i])
00073             return;
00074     elist_append(e, (*L));
00075 }
00076 
00077 edge_t *fast_edge(edge_t * e)
00078 {
00079 #ifdef DEBUG
00080     int i;
00081     edge_t *f;
00082     for (i = 0; (f = ND_out(e->tail).list[i]); i++) {
00083         if (e == f) {
00084             fprintf(stderr, "duplicate fast edge\n");
00085             return;
00086         }
00087         assert(e->head != f->head);
00088     }
00089     for (i = 0; (f = ND_in(e->head).list[i]); i++) {
00090         if (e == f) {
00091             fprintf(stderr, "duplicate fast edge\n");
00092             return;
00093         }
00094         assert(e->tail != f->tail);
00095     }
00096 #endif
00097     elist_append(e, ND_out(e->tail));
00098     elist_append(e, ND_in(e->head));
00099     return e;
00100 }
00101 
00102 /* zapinlist - remove e from list and fill hole with last member of list */
00103 void zapinlist(elist * L, edge_t * e)
00104 {
00105     int i;
00106 
00107     for (i = 0; i < L->size; i++) {
00108         if (L->list[i] == e) {
00109             L->size--;
00110             L->list[i] = L->list[L->size];
00111             L->list[L->size] = NULL;
00112             break;
00113         }
00114     }
00115 }
00116 
00117 /* disconnects e from graph */
00118 void delete_fast_edge(edge_t * e)
00119 {
00120     assert(e != NULL);
00121     zapinlist(&(ND_out(e->tail)), e);
00122     zapinlist(&(ND_in(e->head)), e);
00123 }
00124 
00125 static void 
00126 safe_delete_fast_edge(edge_t * e)
00127 {
00128     int i;
00129     edge_t *f;
00130 
00131     assert(e != NULL);
00132     for (i = 0; (f = ND_out(e->tail).list[i]); i++)
00133         if (f == e)
00134             zapinlist(&(ND_out(e->tail)), e);
00135     for (i = 0; (f = ND_in(e->head).list[i]); i++)
00136         if (f == e)
00137             zapinlist(&(ND_in(e->head)), e);
00138 }
00139 
00140 void other_edge(edge_t * e)
00141 {
00142     elist_append(e, ND_other(e->tail));
00143 }
00144 
00145 void safe_other_edge(edge_t * e)
00146 {
00147     safe_list_append(e, &(ND_other(e->tail)));
00148 }
00149 
00150 #ifdef OBSOLETE
00151 void 
00152 delete_other_edge(edge_t * e)
00153 {
00154     assert(e != NULL);
00155     zapinlist(&(ND_other(e->tail)), e);
00156 }
00157 #endif
00158 
00159 /* new_virtual_edge:
00160  * Create and return a new virtual edge e attached to orig.
00161  * ED_to_orig(e) = orig
00162  * ED_to_virt(orig) = e if e is the first virtual edge attached.
00163  * orig might be an input edge, reverse of an input edge, or virtual edge
00164  */
00165 edge_t *new_virtual_edge(node_t * u, node_t * v, edge_t * orig)
00166 {
00167     edge_t *e;
00168 
00169     e = NEW(edge_t);
00170     e->tail = u;
00171     e->head = v;
00172     ED_edge_type(e) = VIRTUAL;
00173 
00174     if (orig) {
00175         e->id = orig->id;
00176         ED_count(e) = ED_count(orig);
00177         ED_xpenalty(e) = ED_xpenalty(orig);
00178         ED_weight(e) = ED_weight(orig);
00179         ED_minlen(e) = ED_minlen(orig);
00180         if (e->tail == orig->tail)
00181             ED_tail_port(e) = ED_tail_port(orig);
00182         else if (e->tail == orig->head)
00183             ED_tail_port(e) = ED_head_port(orig);
00184         if (e->head == orig->head)
00185             ED_head_port(e) = ED_head_port(orig);
00186         else if (e->head == orig->tail)
00187             ED_head_port(e) = ED_tail_port(orig);
00188 
00189         if (ED_to_virt(orig) == NULL)
00190             ED_to_virt(orig) = e;
00191         ED_to_orig(e) = orig;
00192     } else
00193         ED_minlen(e) = ED_count(e) = ED_xpenalty(e) = ED_weight(e) = 1;
00194     return e;
00195 }
00196 
00197 edge_t *virtual_edge(node_t * u, node_t * v, edge_t * orig)
00198 {
00199     return fast_edge(new_virtual_edge(u, v, orig));
00200 }
00201 
00202 void fast_node(graph_t * g, Agnode_t * n)
00203 {
00204 
00205 #ifdef DEBUG
00206     assert(find_fast_node(g, n) == NULL);
00207 #endif
00208     ND_next(n) = GD_nlist(g);
00209     if (ND_next(n))
00210         ND_next(n)->u.prev = n;
00211     GD_nlist(g) = n;
00212     ND_prev(n) = NULL;
00213     assert(n != ND_next(n));
00214 }
00215 
00216 void fast_nodeapp(node_t * u, node_t * v)
00217 {
00218     assert(u != v);
00219     assert(ND_next(v) == NULL);
00220     ND_next(v) = ND_next(u);
00221     if (ND_next(u))
00222         ND_next(u)->u.prev = v;
00223     ND_prev(v) = u;
00224     ND_next(u) = v;
00225 }
00226 
00227 void delete_fast_node(graph_t * g, node_t * n)
00228 {
00229     assert(find_fast_node(g, n));
00230     if (ND_next(n))
00231         ND_next(n)->u.prev = ND_prev(n);
00232     if (ND_prev(n))
00233         ND_prev(n)->u.next = ND_next(n);
00234     else
00235         GD_nlist(g) = ND_next(n);
00236 }
00237 
00238 node_t *virtual_node(graph_t * g)
00239 {
00240     node_t *n;
00241 
00242     n = NEW(node_t);
00243     n->name = "virtual";
00244     n->graph = g;
00245     ND_node_type(n) = VIRTUAL;
00246     ND_lw_i(n) = ND_rw_i(n) = 1;
00247     ND_ht_i(n) = 1;
00248     ND_UF_size(n) = 1;
00249     alloc_elist(4, ND_in(n));
00250     alloc_elist(4, ND_out(n));
00251     fast_node(g, n);
00252     GD_n_nodes(g)++;
00253     return n;
00254 }
00255 
00256 void flat_edge(graph_t * g, edge_t * e)
00257 {
00258     elist_append(e, ND_flat_out(e->tail));
00259     elist_append(e, ND_flat_in(e->head));
00260     GD_has_flat_edges(g->root) = GD_has_flat_edges(g) = TRUE;
00261 }
00262 
00263 void delete_flat_edge(edge_t * e)
00264 {
00265     assert(e != NULL);
00266     if (ED_to_orig(e) && ED_to_virt(ED_to_orig(e)) == e)
00267         ED_to_virt(ED_to_orig(e)) = NULL;
00268     zapinlist(&(ND_flat_out(e->tail)), e);
00269     zapinlist(&(ND_flat_in(e->head)), e);
00270 }
00271 
00272 #ifdef DEBUG
00273 static char *NAME(node_t * n)
00274 {
00275     static char buf[20];
00276     if (ND_node_type(n) == NORMAL)
00277         return n->name;
00278     sprintf(buf, "V%x", n);
00279     return buf;
00280 }
00281 
00282 void fastgr(graph_t * g)
00283 {
00284     int i, j;
00285     node_t *n, *w;
00286     edge_t *e, *f;
00287 
00288     for (n = GD_nlist(g); n; n = ND_next(n)) {
00289         fprintf(stderr, "%s %d: (", NAME(n), ND_rank(n));
00290         for (i = 0; e = ND_out(n).list[i]; i++) {
00291             fprintf(stderr, " %s:%d", NAME(e->head), ED_count(e));
00292             w = e->head;
00293             if (g == g->root) {
00294                 for (j = 0; f = ND_in(w).list[j]; j++)
00295                     if (e == f)
00296                         break;
00297                 assert(f != NULL);
00298             }
00299         }
00300         fprintf(stderr, " ) (");
00301         for (i = 0; e = ND_in(n).list[i]; i++) {
00302             fprintf(stderr, " %s:%d", NAME(e->tail), ED_count(e));
00303             w = e->tail;
00304             if (g == g->root) {
00305                 for (j = 0; f = ND_out(w).list[j]; j++)
00306                     if (e == f)
00307                         break;
00308                 assert(f != NULL);
00309             }
00310         }
00311         fprintf(stderr, " )\n");
00312     }
00313 }
00314 #endif
00315 
00316 static void 
00317 basic_merge(edge_t * e, edge_t * rep)
00318 {
00319     if (ED_minlen(rep) < ED_minlen(e))
00320         ED_minlen(rep) = ED_minlen(e);
00321     while (rep) {
00322         ED_count(rep) += ED_count(e);
00323         ED_xpenalty(rep) += ED_xpenalty(e);
00324         ED_weight(rep) += ED_weight(e);
00325         rep = ED_to_virt(rep);
00326     }
00327 }
00328         
00329 void 
00330 merge_oneway(edge_t * e, edge_t * rep)
00331 {
00332     if (rep == ED_to_virt(e)) {
00333         agerr(AGWARN, "merge_oneway glitch\n");
00334         return;
00335     }
00336     assert(ED_to_virt(e) == NULL);
00337     ED_to_virt(e) = rep;
00338     basic_merge(e, rep);
00339 }
00340 
00341 static void 
00342 unrep(edge_t * rep, edge_t * e)
00343 {
00344     ED_count(rep) -= ED_count(e);
00345     ED_xpenalty(rep) -= ED_xpenalty(e);
00346     ED_weight(rep) -= ED_weight(e);
00347 }
00348 
00349 void unmerge_oneway(edge_t * e)
00350 {
00351     edge_t *rep, *nextrep;
00352     for (rep = ED_to_virt(e); rep; rep = nextrep) {
00353         unrep(rep, e);
00354         nextrep = ED_to_virt(rep);
00355         if (ED_count(rep) == 0)
00356             safe_delete_fast_edge(rep); /* free(rep)? */
00357 
00358         /* unmerge from a virtual edge chain */
00359         while ((ED_edge_type(rep) == VIRTUAL)
00360                && (ND_node_type(rep->head) == VIRTUAL)
00361                && (ND_out(rep->head).size == 1)) {
00362             rep = ND_out(rep->head).list[0];
00363             unrep(rep, e);
00364         }
00365     }
00366     ED_to_virt(e) = NULL;
00367 }
00368 
00369 #ifdef OBSOLETET
00370 static int 
00371 is_fast_node(graph_t * g, node_t * v)
00372 {
00373     node_t *n;
00374 
00375     for (n = GD_nlist(g); n; n = ND_next(n))
00376         if (v == n)
00377             return TRUE;
00378     return FALSE;
00379 }
00380 #endif

Generated on Mon Mar 31 19:03:26 2008 for Graphviz by  doxygen 1.5.1