Graphviz 14.1.3~dev.20260204.1019
Loading...
Searching...
No Matches
fastgr.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "config.h"
12
13#include <dotgen/dot.h>
14#include <stdbool.h>
15#include <stddef.h>
16#include <util/alloc.h>
17#include <util/unused.h>
18
19/*
20 * operations on the fast internal graph.
21 */
22
23static edge_t *ffe(node_t * u, elist uL, node_t * v, elist vL)
24{
25 int i;
26 edge_t *e;
27
28 if (uL.size > 0 && vL.size > 0) {
29 if (uL.size < vL.size) {
30 for (i = 0; (e = uL.list[i]); i++)
31 if (aghead(e) == v)
32 break;
33 } else {
34 for (i = 0; (e = vL.list[i]); i++)
35 if (agtail(e) == u)
36 break;
37 }
38 } else
39 e = 0;
40 return e;
41}
42
44{
45 return ffe(u, ND_out(u), v, ND_in(v));
46}
47
49 node_t *v;
50 for (v = GD_nlist(g); v; v = ND_next(v))
51 if (v == n)
52 break;
53 return v;
54}
55
57{
58 return ffe(u, ND_flat_out(u), v, ND_flat_in(v));
59}
60
62static void
64{
65 for (size_t i = 0; i < L->size; i++)
66 if (e == L->list[i])
67 return;
68 elist_append(e, (*L));
69}
70
72{
73#ifdef DEBUG
74 edge_t *f;
75 for (int i = 0; (f = ND_out(agtail(e)).list[i]); i++) {
76 if (e == f) {
77 fprintf(stderr, "duplicate fast edge\n");
78 return 0;
79 }
80 assert(aghead(e) != aghead(f));
81 }
82 for (int i = 0; (f = ND_in(aghead(e)).list[i]); i++) {
83 if (e == f) {
84 fprintf(stderr, "duplicate fast edge\n");
85 return 0;
86 }
87 assert(agtail(e) != agtail(f));
88 }
89#endif
92 return e;
93}
94
96void zapinlist(elist * L, edge_t * e)
97{
98 for (size_t i = 0; i < L->size; i++) {
99 if (L->list[i] == e) {
100 L->size--;
101 L->list[i] = L->list[L->size];
102 L->list[L->size] = NULL;
103 break;
104 }
105 }
106}
107
108/* disconnects e from graph */
110{
111 assert(e != NULL);
112 zapinlist(&ND_out(agtail(e)), e);
113 zapinlist(&ND_in(aghead(e)), e);
114}
115
117{
119}
120
122{
124}
125
126/* Create and return a new virtual edge e attached to orig.
127 * ED_to_orig(e) = orig
128 * ED_to_virt(orig) = e if e is the first virtual edge attached.
129 * orig might be an input edge, reverse of an input edge, or virtual edge
130 */
132{
133 Agedgepair_t* e2 = gv_alloc(sizeof(Agedgepair_t));
134 AGTYPE(&e2->in) = AGINEDGE;
135 AGTYPE(&e2->out) = AGOUTEDGE;
136 e2->out.base.data = gv_alloc(sizeof(Agedgeinfo_t));
137 edge_t *e = &e2->out;
138 agtail(e) = u;
139 aghead(e) = v;
141
142 if (orig) {
143 AGSEQ(e) = AGSEQ(orig);
144 AGSEQ(&(e2->in)) = AGSEQ(orig);
145 ED_count(e) = ED_count(orig);
146 ED_xpenalty(e) = ED_xpenalty(orig);
147 ED_weight(e) = ED_weight(orig);
148 ED_minlen(e) = ED_minlen(orig);
149 if (agtail(e) == agtail(orig))
150 ED_tail_port(e) = ED_tail_port(orig);
151 else if (agtail(e) == aghead(orig))
152 ED_tail_port(e) = ED_head_port(orig);
153 if (aghead(e) == aghead(orig))
154 ED_head_port(e) = ED_head_port(orig);
155 else if (aghead(e) == agtail(orig))
156 ED_head_port(e) = ED_tail_port(orig);
157
158 if (ED_to_virt(orig) == NULL)
159 ED_to_virt(orig) = e;
160 ED_to_orig(e) = orig;
161 } else {
162 ED_weight(e) = 1;
163 ED_xpenalty(e) = 1;
164 ED_count(e) = 1;
165 ED_minlen(e) = 1;
166 }
167 return e;
168}
169
171{
172 return fast_edge(new_virtual_edge(u, v, orig));
173}
174
176{
177
178#ifdef DEBUG
179 assert(find_fast_node(g, n) == NULL);
180#endif
181 ND_next(n) = GD_nlist(g);
182 if (ND_next(n))
183 ND_prev(ND_next(n)) = n;
184 GD_nlist(g) = n;
185 ND_prev(n) = NULL;
186 assert(n != ND_next(n));
187}
188
190{
191 assert(find_fast_node(g, n));
192 if (ND_next(n))
193 ND_prev(ND_next(n)) = ND_prev(n);
194 if (ND_prev(n))
195 ND_next(ND_prev(n)) = ND_next(n);
196 else
197 GD_nlist(g) = ND_next(n);
198}
199
201 node_t *n = gv_alloc(sizeof(node_t));
202 AGTYPE(n) = AGNODE;
203 n->base.data = gv_alloc(sizeof(Agnodeinfo_t));
204 n->root = agroot(g);
206 ND_lw(n) = ND_rw(n) = 1;
207 ND_ht(n) = 1;
208 ND_UF_size(n) = 1;
209 alloc_elist(4, ND_in(n));
210 alloc_elist(4, ND_out(n));
211 fast_node(g, n);
212 return n;
213}
214
216{
220}
221
223{
224 assert(e != NULL);
225 if (ED_to_orig(e) && ED_to_virt(ED_to_orig(e)) == e)
228 zapinlist(&ND_flat_in(aghead(e)), e);
229}
230
231static void
233{
234 if (ED_minlen(rep) < ED_minlen(e))
235 ED_minlen(rep) = ED_minlen(e);
236 while (rep) {
237 ED_count(rep) += ED_count(e);
238 ED_xpenalty(rep) += ED_xpenalty(e);
239 ED_weight(rep) += ED_weight(e);
240 rep = ED_to_virt(rep);
241 }
242}
243
244void
246{
247 if (rep == ED_to_virt(e) || e == ED_to_virt(rep)) {
248 agwarningf("merge_oneway glitch\n");
249 return;
250 }
251 assert(ED_to_virt(e) == NULL);
252 ED_to_virt(e) = rep;
253 basic_merge(e, rep);
254}
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
Definition alloc.h:47
#define VIRTUAL
Definition const.h:25
Agraph_t * dot_root(void *p)
Definition dotinit.c:515
static void safe_list_append(edge_t *e, elist *L)
append e to list L only if e not already a member
Definition fastgr.c:63
void zapinlist(elist *L, edge_t *e)
remove e from list and fill hole with last member of list
Definition fastgr.c:96
void delete_fast_edge(edge_t *e)
Definition fastgr.c:109
edge_t * find_flat_edge(node_t *u, node_t *v)
Definition fastgr.c:56
edge_t * new_virtual_edge(node_t *u, node_t *v, edge_t *orig)
Definition fastgr.c:131
static UNUSED node_t * find_fast_node(graph_t *g, node_t *n)
Definition fastgr.c:48
static edge_t * ffe(node_t *u, elist uL, node_t *v, elist vL)
Definition fastgr.c:23
void fast_node(graph_t *g, Agnode_t *n)
Definition fastgr.c:175
node_t * virtual_node(graph_t *g)
Definition fastgr.c:200
void flat_edge(graph_t *g, edge_t *e)
Definition fastgr.c:215
edge_t * find_fast_edge(node_t *u, node_t *v)
Definition fastgr.c:43
void other_edge(edge_t *e)
Definition fastgr.c:116
void delete_flat_edge(edge_t *e)
Definition fastgr.c:222
edge_t * fast_edge(edge_t *e)
Definition fastgr.c:71
static void basic_merge(edge_t *e, edge_t *rep)
Definition fastgr.c:232
void merge_oneway(edge_t *e, edge_t *rep)
Definition fastgr.c:245
void delete_fast_node(graph_t *g, node_t *n)
Definition fastgr.c:189
void safe_other_edge(edge_t *e)
Definition fastgr.c:121
edge_t * virtual_edge(node_t *u, node_t *v, edge_t *orig)
Definition fastgr.c:170
static attrs_t * L
Definition gmlparse.c:94
node NULL
Definition grammar.y:181
#define ED_to_orig(e)
Definition types.h:598
#define ED_minlen(e)
Definition types.h:592
#define ED_xpenalty(e)
Definition types.h:601
#define ED_count(e)
Definition types.h:580
#define agtail(e)
Definition cgraph.h:977
#define ED_edge_type(e)
Definition types.h:582
#define ED_weight(e)
Definition types.h:603
#define aghead(e)
Definition cgraph.h:978
#define ED_head_port(e)
Definition types.h:588
#define ED_tail_port(e)
Definition types.h:597
#define ED_to_virt(e)
Definition types.h:599
void agwarningf(const char *fmt,...)
Definition agerror.c:175
#define GD_has_flat_edges(g)
Definition types.h:370
#define GD_nlist(g)
Definition types.h:393
#define ND_prev(n)
Definition types.h:521
#define ND_ht(n)
Definition types.h:500
#define ND_next(n)
Definition types.h:510
#define ND_other(n)
Definition types.h:514
#define ND_flat_out(n)
Definition types.h:493
#define ND_rw(n)
Definition types.h:525
#define ND_node_type(n)
Definition types.h:511
#define ND_lw(n)
Definition types.h:506
#define ND_UF_size(n)
Definition types.h:487
#define ND_flat_in(n)
Definition types.h:492
#define ND_in(n)
Definition types.h:501
#define ND_out(n)
Definition types.h:515
#define AGTYPE(obj)
returns AGRAPH, AGNODE, or AGEDGE depending on the type of the object
Definition cgraph.h:216
Agraph_t * agroot(void *obj)
Definition obj.c:170
#define AGSEQ(obj)
Definition cgraph.h:225
@ AGOUTEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
@ AGINEDGE
Definition cgraph.h:207
Agobj_t base
Definition cgraph.h:269
Agedge_t in
Definition cgraph.h:276
Agedge_t out
Definition cgraph.h:276
Agraph_t * root
Definition cgraph.h:261
Agobj_t base
Definition cgraph.h:260
Agrec_t * data
stores programmer-defined data, access with AGDATA
Definition cgraph.h:212
graph or subgraph
Definition cgraph.h:424
Definition types.h:251
edge_t ** list
Definition types.h:252
size_t size
Definition types.h:253
#define elist_append(item, L)
Definition types.h:261
#define alloc_elist(n, L)
Definition types.h:267
abstraction for squashing compiler warnings for unused symbols
#define UNUSED
Definition unused.h:25