2 * Copyright 2010-2011 INRIA Saclay
3 * Copyright 2012 Ecole Normale Superieure
5 * Use of this software is governed by the MIT license
7 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
8 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
10 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
15 #include <isl_tarjan.h>
17 struct isl_tarjan_graph
*isl_tarjan_graph_free(struct isl_tarjan_graph
*g
)
28 static struct isl_tarjan_graph
*isl_tarjan_graph_alloc(isl_ctx
*ctx
, int len
)
30 struct isl_tarjan_graph
*g
;
33 g
= isl_calloc_type(ctx
, struct isl_tarjan_graph
);
37 g
->node
= isl_alloc_array(ctx
, struct isl_tarjan_node
, len
);
40 for (i
= 0; i
< len
; ++i
)
41 g
->node
[i
].index
= -1;
42 g
->stack
= isl_alloc_array(ctx
, int, len
);
45 g
->order
= isl_alloc_array(ctx
, int, 2 * len
);
55 isl_tarjan_graph_free(g
);
59 /* Perform Tarjan's algorithm for computing the strongly connected components
60 * in the graph with g->len nodes and with edges defined by "follows".
62 static isl_stat
isl_tarjan_components(struct isl_tarjan_graph
*g
, int i
,
63 isl_bool (*follows
)(int i
, int j
, void *user
), void *user
)
67 g
->node
[i
].index
= g
->index
;
68 g
->node
[i
].min_index
= g
->index
;
69 g
->node
[i
].on_stack
= 1;
71 g
->stack
[g
->sp
++] = i
;
73 for (j
= g
->len
- 1; j
>= 0; --j
) {
78 if (g
->node
[j
].index
>= 0 &&
79 (!g
->node
[j
].on_stack
||
80 g
->node
[j
].index
> g
->node
[i
].min_index
))
83 f
= follows(i
, j
, user
);
85 return isl_stat_error
;
89 if (g
->node
[j
].index
< 0) {
90 isl_tarjan_components(g
, j
, follows
, user
);
91 if (g
->node
[j
].min_index
< g
->node
[i
].min_index
)
92 g
->node
[i
].min_index
= g
->node
[j
].min_index
;
93 } else if (g
->node
[j
].index
< g
->node
[i
].min_index
)
94 g
->node
[i
].min_index
= g
->node
[j
].index
;
97 if (g
->node
[i
].index
!= g
->node
[i
].min_index
)
101 j
= g
->stack
[--g
->sp
];
102 g
->node
[j
].on_stack
= 0;
103 g
->order
[g
->op
++] = j
;
105 g
->order
[g
->op
++] = -1;
110 /* Decompose the graph with "len" nodes and edges defined by "follows"
111 * into strongly connected components (SCCs).
112 * follows(i, j, user) should return 1 if "i" follows "j" and 0 otherwise.
113 * It should return -1 on error.
115 * If SCC a contains a node i that follows a node j in another SCC b
116 * (i.e., follows(i, j, user) returns 1), then SCC a will appear after SCC b
119 struct isl_tarjan_graph
*isl_tarjan_graph_init(isl_ctx
*ctx
, int len
,
120 isl_bool (*follows
)(int i
, int j
, void *user
), void *user
)
123 struct isl_tarjan_graph
*g
= NULL
;
125 g
= isl_tarjan_graph_alloc(ctx
, len
);
128 for (i
= len
- 1; i
>= 0; --i
) {
129 if (g
->node
[i
].index
>= 0)
131 if (isl_tarjan_components(g
, i
, follows
, user
) < 0)
132 return isl_tarjan_graph_free(g
);
138 /* Decompose the graph with "len" nodes and edges defined by "follows"
139 * into the strongly connected component (SCC) that contains "node"
140 * as well as all SCCs that are followed by this SCC.
141 * follows(i, j, user) should return 1 if "i" follows "j" and 0 otherwise.
142 * It should return -1 on error.
144 * The SCC containing "node" will appear as the last component
147 struct isl_tarjan_graph
*isl_tarjan_graph_component(isl_ctx
*ctx
, int len
,
148 int node
, isl_bool (*follows
)(int i
, int j
, void *user
), void *user
)
150 struct isl_tarjan_graph
*g
;
152 g
= isl_tarjan_graph_alloc(ctx
, len
);
155 if (isl_tarjan_components(g
, node
, follows
, user
) < 0)
156 return isl_tarjan_graph_free(g
);