Add shortcut to speed up gc_irgs()
[libfirm] / ir / adt / bipartite.c
1 /*
2  * Specialized implementation for perfect bipartite matching.
3  * @author Sebastian Hack
4  * @cvs-id $Id$
5  */
6
7 #include <stdio.h>
8 #include <assert.h>
9
10 #include "bitset.h"
11 #include "bipartite.h"
12 #include "xmalloc.h"
13
14 struct _bipartite_t {
15         int n_left, n_right;
16         bitset_t *adj[1];
17 };
18
19 bipartite_t *bipartite_new(int n_left, int n_right)
20 {
21         int i, size;
22         bipartite_t *gr;
23
24         size = n_left > 0 ? n_left - 1 : 0;
25         gr = xmalloc(sizeof(*gr) + size * sizeof(void *));
26         memset(gr, 0, sizeof(*gr));
27
28         gr->n_left = n_left;
29         gr->n_right = n_right;
30
31         for(i = 0; i < n_left; ++i)
32                 gr->adj[i] = bitset_malloc(n_right);
33
34         return gr;
35 }
36
37 void bipartite_free(bipartite_t *gr)
38 {
39         int i;
40         for(i = 0; i < gr->n_left; ++i)
41                 bitset_free(gr->adj[i]);
42         free(gr);
43 }
44
45 void bipartite_add(bipartite_t *gr, int i, int j)
46 {
47         assert(i < gr->n_left && j < gr->n_right);
48         bitset_set(gr->adj[i], j);
49 }
50
51 void bipartite_remv(bipartite_t *gr, int i, int j)
52 {
53         assert(i < gr->n_left && j < gr->n_right);
54         bitset_clear(gr->adj[i], j);
55 }
56
57 int bipartite_adj(const bipartite_t *gr, int i, int j)
58 {
59         assert(i < gr->n_left && j < gr->n_right);
60         return bitset_is_set(gr->adj[i], j);
61 }
62
63 static int apply_alternating_path(const bipartite_t *gr, int *matching,
64                 bitset_t *matched_left, bitset_t *matched_right)
65 {
66         int left, right;
67         int done_something = 0;
68         bitset_t *tmp = bitset_alloca(gr->n_right);
69
70         for(left = 0; left < gr->n_left; ++left) {
71                 bitset_t *left_adj = gr->adj[left];
72                 int i;
73
74                 bitset_copy(tmp, left_adj);
75
76                 if(matching[left] >= 0) {
77                         int old_right = matching[left];
78
79                         /* Check of all neighbors of the left node are already matched.
80                          * We cannot improve this edge then. */
81                         if(bitset_contains(left_adj, matched_right))
82                                 continue;
83
84                         bitset_andnot(tmp, matched_right);
85                         right = bitset_next_set(tmp, 0);
86
87                         assert(right != -1);
88
89                         /*
90                                 We have to find another left node which has the old right one as a neighbor.
91                                 This node must not be part of a matching
92                         */
93                         for(i = 0; i < gr->n_left; ++i)
94                                 if(i != left && bitset_is_set(gr->adj[i], old_right) && !bitset_is_set(matched_left, i))
95                                         break;
96
97                         /* If no such node can be found, exit. */
98                         if(i >= gr->n_left)
99                                 continue;
100
101                         /* Else, we can improve this edge. */
102                         matching[left] = right;
103                         matching[i] = old_right;
104                         bitset_set(matched_left, i);
105                         bitset_set(matched_right, right);
106                         done_something = 1;
107                 }
108
109
110                 /* We have to create a new single edge */
111                 else {
112                         assert(!bitset_is_set(matched_left, left));
113
114                         bitset_andnot(tmp, matched_right);
115                         if(bitset_popcnt(tmp) == 0)
116                                 continue;
117
118                         right = bitset_min(tmp);
119                         assert(!bitset_is_set(matched_right, right));
120                         matching[left] = right;
121                         bitset_set(matched_left, left);
122                         bitset_set(matched_right, right);
123                         done_something = 1;
124                 }
125         }
126
127         return done_something;
128 }
129
130 void bipartite_matching(const bipartite_t *gr, int *matching)
131 {
132         bitset_t *matched_left = bitset_alloca(gr->n_left);
133         bitset_t *matched_right = bitset_alloca(gr->n_right);
134
135         memset(matching, -1, gr->n_left * sizeof(int));
136         while(apply_alternating_path(gr, matching, matched_left, matched_right));
137 }
138
139 void bipartite_dump_f(FILE *f, const bipartite_t *gr)
140 {
141         int i;
142
143         for(i = 0; i < gr->n_left; ++i) {
144                 fprintf(f, "%d: ", i);
145                 bitset_fprint(f, gr->adj[i]);
146                 fprintf(f, "\n");
147         }
148 }
149
150 void bipartite_dump(const char *name, const bipartite_t *gr) {
151         FILE *f = fopen(name, "w");
152
153         if (f) {
154                 bipartite_dump_f(f, gr);
155                 fclose(f);
156         }
157 }