Coverage Report

Created: 2025-11-14 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}