22 int ptrcmp(const void *l
, const void *r
)
24 return ((ptrdiff_t)((struct node
*)l
)->data
)
25 -((ptrdiff_t)((struct node
*)r
)->data
);
28 int nodecmp(const void *l
, const void *r
)
30 return ((ptrdiff_t)l
) -((ptrdiff_t)((struct node
*)r
)->data
);
33 struct components
*strongconnect(struct node
*v
, struct node
**stack
, int *sp
,
34 int *index
, int nedges
, struct edge2
*edges
, struct components
*components
)
43 for (int i
= 0; i
<nedges
; i
++) {
44 if (edges
[i
].from
!= v
)
48 components
= strongconnect(w
, stack
, sp
, index
,
49 nedges
, edges
, components
);
50 } else if (w
->onStack
) {
51 v
->lowlink
= min(v
->lowlink
, w
->index
);
55 if (v
->lowlink
== v
->index
) {
56 struct list
*res
= NULL
;
60 res
= list_cons(w
->data
, res
);
62 struct components
*ng
= safe_malloc(sizeof(struct components
));
63 ng
->next
= components
;
64 ng
->nodes
= list_to_array(res
, &ng
->nnodes
, false);
70 struct components
*scc(int nnodes
, void **nodedata
, int nedges
, struct edge
*edgedata
)
72 struct components
*res
= NULL
;
73 struct node
*nodes
= safe_malloc(nnodes
*sizeof(struct node
));
74 for (int i
= 0; i
<nnodes
; i
++)
75 nodes
[i
] = (struct node
){.lowlink
=-1, .index
=-1,
76 .onStack
=false, .data
=nodedata
[i
]};
77 qsort(nodes
, nnodes
, sizeof(struct node
), ptrcmp
);
79 struct edge2
*edges
= safe_malloc(nedges
*sizeof(struct edge2
));
80 for (int i
= 0; i
<nedges
; i
++) {
81 struct node
*from
= bsearch(edgedata
[i
].from
, nodes
, nnodes
,
82 sizeof(struct node
), nodecmp
);
84 fprintf(stderr
, "edge from references unknown node\n");
87 struct node
*to
= bsearch(edgedata
[i
].to
, nodes
, nnodes
,
88 sizeof(struct node
), nodecmp
);
90 fprintf(stderr
, "edge to references unknown node\n");
93 edges
[i
] = (struct edge2
){.from
=from
, .to
=to
};
96 struct node
**stack
= safe_malloc(nnodes
*sizeof(struct node
*));
99 for (int i
= 0; i
< nnodes
; i
++)
100 if (nodes
[i
].index
== -1)
101 res
= strongconnect(&nodes
[i
], stack
, &sp
, &index
,
110 void components_free(struct components
*cs
, void (*freefun
)(void *))
114 for (int i
= 0; i
<cs
->nnodes
; i
++)
115 freefun(cs
->nodes
[i
]);
117 struct components
*t
= cs
->next
;
125 // void *nodes[] = {(void *)1, (void *)2, (void *)3};
126 // struct edge edges[] = {{(void *)1, (void *)2}, {(void *)2, (void *)1}};
127 // struct components *cs = scc(3, &nodes[0], 2, &edges[0]);
128 // FOREACHCOMP(c, cs) {
129 // fprintf(stderr, "comp: ");
130 // for (int i = 0; i<c->nnodes; i++)
131 // fprintf(stderr, "%d, ", c->nodes[i]);
132 // fprintf(stderr, "\n");
134 // components_free(cs, NULL);