2
This software may only be used by you under license from AT&T Corp.
3
("AT&T"). A copy of AT&T's Source Code Agreement is available at
4
AT&T's Internet website having the URL:
5
<http://www.research.att.com/sw/tools/graphviz/license/source.html>
6
If you received this software without first entering into a license
7
with AT&T, you have an infringing copy of this software and cannot use
8
it without violating AT&T's intellectual property rights.
19
* operations on the fast internal graph.
22
static edge_t* ffe(node_t *u, elist uL, node_t *v, elist vL)
27
if (uL.size < vL.size) {
28
for (i = 0; (e = uL.list[i]); i++)
29
if (e->head == v) break;
32
for (i = 0; (e = vL.list[i]); i++)
33
if (e->tail == u) break;
38
edge_t* find_fast_edge(node_t *u,node_t *v)
40
return ffe(u,u->u.out,v,v->u.in);
43
node_t* find_fast_node(graph_t *g, node_t *n)
46
for (v = g->u.nlist; v; v = v->u.next)
51
edge_t* find_flat_edge(node_t *u, node_t *v)
53
return ffe(u,u->u.flat_out,v,v->u.flat_in);
56
/* safe_list_append - append e to list L only if e not already a member */
57
void safe_list_append(edge_t *e, elist *L)
61
for (i = 0; i < L->size; i++) if (e == L->list[i]) return;
71
for (i = 0; (f = e->tail->u.out.list[i]); i++) {
72
if (e == f) {fprintf(stderr,"duplicate fast edge\n"); return;}
73
assert (e->head != f->head);
75
for (i = 0; (f = e->head->u.in.list[i]); i++) {
76
if (e == f) {fprintf(stderr,"duplicate fast edge\n"); return;}
77
assert (e->tail != f->tail);
80
elist_append(e,e->tail->u.out);
81
elist_append(e,e->head->u.in);
85
/* zapinlist - remove e from list and fill hole with last member of list */
86
void zapinlist(elist *L, edge_t *e)
90
for (i = 0; i < L->size; i++) {
91
if (L->list[i] == e) {
93
L->list[i] = L->list[L->size];
94
L->list[L->size] = NULL;
100
/* disconnects e from graph */
101
void delete_fast_edge(edge_t *e)
104
zapinlist(&(e->tail->u.out),e);
105
zapinlist(&(e->head->u.in),e);
108
void safe_delete_fast_edge(edge_t *e)
114
for (i = 0; (f = e->tail->u.out.list[i]); i++)
115
if (f == e) zapinlist(&(e->tail->u.out),e);
116
for (i = 0; (f = e->head->u.in.list[i]); i++)
117
if (f == e) zapinlist(&(e->head->u.in),e);
120
void other_edge(edge_t *e)
122
elist_append(e,e->tail->u.other);
125
void safe_other_edge(edge_t *e)
127
safe_list_append(e,&(e->tail->u.other));
130
void delete_other_edge(edge_t *e)
133
zapinlist(&(e->tail->u.other),e);
136
/* orig might be an input edge, reverse of an input edge, or virtual edge */
138
new_virtual_edge(node_t *u, node_t *v, edge_t *orig)
145
e->u.edge_type = VIRTUAL;
148
e->u.count = orig->u.count;
149
e->u.xpenalty = orig->u.xpenalty;
150
e->u.weight = orig->u.weight;
151
e->u.minlen = orig->u.minlen;
152
if (e->tail == orig->tail) e->u.tail_port = orig->u.tail_port;
153
else if (e->tail == orig->head) e->u.tail_port = orig->u.head_port;
154
if (e->head == orig->head) e->u.head_port = orig->u.head_port;
155
else if (e->head == orig->tail) e->u.head_port = orig->u.tail_port;
157
if (orig->u.to_virt == NULL) orig->u.to_virt = e;
160
else e->u.minlen = e->u.count = e->u.xpenalty = e->u.weight = 1;
165
virtual_edge(node_t *u, node_t *v, edge_t *orig)
167
return fast_edge(new_virtual_edge(u,v,orig));
170
void fast_node(graph_t *g, Agnode_t *n)
174
assert (find_fast_node(g,n) == NULL);
176
n->u.next = g->u.nlist;
177
if (n->u.next) n->u.next->u.prev = n;
180
assert (n != n->u.next);
183
void fast_nodeapp(node_t *u, node_t *v)
186
assert (v->u.next == NULL);
187
v->u.next = u->u.next;
188
if (u->u.next) u->u.next->u.prev = v;
193
void delete_fast_node(graph_t *g, node_t *n)
195
assert(find_fast_node(g,n));
196
if (n->u.next) n->u.next->u.prev = n->u.prev;
197
if (n->u.prev) n->u.prev->u.next = n->u.next;
198
else g->u.nlist = n->u.next;
201
node_t* virtual_node(graph_t *g)
208
n->u.node_type = VIRTUAL;
209
n->u.lw = n->u.rw = 1;
212
alloc_elist(4,n->u.in);
213
alloc_elist(4,n->u.out);
219
void flat_edge(graph_t *g, edge_t *e)
221
elist_append(e,e->tail->u.flat_out);
222
elist_append(e,e->head->u.flat_in);
223
g->root->u.has_flat_edges = g->u.has_flat_edges = TRUE;
226
void delete_flat_edge(edge_t *e)
229
zapinlist(&(e->tail->u.flat_out),e);
230
zapinlist(&(e->head->u.flat_in),e);
238
if (n->u.node_type == NORMAL) return n->name;
239
sprintf(buf,"V%x",n);
243
void fastgr(graph_t *g)
249
for (n = g->u.nlist; n; n = n->u.next) {
250
fprintf(stderr,"%s %d: (",NAME(n), n->u.rank);
251
for (i = 0; e = n->u.out.list[i]; i++) {
252
fprintf(stderr," %s:%d",NAME(e->head),e->u.count);
255
for (j = 0; f = w->u.in.list[j]; j++) if (e == f) break;
259
fprintf(stderr," ) (");
260
for (i = 0; e = n->u.in.list[i]; i++) {
261
fprintf(stderr," %s:%d",NAME(e->tail),e->u.count);
264
for (j = 0; f = w->u.out.list[j]; j++) if (e == f) break;
268
fprintf(stderr," )\n");
273
void merge_oneway(edge_t *e, edge_t *rep)
275
if (rep == e->u.to_virt) {fprintf(stderr,"warning, merge_oneway glitch\n"); return;}
276
assert(e->u.to_virt == NULL);
281
void basic_merge(edge_t *e, edge_t *rep)
283
if (rep->u.minlen < e->u.minlen)
284
rep->u.minlen = e->u.minlen;
286
rep->u.count += e->u.count;
287
rep->u.xpenalty += e->u.xpenalty;
288
rep->u.weight += e->u.weight;
289
rep = rep->u.to_virt;
293
static void unrep(edge_t *rep, edge_t *e)
295
rep->u.count -= e->u.count;
296
rep->u.xpenalty -= e->u.xpenalty;
297
rep->u.weight -= e->u.weight;
300
void unmerge_oneway(edge_t *e)
302
edge_t *rep,*nextrep;
303
for (rep = e->u.to_virt; rep; rep = nextrep) {
305
nextrep = rep->u.to_virt;
306
if (rep->u.count == 0) safe_delete_fast_edge(rep); /* free(rep)? */
308
/* unmerge from a virtual edge chain */
309
while ((rep->u.edge_type == VIRTUAL)
310
&& (rep->head->u.node_type == VIRTUAL)
311
&& (rep->head->u.out.size == 1)) {
312
rep = rep->head->u.out.list[0];
319
int is_fast_node(graph_t *g, node_t *v)
323
for (n = g->u.nlist; n; n = n->u.next)
324
if (v == n) return TRUE;