/src/igraph/src/core/buckets.c
Line | Count | Source |
1 | | /* |
2 | | igraph library. |
3 | | Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor@gmail.com> |
4 | | 334 Harvard street, Cambridge, MA 02139 USA |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 2 of the License, or |
9 | | (at your option) any later version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with this program; if not, write to the Free Software |
18 | | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
19 | | 02110-1301 USA |
20 | | |
21 | | */ |
22 | | |
23 | | #include "core/buckets.h" |
24 | | |
25 | | /* The igraph_buckets_t data structure can store at most 'size' |
26 | | * unique integers in 'bsize' buckets. It has the following simple |
27 | | * operations (in addition to _init() and _destroy(): |
28 | | * - _add() adding an element to the given bucket. |
29 | | * - _popmax() removing an element from the bucket with the highest |
30 | | * id. |
31 | | * Currently buckets work as stacks, last-in-first-out mode. |
32 | | * - _empty() queries whether the buckets is empty. |
33 | | * |
34 | | * Internal representation: we use a vector to create single linked |
35 | | * lists, and another vector that points to the starting element of |
36 | | * each bucket. Zero means the end of the chain. So bucket i contains |
37 | | * elements bptr[i], buckets[bptr[i]], buckets[buckets[bptr[i]]], |
38 | | * etc., until a zero is found. |
39 | | * |
40 | | * We also keep the total number of elements in the buckets and the |
41 | | * id of the non-empty bucket with the highest id, to facilitate the |
42 | | * _empty() and _popmax() operations. |
43 | | */ |
44 | | |
45 | 412k | igraph_error_t igraph_buckets_init(igraph_buckets_t *b, igraph_int_t bsize, igraph_int_t size) { |
46 | 412k | IGRAPH_VECTOR_INT_INIT_FINALLY(&b->bptr, bsize); |
47 | 412k | IGRAPH_VECTOR_INT_INIT_FINALLY(&b->buckets, size); |
48 | 412k | b->max = -1; b->no = 0; |
49 | 412k | IGRAPH_FINALLY_CLEAN(2); |
50 | 412k | return IGRAPH_SUCCESS; |
51 | 412k | } |
52 | | |
53 | 412k | void igraph_buckets_destroy(igraph_buckets_t *b) { |
54 | 412k | igraph_vector_int_destroy(&b->bptr); |
55 | 412k | igraph_vector_int_destroy(&b->buckets); |
56 | 412k | } |
57 | | |
58 | 26.5M | igraph_int_t igraph_buckets_popmax(igraph_buckets_t *b) { |
59 | | /* Precondition: there is at least a non-empty bucket */ |
60 | | /* Search for the highest bucket first */ |
61 | 26.5M | igraph_int_t max; |
62 | 37.0M | while ( (max = VECTOR(b->bptr)[b->max]) == 0) { |
63 | 10.5M | b->max --; |
64 | 10.5M | } |
65 | 26.5M | VECTOR(b->bptr)[b->max] = VECTOR(b->buckets)[max - 1]; |
66 | 26.5M | b->no--; |
67 | | |
68 | 26.5M | return max - 1; |
69 | 26.5M | } |
70 | | |
71 | 0 | igraph_int_t igraph_buckets_pop(igraph_buckets_t *b, igraph_int_t bucket) { |
72 | 0 | igraph_int_t ret = VECTOR(b->bptr)[bucket] - 1; |
73 | 0 | VECTOR(b->bptr)[bucket] = VECTOR(b->buckets)[ret]; |
74 | 0 | b->no--; |
75 | 0 | return ret; |
76 | 0 | } |
77 | | |
78 | 26.9M | igraph_bool_t igraph_buckets_empty(const igraph_buckets_t *b) { |
79 | 26.9M | return (b->no == 0); |
80 | 26.9M | } |
81 | | |
82 | | igraph_bool_t igraph_buckets_empty_bucket(const igraph_buckets_t *b, |
83 | 11.2M | igraph_int_t bucket) { |
84 | 11.2M | return VECTOR(b->bptr)[bucket] == 0; |
85 | 11.2M | } |
86 | | |
87 | | void igraph_buckets_add(igraph_buckets_t *b, igraph_int_t bucket, |
88 | 26.9M | igraph_int_t elem) { |
89 | | |
90 | 26.9M | VECTOR(b->buckets)[elem] = VECTOR(b->bptr)[bucket]; |
91 | 26.9M | VECTOR(b->bptr)[bucket] = elem + 1; |
92 | 26.9M | if (bucket > b->max) { |
93 | 8.44M | b->max = bucket; |
94 | 8.44M | } |
95 | 26.9M | b->no++; |
96 | 26.9M | } |
97 | | |
98 | 517k | void igraph_buckets_clear(igraph_buckets_t *b) { |
99 | 517k | igraph_vector_int_null(&b->bptr); |
100 | 517k | igraph_vector_int_null(&b->buckets); |
101 | 517k | b->max = -1; |
102 | 517k | b->no = 0; |
103 | 517k | } |
104 | | |
105 | 412k | igraph_error_t igraph_dbuckets_init(igraph_dbuckets_t *b, igraph_int_t bsize, igraph_int_t size) { |
106 | 412k | IGRAPH_VECTOR_INT_INIT_FINALLY(&b->bptr, bsize); |
107 | 412k | IGRAPH_VECTOR_INT_INIT_FINALLY(&b->next, size); |
108 | 412k | IGRAPH_VECTOR_INT_INIT_FINALLY(&b->prev, size); |
109 | 412k | b->max = -1; b->no = 0; |
110 | 412k | IGRAPH_FINALLY_CLEAN(3); |
111 | 412k | return IGRAPH_SUCCESS; |
112 | 412k | } |
113 | | |
114 | 412k | void igraph_dbuckets_destroy(igraph_dbuckets_t *b) { |
115 | 412k | igraph_vector_int_destroy(&b->bptr); |
116 | 412k | igraph_vector_int_destroy(&b->next); |
117 | 412k | igraph_vector_int_destroy(&b->prev); |
118 | 412k | } |
119 | | |
120 | 460k | void igraph_dbuckets_clear(igraph_dbuckets_t *b) { |
121 | 460k | igraph_vector_int_null(&b->bptr); |
122 | 460k | igraph_vector_int_null(&b->next); |
123 | 460k | igraph_vector_int_null(&b->prev); |
124 | 460k | b->max = -1; |
125 | 460k | b->no = 0; |
126 | 460k | } |
127 | | |
128 | 0 | igraph_int_t igraph_dbuckets_popmax(igraph_dbuckets_t *b) { |
129 | 0 | while ( VECTOR(b->bptr)[b->max] == 0) { |
130 | 0 | b->max--; |
131 | 0 | } |
132 | 0 | return igraph_dbuckets_pop(b, b->max); |
133 | 0 | } |
134 | | |
135 | 5.97M | igraph_int_t igraph_dbuckets_pop(igraph_dbuckets_t *b, igraph_int_t bucket) { |
136 | 5.97M | igraph_int_t ret = VECTOR(b->bptr)[bucket] - 1; |
137 | 5.97M | igraph_int_t next = VECTOR(b->next)[ret]; |
138 | 5.97M | VECTOR(b->bptr)[bucket] = next; |
139 | 5.97M | if (next != 0) { |
140 | 4.90M | VECTOR(b->prev)[next - 1] = 0; |
141 | 4.90M | } |
142 | | |
143 | 5.97M | b->no--; |
144 | 5.97M | return ret; |
145 | 5.97M | } |
146 | | |
147 | 0 | igraph_bool_t igraph_dbuckets_empty(const igraph_dbuckets_t *b) { |
148 | 0 | return (b->no == 0); |
149 | 0 | } |
150 | | |
151 | | igraph_bool_t igraph_dbuckets_empty_bucket(const igraph_dbuckets_t *b, |
152 | 62.3M | igraph_int_t bucket) { |
153 | 62.3M | return VECTOR(b->bptr)[bucket] == 0; |
154 | 62.3M | } |
155 | | |
156 | | void igraph_dbuckets_add(igraph_dbuckets_t *b, igraph_int_t bucket, |
157 | 47.4M | igraph_int_t elem) { |
158 | 47.4M | igraph_int_t oldfirst = VECTOR(b->bptr)[bucket]; |
159 | 47.4M | VECTOR(b->bptr)[bucket] = elem + 1; |
160 | 47.4M | VECTOR(b->next)[elem] = oldfirst; |
161 | 47.4M | if (oldfirst != 0) { |
162 | 39.4M | VECTOR(b->prev)[oldfirst - 1] = elem + 1; |
163 | 39.4M | } |
164 | 47.4M | if (bucket > b->max) { |
165 | 5.70M | b->max = bucket; |
166 | 5.70M | } |
167 | 47.4M | b->no++; |
168 | 47.4M | } |
169 | | |
170 | | /* Remove an arbitrary element */ |
171 | | |
172 | | void igraph_dbuckets_delete(igraph_dbuckets_t *b, igraph_int_t bucket, |
173 | 23.0M | igraph_int_t elem) { |
174 | 23.0M | if (VECTOR(b->bptr)[bucket] == elem + 1) { |
175 | | /* First element in bucket */ |
176 | 10.4M | igraph_int_t next = VECTOR(b->next)[elem]; |
177 | 10.4M | if (next != 0) { |
178 | 7.97M | VECTOR(b->prev)[next - 1] = 0; |
179 | 7.97M | } |
180 | 10.4M | VECTOR(b->bptr)[bucket] = next; |
181 | 12.6M | } else { |
182 | 12.6M | igraph_int_t next = VECTOR(b->next)[elem]; |
183 | 12.6M | igraph_int_t prev = VECTOR(b->prev)[elem]; |
184 | 12.6M | if (next != 0) { |
185 | 10.9M | VECTOR(b->prev)[next - 1] = prev; |
186 | 10.9M | } |
187 | 12.6M | if (prev != 0) { |
188 | 12.6M | VECTOR(b->next)[prev - 1] = next; |
189 | 12.6M | } |
190 | 12.6M | } |
191 | 23.0M | b->no--; |
192 | 23.0M | } |