Coverage Report

Created: 2025-08-29 06:49

/src/igraph/src/graph/iterators.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   IGraph library.
3
   Copyright (C) 2005-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 "igraph_datatype.h"
24
#include "igraph_error.h"
25
#include "igraph_iterators.h"
26
#include "igraph_memory.h"
27
#include "igraph_interface.h"
28
#include "igraph_types.h"
29
30
#include <string.h>
31
#include <stdarg.h>
32
33
/**
34
 * \section about_iterators About selectors, iterators
35
 *
36
 * <para>Everything about vertices and vertex selectors also applies
37
 * to edges and edge selectors unless explicitly noted otherwise.</para>
38
 *
39
 * <para>The vertex (and edge) selector notion was introduced in igraph 0.2.
40
 * It is a way to reference a sequence of vertices or edges
41
 * independently of the graph.</para>
42
 *
43
 * <para>While this might sound quite mysterious, it is actually very
44
 * simple. For example, all vertices of a graph can be selected by
45
 * \ref igraph_vs_all() and the graph independence means that
46
 * \ref igraph_vs_all() is not parametrized by a graph object. That is,
47
 * \ref igraph_vs_all() is the general \em concept of selecting all vertices
48
 * of a graph. A vertex selector is then a way to specify the class of vertices
49
 * to be visited. The selector might specify that all vertices of a graph or
50
 * all the neighbours of a vertex are to be visited. A vertex selector is a
51
 * way of saying that you want to visit a bunch of vertices, as opposed to a
52
 * vertex iterator which is a concrete plan for visiting each of the
53
 * chosen vertices of a specific graph.</para>
54
 *
55
 * <para>To determine the actual vertex IDs implied by a vertex selector, you
56
 * need to apply the concept of selecting vertices to a specific graph object.
57
 * This can be accomplished by instantiating a vertex iterator using a
58
 * specific vertex selection concept and a specific graph object. The notion
59
 * of vertex iterators can be thought of in the following way. Given a
60
 * specific graph object and the class of vertices to be visited, a vertex
61
 * iterator is a road map, plan or route for how to visit the chosen
62
 * vertices.</para>
63
 *
64
 * <para>Some vertex selectors have \em immediate versions. These have the
65
 * prefix \c igraph_vss instead of \c igraph_vs, e.g. \ref igraph_vss_all()
66
 * instead of \ref igraph_vs_all(). The immediate versions are to be used in
67
 * the parameter list of the igraph functions, such as \ref igraph_degree().
68
 * These functions are not associated with any \type igraph_vs_t object, so
69
 * they have no separate constructors and destructors
70
 * (destroy functions).</para>
71
 */
72
73
/**
74
 * \section about_vertex_selectors
75
 *
76
 * <para>Vertex selectors are created by vertex selector constructors,
77
 * can be instantiated with \ref igraph_vit_create(), and are
78
 * destroyed with \ref igraph_vs_destroy().</para>
79
 */
80
81
/**
82
 * \function igraph_vs_all
83
 * \brief Vertex set, all vertices of a graph.
84
 *
85
 * \param vs Pointer to an uninitialized \type igraph_vs_t object.
86
 * \return Error code.
87
 * \sa \ref igraph_vss_all(), \ref igraph_vs_destroy()
88
 *
89
 * This selector includes all vertices of a given graph in
90
 * increasing vertex ID order.
91
 *
92
 * </para><para>
93
 * Time complexity: O(1).
94
 */
95
96
0
igraph_error_t igraph_vs_all(igraph_vs_t *vs) {
97
0
    vs->type = IGRAPH_VS_ALL;
98
0
    return IGRAPH_SUCCESS;
99
0
}
100
101
/**
102
 * \function igraph_vss_all
103
 * \brief All vertices of a graph (immediate version).
104
 *
105
 * Immediate vertex selector for all vertices in a graph. It can
106
 * be used conveniently when some vertex property (e.g. betweenness,
107
 * degree, etc.) should be calculated for all vertices.
108
 *
109
 * \return A vertex selector for all vertices in a graph.
110
 * \sa \ref igraph_vs_all()
111
 *
112
 * Time complexity: O(1).
113
 */
114
115
945
igraph_vs_t igraph_vss_all(void) {
116
945
    igraph_vs_t allvs;
117
945
    allvs.type = IGRAPH_VS_ALL;
118
945
    return allvs;
119
945
}
120
121
/**
122
 * \function igraph_vs_adj
123
 * \brief Adjacent vertices of a vertex.
124
 *
125
 * All neighboring vertices of a given vertex are selected by this
126
 * selector. The \c mode argument controls the type of the neighboring
127
 * vertices to be selected. The vertices are visited in increasing vertex
128
 * ID order, as of igraph version 0.4.
129
 *
130
 * \param vs Pointer to an uninitialized vertex selector object.
131
 * \param vid Vertex ID, the center of the neighborhood.
132
 * \param mode Decides the type of the neighborhood for directed
133
 *        graphs. This parameter is ignored for undirected graphs.
134
 *        Possible values:
135
 *        \clist
136
 *        \cli IGRAPH_OUT
137
 *          All vertices to which there is a directed edge from \c vid. That
138
 *          is, all the out-neighbors of \c vid.
139
 *        \cli IGRAPH_IN
140
 *          All vertices from which there is a directed edge to \c vid. In
141
 *          other words, all the in-neighbors of \c vid.
142
 *        \cli IGRAPH_ALL
143
 *          All vertices to which or from which there is a directed edge
144
 *          from/to \c vid. That is, all the neighbors of \c vid considered
145
 *          as if the graph is undirected.
146
 *        \endclist
147
 * \param loops Whether to include the vertex itself in the neighborhood if the
148
 *        vertex has a loop edge. If \c IGRAPH_NO_LOOPS, loop edges are
149
 *        excluded. If \c IGRAPH_LOOPS_ONCE, the vertex is included in its own
150
 *        neighborhood once for every loop edge that it has. If
151
 *        \c IGRAPH_LOOPS_TWICE, the vertex is included twice in its own
152
 *        neighborhood for every loop edge that it has, but only if the graph is
153
 *        undirected or \p mode is set to \c IGRAPH_ALL.
154
 * \param multiple Whether to include multiple edges. If \c IGRAPH_NO_MULTIPLE,
155
 *        multiple edges are not included in the neighborhood. If
156
 *        \c IGRAPH_MULTIPLE, multiple edges are included in the neighborhood.
157
 *
158
 * \return Error code.
159
 * \sa \ref igraph_vs_destroy()
160
 *
161
 * Time complexity: O(1).
162
 */
163
164
igraph_error_t igraph_vs_adj(
165
    igraph_vs_t *vs, igraph_integer_t vid, igraph_neimode_t mode,
166
    igraph_loops_t loops, igraph_bool_t multiple
167
0
) {
168
0
    vs->type = IGRAPH_VS_ADJ;
169
0
    vs->data.adj.vid = vid;
170
0
    vs->data.adj.mode = mode;
171
0
    vs->data.adj.loops = loops;
172
0
    vs->data.adj.multiple = multiple;
173
0
    return IGRAPH_SUCCESS;
174
0
}
175
176
/**
177
 * \function igraph_vs_nonadj
178
 * \brief Non-adjacent vertices of a vertex.
179
 *
180
 * All non-neighboring vertices of a given vertex. The \p mode
181
 * argument controls the type of neighboring vertices \em not to
182
 * select. Instead of selecting immediate neighbors of \c vid as is done by
183
 * \ref igraph_vs_adj(), the current function selects vertices that are \em not
184
 * immediate neighbors of \c vid.
185
 *
186
 * \param vs Pointer to an uninitialized vertex selector object.
187
 * \param vid Vertex ID, the \quote center \endquote of the
188
 *        non-neighborhood.
189
 * \param mode The type of neighborhood not to select in directed
190
 *        graphs. Possible values:
191
 *        \clist
192
 *        \cli IGRAPH_OUT
193
 *          All vertices will be selected except those to which there is a
194
 *          directed edge from \c vid. That is, we select all vertices
195
 *          excluding the out-neighbors of \c vid.
196
 *        \cli IGRAPH_IN
197
 *          All vertices will be selected except those from which there is a
198
 *          directed edge to \c vid. In other words, we select all vertices
199
 *          but the in-neighbors of \c vid.
200
 *        \cli IGRAPH_ALL
201
 *          All vertices will be selected except those from or to which there
202
 *          is a directed edge to or from \c vid. That is, we select all
203
 *          vertices of \c vid except for its immediate neighbors.
204
 *        \endclist
205
 * \return Error code.
206
 * \sa \ref igraph_vs_destroy()
207
 *
208
 * Time complexity: O(1).
209
 *
210
 * \example examples/simple/igraph_vs_nonadj.c
211
 */
212
213
igraph_error_t igraph_vs_nonadj(igraph_vs_t *vs, igraph_integer_t vid,
214
0
                     igraph_neimode_t mode) {
215
0
    vs->type = IGRAPH_VS_NONADJ;
216
0
    vs->data.adj.vid = vid;
217
0
    vs->data.adj.mode = mode;
218
0
    vs->data.adj.loops = IGRAPH_LOOPS;
219
0
    vs->data.adj.multiple = IGRAPH_MULTIPLE;
220
0
    return IGRAPH_SUCCESS;
221
0
}
222
223
/**
224
 * \function igraph_vs_none
225
 * \brief Empty vertex set.
226
 *
227
 * Creates an empty vertex selector.
228
 *
229
 * \param vs Pointer to an uninitialized vertex selector object.
230
 * \return Error code.
231
 * \sa \ref igraph_vss_none(), \ref igraph_vs_destroy()
232
 *
233
 * Time complexity: O(1).
234
 */
235
236
0
igraph_error_t igraph_vs_none(igraph_vs_t *vs) {
237
0
    vs->type = IGRAPH_VS_NONE;
238
0
    return IGRAPH_SUCCESS;
239
0
}
240
241
/**
242
 * \function igraph_vss_none
243
 * \brief Empty vertex set (immediate version).
244
 *
245
 * The immediate version of the empty vertex selector.
246
 *
247
 * \return An empty vertex selector.
248
 * \sa \ref igraph_vs_none()
249
 *
250
 * Time complexity: O(1).
251
 */
252
253
0
igraph_vs_t igraph_vss_none(void) {
254
0
    igraph_vs_t nonevs;
255
0
    nonevs.type = IGRAPH_VS_NONE;
256
0
    return nonevs;
257
0
}
258
259
/**
260
 * \function igraph_vs_1
261
 * \brief Vertex set with a single vertex.
262
 *
263
 * This vertex selector selects a single vertex.
264
 *
265
 * \param vs Pointer to an uninitialized vertex selector object.
266
 * \param vid The vertex ID to be selected.
267
 * \return Error Code.
268
 * \sa \ref igraph_vss_1(), \ref igraph_vs_destroy()
269
 *
270
 * Time complexity: O(1).
271
 */
272
273
0
igraph_error_t igraph_vs_1(igraph_vs_t *vs, igraph_integer_t vid) {
274
0
    vs->type = IGRAPH_VS_1;
275
0
    vs->data.vid = vid;
276
0
    return IGRAPH_SUCCESS;
277
0
}
278
279
/**
280
 * \function igraph_vss_1
281
 * \brief Vertex set with a single vertex (immediate version).
282
 *
283
 * The immediate version of the single-vertex selector.
284
 *
285
 * \param vid The vertex to be selected.
286
 * \return A vertex selector containing a single vertex.
287
 * \sa \ref igraph_vs_1()
288
 *
289
 * Time complexity: O(1).
290
 */
291
292
7.14M
igraph_vs_t igraph_vss_1(igraph_integer_t vid) {
293
7.14M
    igraph_vs_t onevs;
294
7.14M
    onevs.type = IGRAPH_VS_1;
295
7.14M
    onevs.data.vid = vid;
296
7.14M
    return onevs;
297
7.14M
}
298
299
/**
300
 * \function igraph_vs_vector
301
 * \brief Vertex set based on a vector.
302
 *
303
 * This function makes it possible to handle an \type igraph_vector_int_t
304
 * temporarily as a vertex selector. The vertex selector should be
305
 * thought of as a \em view into the vector. If you make changes to
306
 * the vector that also affects the vertex selector. Destroying the
307
 * vertex selector does not destroy the vector. Do not destroy the
308
 * vector before destroying the vertex selector, or you might get
309
 * strange behavior. Since selectors are not tied to any specific
310
 * graph, this function does not check whether the vertex IDs in
311
 * the vector are valid.
312
 *
313
 * \param vs Pointer to an uninitialized vertex selector.
314
 * \param v Pointer to a \type igraph_vector_int_t object.
315
 * \return Error code.
316
 * \sa \ref igraph_vss_vector(), \ref igraph_vs_destroy()
317
 *
318
 * Time complexity: O(1).
319
 *
320
 * \example examples/simple/igraph_vs_vector.c
321
 */
322
323
igraph_error_t igraph_vs_vector(igraph_vs_t *vs,
324
0
                     const igraph_vector_int_t *v) {
325
0
    vs->type = IGRAPH_VS_VECTORPTR;
326
0
    vs->data.vecptr = v;
327
0
    return IGRAPH_SUCCESS;
328
0
}
329
330
/**
331
 * \function igraph_vss_vector
332
 * \brief Vertex set based on a vector (immediate version).
333
 *
334
 * This is the immediate version of \ref igraph_vs_vector.
335
 *
336
 * \param v Pointer to a \type igraph_vector_int_t object.
337
 * \return A vertex selector object containing the vertices in the
338
 *         vector.
339
 * \sa \ref igraph_vs_vector()
340
 *
341
 * Time complexity: O(1).
342
 */
343
344
0
igraph_vs_t igraph_vss_vector(const igraph_vector_int_t *v) {
345
0
    igraph_vs_t vecvs;
346
0
    vecvs.type = IGRAPH_VS_VECTORPTR;
347
0
    vecvs.data.vecptr = v;
348
0
    return vecvs;
349
0
}
350
351
/**
352
 * \function igraph_vs_vector_small
353
 * \brief Create a vertex set by giving its elements.
354
 *
355
 * This function can be used to create a vertex selector with a few
356
 * of vertices. Do not forget to include a <code>-1</code> after the
357
 * last vertex ID. The behavior of the function is undefined if you
358
 * don't use a <code>-1</code> properly.
359
 *
360
 * </para><para>
361
 * Note that the vertex IDs supplied will be parsed as value of type
362
 * \type int so you cannot supply arbitrarily large (too
363
 * large for \type int) vertex IDs here.
364
 *
365
 * \param vs Pointer to an uninitialized vertex selector object.
366
 * \param ... Additional parameters, these will be the vertex IDs to
367
 *        be included in the vertex selector. Supply a <code>-1</code>
368
 *        after the last vertex ID.
369
 * \return Error code.
370
 * \sa \ref igraph_vs_destroy()
371
 *
372
 * Time complexity: O(n), the number of vertex IDs supplied.
373
 */
374
375
0
igraph_error_t igraph_vs_vector_small(igraph_vs_t *vs, ...) {
376
0
    va_list ap;
377
0
    igraph_integer_t i, n = 0;
378
0
    igraph_vector_int_t* vec;
379
380
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
381
0
    IGRAPH_CHECK_OOM(vec, "Cannot create vertex selector.");
382
0
    IGRAPH_FINALLY(igraph_free, vec);
383
384
0
    va_start(ap, vs);
385
0
    while (1) {
386
0
        int num = va_arg(ap, int);
387
0
        if (num == -1) {
388
0
            break;
389
0
        }
390
0
        n++;
391
0
    }
392
0
    va_end(ap);
393
394
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(vec, n);
395
396
0
    va_start(ap, vs);
397
0
    for (i = 0; i < n; i++) {
398
0
        VECTOR(*vec)[i] = va_arg(ap, int);
399
0
    }
400
0
    va_end(ap);
401
402
0
    IGRAPH_FINALLY_CLEAN(2);
403
404
0
    vs->type = IGRAPH_VS_VECTOR;
405
0
    vs->data.vecptr = vec;
406
407
0
    return IGRAPH_SUCCESS;
408
0
}
409
410
/**
411
 * \function igraph_vs_vector_copy
412
 * \brief Vertex set based on a vector, with copying.
413
 *
414
 * This function makes it possible to handle an \type igraph_vector_int_t
415
 * permanently as a vertex selector. The vertex selector creates a
416
 * copy of the original vector, so the vector can safely be destroyed
417
 * after creating the vertex selector. Changing the original vector
418
 * will not affect the vertex selector. The vertex selector is
419
 * responsible for deleting the copy made by itself. Since selectors
420
 * are not tied to any specific graph, this function does not check whether
421
 * the vertex IDs in the vector are valid.
422
 *
423
 * \param vs Pointer to an uninitialized vertex selector.
424
 * \param v Pointer to a \type igraph_vector_int_t object.
425
 * \return Error code.
426
 * \sa \ref igraph_vs_destroy()
427
 *
428
 * Time complexity: O(1).
429
 */
430
431
0
igraph_error_t igraph_vs_vector_copy(igraph_vs_t *vs, const igraph_vector_int_t *v) {
432
0
    igraph_vector_int_t* vec;
433
434
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
435
0
    IGRAPH_CHECK_OOM(vec, "Cannot create vertex selector.");
436
0
    IGRAPH_FINALLY(igraph_free, vec);
437
0
    IGRAPH_CHECK(igraph_vector_int_init_copy(vec, v));
438
0
    IGRAPH_FINALLY_CLEAN(1);
439
440
0
    vs->type = IGRAPH_VS_VECTOR;
441
0
    vs->data.vecptr = vec;
442
443
0
    return IGRAPH_SUCCESS;
444
0
}
445
446
/**
447
 * \function igraph_vs_range
448
 * \brief Vertex set, an interval of vertices.
449
 *
450
 * Creates a vertex selector containing all vertices with vertex ID
451
 * equal to or bigger than \p from and smaller than \p to. Note that the
452
 * interval is closed from the left and open from the right, following C
453
 * conventions.
454
 *
455
 * \param vs Pointer to an uninitialized vertex selector object.
456
 * \param start The first vertex ID to be included in the vertex selector.
457
 * \param end The first vertex ID \em not to be included in the vertex selector.
458
 * \return Error code.
459
 * \sa \ref igraph_vss_range(), \ref igraph_vs_destroy()
460
 *
461
 * Time complexity: O(1).
462
 *
463
 * \example examples/simple/igraph_vs_range.c
464
 */
465
466
0
igraph_error_t igraph_vs_range(igraph_vs_t *vs, igraph_integer_t start, igraph_integer_t end) {
467
0
    *vs = igraph_vss_range(start, end);
468
0
    return IGRAPH_SUCCESS;
469
0
}
470
471
/**
472
 * \function igraph_vss_range
473
 * \brief An interval of vertices (immediate version).
474
 *
475
 * The immediate version of \ref igraph_vs_range().
476
 *
477
 * \param start The first vertex ID to be included in the vertex selector.
478
 * \param end The first vertex ID \em not to be included in the vertex selector.
479
 * \return Error code.
480
 * \sa \ref igraph_vs_range()
481
 *
482
 * Time complexity: O(1).
483
 */
484
485
0
igraph_vs_t igraph_vss_range(igraph_integer_t start, igraph_integer_t end) {
486
0
    igraph_vs_t vs;
487
0
    vs.type = IGRAPH_VS_RANGE;
488
0
    vs.data.range.start = start;
489
0
    vs.data.range.end = end;
490
0
    return vs;
491
0
}
492
493
/**
494
 * \function igraph_vs_destroy
495
 * \brief Destroy a vertex set.
496
 *
497
 * This function should be called for all vertex selectors when they
498
 * are not needed. The memory allocated for the vertex selector will
499
 * be deallocated. Do not call this function on vertex selectors
500
 * created with the immediate versions of the vertex selector
501
 * constructors (starting with <code>igraph_vss</code>).
502
 *
503
 * \param vs Pointer to a vertex selector object.
504
 *
505
 * Time complexity: operating system dependent, usually O(1).
506
 */
507
508
0
void igraph_vs_destroy(igraph_vs_t *vs) {
509
0
    switch (vs->type) {
510
0
    case IGRAPH_VS_ALL:
511
0
    case IGRAPH_VS_ADJ:
512
0
    case IGRAPH_VS_NONE:
513
0
    case IGRAPH_VS_1:
514
0
    case IGRAPH_VS_VECTORPTR:
515
0
    case IGRAPH_VS_RANGE:
516
0
    case IGRAPH_VS_NONADJ:
517
0
        break;
518
0
    case IGRAPH_VS_VECTOR:
519
0
        igraph_vector_int_destroy((igraph_vector_int_t*) vs->data.vecptr);
520
0
        IGRAPH_FREE(vs->data.vecptr);
521
0
        break;
522
0
    default:
523
0
        break;
524
0
    }
525
0
}
526
527
/**
528
 * \function igraph_vs_is_all
529
 * \brief Check whether all vertices are included.
530
 *
531
 * This function checks whether the vertex selector object was created
532
 * by \ref igraph_vs_all() or \ref igraph_vss_all(). Note that the
533
 * vertex selector might contain all vertices in a given graph but if
534
 * it wasn't created by the two constructors mentioned here the return
535
 * value will be \c false.
536
 *
537
 * \param vs Pointer to a vertex selector object.
538
 * \return \c true if the vertex selector contains all vertices and
539
 *         \c false otherwise.
540
 *
541
 * Time complexity: O(1).
542
 */
543
544
7.14M
igraph_bool_t igraph_vs_is_all(const igraph_vs_t *vs) {
545
7.14M
    return vs->type == IGRAPH_VS_ALL;
546
7.14M
}
547
548
igraph_error_t igraph_vs_as_vector(const igraph_t *graph, igraph_vs_t vs,
549
0
                        igraph_vector_int_t *v) {
550
0
    igraph_vit_t vit;
551
552
0
    IGRAPH_CHECK(igraph_vit_create(graph, vs, &vit));
553
0
    IGRAPH_FINALLY(igraph_vit_destroy, &vit);
554
0
    IGRAPH_CHECK(igraph_vit_as_vector(&vit, v));
555
556
0
    igraph_vit_destroy(&vit);
557
0
    IGRAPH_FINALLY_CLEAN(1);
558
0
    return IGRAPH_SUCCESS;
559
0
}
560
561
/**
562
 * \function igraph_vs_copy
563
 * \brief Creates a copy of a vertex selector.
564
 *
565
 * \param dest An uninitialized selector that will contain the copy.
566
 * \param src The selector being copied.
567
 * \return Error code.
568
 */
569
0
igraph_error_t igraph_vs_copy(igraph_vs_t* dest, const igraph_vs_t* src) {
570
0
    igraph_vector_int_t *vec;
571
572
0
    memcpy(dest, src, sizeof(igraph_vs_t));
573
574
0
    switch (dest->type) {
575
0
    case IGRAPH_VS_VECTOR:
576
0
        vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
577
0
        IGRAPH_CHECK_OOM(vec, "Cannot copy vertex selector.");
578
0
        IGRAPH_FINALLY(igraph_free, &vec);
579
0
        IGRAPH_CHECK(igraph_vector_int_init_copy(vec, src->data.vecptr));
580
0
        dest->data.vecptr = vec;
581
0
        IGRAPH_FINALLY_CLEAN(1); /* ownership of vec taken by 'dest' */
582
0
        break;
583
0
    default:
584
0
        break;
585
0
    }
586
587
0
    return IGRAPH_SUCCESS;
588
0
}
589
590
/**
591
 * \function igraph_vs_type
592
 * \brief Returns the type of the vertex selector.
593
 */
594
0
igraph_vs_type_t igraph_vs_type(const igraph_vs_t *vs) {
595
0
    return vs->type;
596
0
}
597
598
/**
599
 * \function igraph_vs_size
600
 * \brief Returns the size of the vertex selector.
601
 *
602
 * The size of the vertex selector is the number of vertices it will
603
 * yield when it is iterated over.
604
 *
605
 * \param graph The graph over which we will iterate.
606
 * \param vs the vertex selector.
607
 * \param result The result will be returned here.
608
 * \return Error code.
609
 */
610
igraph_error_t igraph_vs_size(const igraph_t *graph, const igraph_vs_t *vs,
611
0
                   igraph_integer_t *result) {
612
0
    igraph_vector_int_t vec;
613
0
    igraph_bool_t *seen;
614
0
    igraph_integer_t i;
615
0
    igraph_integer_t vec_len;
616
617
0
    switch (vs->type) {
618
0
    case IGRAPH_VS_NONE:
619
0
        *result = 0; return IGRAPH_SUCCESS;
620
621
0
    case IGRAPH_VS_1:
622
0
        *result = 0;
623
0
        if (vs->data.vid < igraph_vcount(graph) && vs->data.vid >= 0) {
624
0
            *result = 1;
625
0
        }
626
0
        return IGRAPH_SUCCESS;
627
628
0
    case IGRAPH_VS_RANGE:
629
0
        *result = vs->data.range.end - vs->data.range.start;
630
0
        return IGRAPH_SUCCESS;
631
632
0
    case IGRAPH_VS_ALL:
633
0
        *result = igraph_vcount(graph); return IGRAPH_SUCCESS;
634
635
0
    case IGRAPH_VS_ADJ:
636
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0);
637
0
        IGRAPH_CHECK(igraph_neighbors(
638
0
            graph, &vec, vs->data.adj.vid, vs->data.adj.mode,
639
0
            vs->data.adj.loops, vs->data.adj.multiple
640
0
        ));
641
0
        *result = igraph_vector_int_size(&vec);
642
0
        igraph_vector_int_destroy(&vec);
643
0
        IGRAPH_FINALLY_CLEAN(1);
644
0
        return IGRAPH_SUCCESS;
645
646
0
    case IGRAPH_VS_NONADJ:
647
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0);
648
0
        IGRAPH_CHECK(igraph_neighbors(
649
0
            graph, &vec, vs->data.adj.vid, vs->data.adj.mode,
650
0
            vs->data.adj.loops, vs->data.adj.multiple
651
0
        ));
652
0
        vec_len = igraph_vector_int_size(&vec);
653
0
        *result = igraph_vcount(graph);
654
0
        seen = IGRAPH_CALLOC(*result, igraph_bool_t);
655
0
        IGRAPH_CHECK_OOM(seen, "Cannot calculate vertex selector length.");
656
0
        IGRAPH_FINALLY(igraph_free, seen);
657
0
        for (i = 0; i < vec_len; i++) {
658
0
            if (!seen[ VECTOR(vec)[i] ]) {
659
0
                (*result)--;
660
0
                seen[ VECTOR(vec)[i] ] = true;
661
0
            }
662
0
        }
663
0
        igraph_free(seen);
664
0
        igraph_vector_int_destroy(&vec);
665
0
        IGRAPH_FINALLY_CLEAN(2);
666
0
        return IGRAPH_SUCCESS;
667
668
0
    case IGRAPH_VS_VECTOR:
669
0
    case IGRAPH_VS_VECTORPTR:
670
0
        *result = igraph_vector_int_size(vs->data.vecptr);
671
0
        return IGRAPH_SUCCESS;
672
0
    }
673
674
0
    IGRAPH_ERROR("Cannot calculate selector length, invalid selector type",
675
0
                 IGRAPH_EINVAL);
676
0
}
677
678
/***************************************************/
679
680
/**
681
 * \function igraph_vit_create
682
 * \brief Creates a vertex iterator from a vertex selector.
683
 *
684
 * This function instantiates a vertex selector object with a given
685
 * graph. This is the step when the actual vertex IDs are created from
686
 * the \em logical notion of the vertex selector based on the graph.
687
 * E.g. a vertex selector created with \ref igraph_vs_all() contains
688
 * knowledge that \em all vertices are included in a (yet indefinite)
689
 * graph. When instantiating it a vertex iterator object is created,
690
 * this contains the actual vertex IDs in the graph supplied as a
691
 * parameter.
692
 *
693
 * </para><para>
694
 * The same vertex selector object can be used to instantiate any
695
 * number vertex iterators.
696
 *
697
 * \param graph An \type igraph_t object, a graph.
698
 * \param vs A vertex selector object.
699
 * \param vit Pointer to an uninitialized vertex iterator object.
700
 * \return Error code.
701
 * \sa \ref igraph_vit_destroy().
702
 *
703
 * Time complexity: it depends on the vertex selector type. O(1) for
704
 * vertex selectors created with \ref igraph_vs_all(), \ref
705
 * igraph_vs_none(), \ref igraph_vs_1, \ref igraph_vs_vector, \ref
706
 * igraph_vs_range(), \ref igraph_vs_vector(), \ref
707
 * igraph_vs_vector_small(). O(d) for \ref igraph_vs_adj(), d is the
708
 * number of vertex IDs to be included in the iterator. O(|V|) for
709
 * \ref igraph_vs_nonadj(), |V| is the number of vertices in the graph.
710
 */
711
712
7.14M
igraph_error_t igraph_vit_create(const igraph_t *graph, igraph_vs_t vs, igraph_vit_t *vit) {
713
7.14M
    igraph_vector_int_t vec;
714
7.14M
    igraph_vector_int_t *vec_int;
715
7.14M
    igraph_bool_t *seen;
716
7.14M
    igraph_integer_t i, j, n;
717
7.14M
    igraph_integer_t vec_len;
718
719
7.14M
    switch (vs.type) {
720
0
    case IGRAPH_VS_ALL:
721
0
        vit->type = IGRAPH_VIT_RANGE;
722
0
        vit->pos = 0;
723
0
        vit->start = 0;
724
0
        vit->end = igraph_vcount(graph);
725
0
        break;
726
0
    case IGRAPH_VS_ADJ:
727
0
        vec_int = IGRAPH_CALLOC(1, igraph_vector_int_t);
728
0
        IGRAPH_CHECK_OOM(vec_int, "Cannot create vertex iterator.");
729
0
        IGRAPH_FINALLY(igraph_free, vec_int);
730
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(vec_int, 0);
731
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0);
732
0
        IGRAPH_CHECK(igraph_neighbors(
733
0
            graph, &vec, vs.data.adj.vid, vs.data.adj.mode,
734
0
            vs.data.adj.loops, vs.data.adj.multiple
735
0
        ));
736
0
        n = igraph_vector_int_size(&vec);
737
0
        IGRAPH_CHECK(igraph_vector_int_resize(vec_int, n));
738
0
        for (i = 0; i < n; i++) {
739
0
            VECTOR(*vec_int)[i] = VECTOR(vec)[i];
740
0
        }
741
742
0
        igraph_vector_int_destroy(&vec);
743
0
        IGRAPH_FINALLY_CLEAN(3);
744
745
0
        vit->type = IGRAPH_VIT_VECTOR;
746
0
        vit->pos = 0;
747
0
        vit->start = 0;
748
0
        vit->vec = vec_int;
749
0
        vit->end = n;
750
751
0
        break;
752
0
    case IGRAPH_VS_NONADJ:
753
0
        vec_int = IGRAPH_CALLOC(1, igraph_vector_int_t);
754
0
        IGRAPH_CHECK_OOM(vec_int, "Cannot create vertex iterator.");
755
0
        IGRAPH_FINALLY(igraph_free, vec_int);
756
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(vec_int, 0);
757
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0);
758
0
        IGRAPH_CHECK(igraph_neighbors(
759
0
            graph, &vec, vs.data.adj.vid, vs.data.adj.mode,
760
0
            vs.data.adj.loops, vs.data.adj.multiple
761
0
        ));
762
0
        vec_len = igraph_vector_int_size(&vec);
763
0
        n = igraph_vcount(graph);
764
0
        seen = IGRAPH_CALLOC(n, igraph_bool_t);
765
0
        IGRAPH_CHECK_OOM(seen, "Cannot create vertex iterator.");
766
0
        IGRAPH_FINALLY(igraph_free, seen);
767
0
        for (i = 0; i < vec_len; i++) {
768
0
            if (! seen [ VECTOR(vec)[i] ] ) {
769
0
                n--;
770
0
                seen[ VECTOR(vec)[i] ] = true;
771
0
            }
772
0
        }
773
0
        IGRAPH_CHECK(igraph_vector_int_resize(vec_int, n));
774
0
        for (i = 0, j = 0; j < n; i++) {
775
0
            if (!seen[i]) {
776
0
                VECTOR(*vec_int)[j++] = i;
777
0
            }
778
0
        }
779
780
0
        IGRAPH_FREE(seen);
781
0
        igraph_vector_int_destroy(&vec);
782
0
        IGRAPH_FINALLY_CLEAN(4);
783
784
0
        vit->type = IGRAPH_VIT_VECTOR;
785
0
        vit->pos = 0;
786
0
        vit->start = 0;
787
0
        vit->vec = vec_int;
788
0
        vit->end = n;
789
0
        break;
790
0
    case IGRAPH_VS_NONE:
791
0
        vit->type = IGRAPH_VIT_RANGE;
792
0
        vit->pos = 0;
793
0
        vit->start = 0;
794
0
        vit->end = 0;
795
0
        break;
796
7.14M
    case IGRAPH_VS_1:
797
7.14M
        vit->type = IGRAPH_VIT_RANGE;
798
7.14M
        vit->pos = vs.data.vid;
799
7.14M
        vit->start = vs.data.vid;
800
7.14M
        vit->end = vs.data.vid + 1;
801
7.14M
        if (vit->pos >= igraph_vcount(graph)) {
802
0
            IGRAPH_ERROR("Cannot create iterator, invalid vertex ID.", IGRAPH_EINVVID);
803
0
        }
804
7.14M
        break;
805
7.14M
    case IGRAPH_VS_VECTORPTR:
806
0
    case IGRAPH_VS_VECTOR:
807
0
        vit->type = IGRAPH_VIT_VECTORPTR;
808
0
        vit->pos = 0;
809
0
        vit->start = 0;
810
0
        vit->vec = vs.data.vecptr;
811
0
        vit->end = igraph_vector_int_size(vit->vec);
812
0
        if (!igraph_vector_int_isininterval(vit->vec, 0, igraph_vcount(graph) - 1)) {
813
0
            IGRAPH_ERROR("Cannot create iterator, invalid vertex ID.", IGRAPH_EINVVID);
814
0
        }
815
0
        break;
816
0
    case IGRAPH_VS_RANGE:
817
0
        {
818
0
            igraph_integer_t no_of_nodes = igraph_vcount(graph);
819
0
            if (vs.data.range.start < 0 ||
820
0
                vs.data.range.start > no_of_nodes ||
821
0
                (no_of_nodes > 0 && vs.data.range.start == no_of_nodes)) {
822
0
                IGRAPH_ERROR("Cannot create range iterator, starting vertex ID out of range.", IGRAPH_EINVAL);
823
0
            }
824
0
            if (vs.data.range.end < 0 || vs.data.range.end > no_of_nodes) {
825
0
                IGRAPH_ERROR("Cannot create range iterator, ending vertex ID out of range.", IGRAPH_EINVAL);
826
0
            }
827
0
        }
828
0
        vit->type = IGRAPH_VIT_RANGE;
829
0
        vit->pos = vs.data.range.start;
830
0
        vit->start = vs.data.range.start;
831
0
        vit->end = vs.data.range.end;
832
0
        break;
833
0
    default:
834
0
        IGRAPH_ERROR("Cannot create iterator, invalid selector.", IGRAPH_EINVAL);
835
0
        break;
836
7.14M
    }
837
7.14M
    return IGRAPH_SUCCESS;
838
7.14M
}
839
840
/**
841
 * \function igraph_vit_destroy
842
 * \brief Destroys a vertex iterator.
843
 *
844
 * </para><para>
845
 * Deallocates memory allocated for a vertex iterator.
846
 *
847
 * \param vit Pointer to an initialized vertex iterator object.
848
 * \sa \ref igraph_vit_create()
849
 *
850
 * Time complexity: operating system dependent, usually O(1).
851
 */
852
853
7.14M
void igraph_vit_destroy(const igraph_vit_t *vit) {
854
7.14M
    switch (vit->type) {
855
7.14M
    case IGRAPH_VIT_RANGE:
856
7.14M
    case IGRAPH_VIT_VECTORPTR:
857
7.14M
        break;
858
0
    case IGRAPH_VIT_VECTOR:
859
0
        igraph_vector_int_destroy((igraph_vector_int_t*) vit->vec);
860
0
        igraph_free((igraph_vector_int_t*) vit->vec);
861
0
        break;
862
0
    default:
863
        /*     IGRAPH_ERROR("Cannot destroy iterator, unknown type", IGRAPH_EINVAL); */
864
0
        break;
865
7.14M
    }
866
7.14M
}
867
868
0
igraph_error_t igraph_vit_as_vector(const igraph_vit_t *vit, igraph_vector_int_t *v) {
869
0
    igraph_integer_t i;
870
871
0
    IGRAPH_CHECK(igraph_vector_int_resize(v, IGRAPH_VIT_SIZE(*vit)));
872
873
0
    switch (vit->type) {
874
0
    case IGRAPH_VIT_RANGE:
875
0
        for (i = 0; i < IGRAPH_VIT_SIZE(*vit); i++) {
876
0
            VECTOR(*v)[i] = vit->start + i;
877
0
        }
878
0
        break;
879
0
    case IGRAPH_VIT_VECTOR:
880
0
    case IGRAPH_VIT_VECTORPTR:
881
0
        for (i = 0; i < IGRAPH_VIT_SIZE(*vit); i++) {
882
0
            VECTOR(*v)[i] = VECTOR(*vit->vec)[i];
883
0
        }
884
0
        break;
885
0
    default:
886
0
        IGRAPH_ERROR("Cannot convert to vector, unknown iterator type",
887
0
                     IGRAPH_EINVAL);
888
0
        break;
889
0
    }
890
891
0
    return IGRAPH_SUCCESS;
892
0
}
893
894
/*******************************************************/
895
896
/**
897
 * \function igraph_es_all
898
 * \brief Edge set, all edges.
899
 *
900
 * \param es Pointer to an uninitialized edge selector object.
901
 * \param order Constant giving the order in which the edges will be
902
 *        included in the selector. Possible values:
903
 *        \clist
904
 *        \cli IGRAPH_EDGEORDER_ID
905
 *        Edge ID order; currently performs the fastest.
906
 *        \cli IGRAPH_EDGEORDER_FROM
907
 *        Vertex ID order, the id of the \em source vertex counts for directed
908
 *        graphs. The order of the incident edges of a given vertex is arbitrary.
909
 *        \cli IGRAPH_EDGEORDER_TO
910
 *        Vertex ID order, the ID of the \em target vertex counts for directed
911
 *        graphs. The order of the incident edges of a given vertex is arbitrary.
912
 *        \endclist
913
 *        For undirected graph the latter two is the same.
914
 * \return Error code.
915
 * \sa \ref igraph_ess_all(), \ref igraph_es_destroy()
916
 *
917
 * Time complexity: O(1).
918
 */
919
920
igraph_error_t igraph_es_all(igraph_es_t *es,
921
0
                  igraph_edgeorder_type_t order) {
922
0
    switch (order) {
923
0
    case IGRAPH_EDGEORDER_ID:
924
0
        es->type = IGRAPH_ES_ALL;
925
0
        break;
926
0
    case IGRAPH_EDGEORDER_FROM:
927
0
        es->type = IGRAPH_ES_ALLFROM;
928
0
        break;
929
0
    case IGRAPH_EDGEORDER_TO:
930
0
        es->type = IGRAPH_ES_ALLTO;
931
0
        break;
932
0
    default:
933
0
        IGRAPH_ERROR("Invalid edge order, cannot create selector.", IGRAPH_EINVAL);
934
0
        break;
935
0
    }
936
0
    return IGRAPH_SUCCESS;
937
0
}
938
939
/**
940
 * \function igraph_ess_all
941
 * \brief Edge set, all edges (immediate version).
942
 *
943
 * The immediate version of the all-edges selector.
944
 *
945
 * \param order Constant giving the order of the edges in the edge
946
 *        selector. See \ref igraph_es_all() for the possible values.
947
 * \return The edge selector.
948
 * \sa \ref igraph_es_all()
949
 *
950
 * Time complexity: O(1).
951
 */
952
953
0
igraph_es_t igraph_ess_all(igraph_edgeorder_type_t order) {
954
0
    igraph_es_t es;
955
0
    igraph_es_all(&es, order); /* cannot fail */
956
0
    return es;
957
0
}
958
959
/**
960
 * \function igraph_es_incident
961
 * \brief Edges incident on a given vertex.
962
 *
963
 * \param es Pointer to an uninitialized edge selector object.
964
 * \param vid Vertex ID, of which the incident edges will be
965
 *        selected.
966
 * \param mode Constant giving the type of the incident edges to
967
 *        select. This is ignored for undirected graphs. Possible values:
968
 *        \c IGRAPH_OUT, outgoing edges;
969
 *        \c IGRAPH_IN, incoming edges;
970
 *        \c IGRAPH_ALL, all edges.
971
 * \param loops Whether to include loop edges in the result. If
972
 *        \c IGRAPH_NO_LOOPS, loop edges are excluded. If \c IGRAPH_LOOPS_ONCE,
973
 *        loop edges are included once. If \c IGRAPH_LOOPS_TWICE, loop edges
974
 *        are included twice, but only if the graph is undirected or \p mode is
975
 *        set to \c IGRAPH_ALL.
976
 * \return Error code.
977
 * \sa \ref igraph_es_destroy()
978
 *
979
 * Time complexity: O(1).
980
 */
981
982
igraph_error_t igraph_es_incident(
983
    igraph_es_t *es, igraph_integer_t vid, igraph_neimode_t mode,
984
    igraph_loops_t loops
985
0
) {
986
0
    es->type = IGRAPH_ES_INCIDENT;
987
0
    es->data.incident.vid = vid;
988
0
    es->data.incident.mode = mode;
989
0
    es->data.incident.loops = loops;
990
0
    return IGRAPH_SUCCESS;
991
0
}
992
993
/**
994
 * \function igraph_es_none
995
 * \brief Empty edge selector.
996
 *
997
 * \param es Pointer to an uninitialized edge selector object to
998
 * initialize.
999
 * \return Error code.
1000
 * \sa \ref igraph_ess_none(), \ref igraph_es_destroy()
1001
 *
1002
 * Time complexity: O(1).
1003
 */
1004
1005
0
igraph_error_t igraph_es_none(igraph_es_t *es) {
1006
0
    es->type = IGRAPH_ES_NONE;
1007
0
    return IGRAPH_SUCCESS;
1008
0
}
1009
1010
/**
1011
 * \function igraph_ess_none
1012
 * \brief Immediate empty edge selector.
1013
 *
1014
 * </para><para>
1015
 * Immediate version of the empty edge selector.
1016
 *
1017
 * \return Initialized empty edge selector.
1018
 * \sa \ref igraph_es_none()
1019
 *
1020
 * Time complexity: O(1).
1021
 */
1022
1023
0
igraph_es_t igraph_ess_none(void) {
1024
0
    igraph_es_t es;
1025
0
    es.type = IGRAPH_ES_NONE;
1026
0
    return es;
1027
0
}
1028
1029
/**
1030
 * \function igraph_es_1
1031
 * \brief Edge selector containing a single edge.
1032
 *
1033
 * \param es Pointer to an uninitialized edge selector object.
1034
 * \param eid Edge ID of the edge to select.
1035
 * \return Error code.
1036
 * \sa \ref igraph_ess_1(), \ref igraph_es_destroy()
1037
 *
1038
 * Time complexity: O(1).
1039
 */
1040
1041
0
igraph_error_t igraph_es_1(igraph_es_t *es, igraph_integer_t eid) {
1042
0
    es->type = IGRAPH_ES_1;
1043
0
    es->data.eid = eid;
1044
0
    return IGRAPH_SUCCESS;
1045
0
}
1046
1047
/**
1048
 * \function igraph_ess_1
1049
 * \brief Immediate version of the single edge edge selector.
1050
 *
1051
 * \param eid The ID of the edge.
1052
 * \return The edge selector.
1053
 * \sa \ref igraph_es_1()
1054
 *
1055
 * Time complexity: O(1).
1056
 */
1057
1058
1.27M
igraph_es_t igraph_ess_1(igraph_integer_t eid) {
1059
1.27M
    igraph_es_t es;
1060
1.27M
    es.type = IGRAPH_ES_1;
1061
1.27M
    es.data.eid = eid;
1062
1.27M
    return es;
1063
1.27M
}
1064
1065
/**
1066
 * \function igraph_es_vector
1067
 * \brief Handle a vector as an edge selector.
1068
 *
1069
 * Creates an edge selector which serves as a view into a vector
1070
 * containing edge IDs. Do not destroy the vector before destroying
1071
 * the edge selector. Since selectors are not tied to any specific
1072
 * graph, this function does not check whether the edge IDs in
1073
 * the vector are valid.
1074
 *
1075
 * \param es Pointer to an uninitialized edge selector.
1076
 * \param v Vector containing edge IDs.
1077
 * \return Error code.
1078
 * \sa \ref igraph_ess_vector(), \ref igraph_es_destroy()
1079
 *
1080
 * Time complexity: O(1).
1081
 */
1082
1083
0
igraph_error_t igraph_es_vector(igraph_es_t *es, const igraph_vector_int_t *v) {
1084
0
    es->type = IGRAPH_ES_VECTORPTR;
1085
0
    es->data.vecptr = v;
1086
0
    return IGRAPH_SUCCESS;
1087
0
}
1088
1089
/**
1090
 * \function igraph_es_vector_copy
1091
 * \brief Edge set, based on a vector, with copying.
1092
 *
1093
 * This function makes it possible to handle an \type igraph_vector_int_t
1094
 * permanently as an edge selector. The edge selector creates a
1095
 * copy of the original vector, so the vector can safely be destroyed
1096
 * after creating the edge selector. Changing the original vector
1097
 * will not affect the edge selector. The edge selector is
1098
 * responsible for deleting the copy made by itself. Since selectors
1099
 * are not tied to any specific graph, this function does not check
1100
 * whether the edge IDs in the vector are valid.
1101
 *
1102
 * \param es Pointer to an uninitialized edge selector.
1103
 * \param v Pointer to a \type igraph_vector_int_t object.
1104
 * \return Error code.
1105
 * \sa \ref igraph_es_destroy()
1106
 *
1107
 * Time complexity: O(1).
1108
 */
1109
1110
0
igraph_error_t igraph_es_vector_copy(igraph_es_t *es, const igraph_vector_int_t *v) {
1111
0
    igraph_vector_int_t* vec;
1112
1113
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1114
0
    IGRAPH_CHECK_OOM(vec, "Cannot create edge selector.");
1115
0
    IGRAPH_FINALLY(igraph_free, vec);
1116
0
    IGRAPH_CHECK(igraph_vector_int_init_copy(vec, v));
1117
0
    IGRAPH_FINALLY_CLEAN(1);
1118
1119
0
    es->type = IGRAPH_ES_VECTOR;
1120
0
    es->data.vecptr = vec;
1121
1122
0
    return IGRAPH_SUCCESS;
1123
0
}
1124
1125
/**
1126
 * \function igraph_ess_vector
1127
 * \brief Immediate vector view edge selector.
1128
 *
1129
 * This is the immediate version of the vector of edge IDs edge
1130
 * selector.
1131
 *
1132
 * \param v The vector of edge IDs.
1133
 * \return Edge selector, initialized.
1134
 * \sa \ref igraph_es_vector()
1135
 *
1136
 * Time complexity: O(1).
1137
 */
1138
1139
0
igraph_es_t igraph_ess_vector(const igraph_vector_int_t *v) {
1140
0
    igraph_es_t es;
1141
0
    es.type = IGRAPH_ES_VECTORPTR;
1142
0
    es.data.vecptr = v;
1143
0
    return es;
1144
0
}
1145
1146
/**
1147
 * \function igraph_es_range
1148
 * \brief Edge selector, a sequence of edge IDs.
1149
 *
1150
 * Creates an edge selector containing all edges with edge ID
1151
 * equal to or bigger than \p from and smaller than \p to. Note that the
1152
 * interval is closed from the left and open from the right, following C
1153
 * conventions.
1154
 *
1155
 * \param es Pointer to an uninitialized edge selector object.
1156
 * \param start The first edge ID to be included in the edge selector.
1157
 * \param end The first edge ID \em not to be included in the edge selector.
1158
 * \return Error code.
1159
 * \sa \ref igraph_ess_range(), \ref igraph_es_destroy()
1160
 *
1161
 * Time complexity: O(1).
1162
 */
1163
1164
0
igraph_error_t igraph_es_range(igraph_es_t *es, igraph_integer_t start, igraph_integer_t end) {
1165
0
    *es = igraph_ess_range(start, end);
1166
0
    return IGRAPH_SUCCESS;
1167
0
}
1168
1169
/**
1170
 * \function igraph_ess_range
1171
 * \brief Immediate version of the sequence edge selector.
1172
 *
1173
 * \param start The first edge ID to be included in the edge selector.
1174
 * \param end The first edge ID \em not to be included in the edge selector.
1175
 * \return The initialized edge selector.
1176
 * \sa \ref igraph_es_range()
1177
 *
1178
 * Time complexity: O(1).
1179
 */
1180
1181
0
igraph_es_t igraph_ess_range(igraph_integer_t start, igraph_integer_t end) {
1182
0
    igraph_es_t es;
1183
0
    es.type = IGRAPH_ES_RANGE;
1184
0
    es.data.range.start = start;
1185
0
    es.data.range.end = end;
1186
0
    return es;
1187
0
}
1188
1189
/**
1190
 * \function igraph_es_pairs
1191
 * \brief Edge selector, multiple edges defined by their endpoints in a vector.
1192
 *
1193
 * The edges between the given pairs of vertices will be included in the
1194
 * edge selection. The vertex pairs must be defined in the vector <code>v</code>,
1195
 * the first element of the vector is the first vertex of the first edge
1196
 * to be selected, the second element is the second vertex of the first
1197
 * edge, the third element is the first vertex of the second edge and
1198
 * so on.
1199
 *
1200
 * \param es Pointer to an uninitialized edge selector object.
1201
 * \param v The vector containing the endpoints of the edges.
1202
 * \param directed Whether the graph is directed or not.
1203
 * \return Error code.
1204
 * \sa \ref igraph_es_pairs_small(), \ref igraph_es_destroy()
1205
 *
1206
 * Time complexity: O(n), the number of edges being selected.
1207
 *
1208
 * \example examples/simple/igraph_es_pairs.c
1209
 */
1210
1211
igraph_error_t igraph_es_pairs(igraph_es_t *es, const igraph_vector_int_t *v,
1212
0
                    igraph_bool_t directed) {
1213
0
    igraph_vector_int_t* vec;
1214
1215
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1216
0
    IGRAPH_CHECK_OOM(vec, "Cannot create edge selector.");
1217
0
    IGRAPH_FINALLY(igraph_free, vec);
1218
0
    IGRAPH_CHECK(igraph_vector_int_init_copy(vec, v));
1219
0
    IGRAPH_FINALLY_CLEAN(1);
1220
1221
0
    es->type = IGRAPH_ES_PAIRS;
1222
0
    es->data.path.mode = directed;
1223
0
    es->data.path.ptr = vec;
1224
1225
0
    return IGRAPH_SUCCESS;
1226
0
}
1227
1228
/**
1229
 * \function igraph_es_pairs_small
1230
 * \brief Edge selector, multiple edges defined by their endpoints as arguments.
1231
 *
1232
 * The edges between the given pairs of vertices will be included in the
1233
 * edge selection. The vertex pairs must be given as the arguments of the
1234
 * function call, the third argument is the first vertex of the first edge,
1235
 * the fourth argument is the second vertex of the first edge, the fifth
1236
 * is the first vertex of the second edge and so on. The last element of the
1237
 * argument list must be -1 to denote the end of the argument list.
1238
 *
1239
 * </para><para>
1240
 * Note that the vertex IDs supplied will be parsed as
1241
 * <code>int</code>'s so you cannot supply arbitrarily large (too
1242
 * large for int) vertex IDs here.
1243
 *
1244
 * \param es Pointer to an uninitialized edge selector object.
1245
 * \param directed Whether the graph is directed or not.
1246
 * \param ... The additional arguments give the edges to be included in the
1247
 *        selector, as pairs of vertex IDs. The last argument must be -1.
1248
 *        The \p first parameter is present for technical reasons and represents
1249
 *        the first variadic argument.
1250
 * \return Error code.
1251
 * \sa \ref igraph_es_pairs(), \ref igraph_es_destroy()
1252
 *
1253
 * Time complexity: O(n), the number of edges being selected.
1254
 */
1255
1256
0
igraph_error_t igraph_es_pairs_small(igraph_es_t *es, igraph_bool_t directed, int first, ...) {
1257
0
    va_list ap;
1258
0
    igraph_integer_t i, n = 0;
1259
0
    igraph_vector_int_t *vec;
1260
0
    int num;
1261
1262
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1263
0
    IGRAPH_CHECK_OOM(vec, "Cannot create edge selector.");
1264
0
    IGRAPH_FINALLY(igraph_free, vec);
1265
1266
0
    va_start(ap, first);
1267
0
    num = first;
1268
0
    while (num != -1) {
1269
0
        n++;
1270
0
        num = va_arg(ap, int);
1271
0
    }
1272
0
    va_end(ap);
1273
1274
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(vec, n);
1275
1276
0
    if (n > 0) {
1277
0
        va_start(ap, first);
1278
0
        VECTOR(*vec)[0] = first;
1279
0
        for (i = 1; i < n; i++) {
1280
0
            VECTOR(*vec)[i] = va_arg(ap, int);
1281
0
        }
1282
0
        va_end(ap);
1283
0
    }
1284
1285
0
    IGRAPH_FINALLY_CLEAN(2);
1286
1287
0
    es->type = IGRAPH_ES_PAIRS;
1288
0
    es->data.path.mode = directed;
1289
0
    es->data.path.ptr = vec;
1290
1291
0
    return IGRAPH_SUCCESS;
1292
0
}
1293
1294
/**
1295
 * \function igraph_es_path
1296
 * \brief Edge selector, edge IDs on a path.
1297
 *
1298
 * This function takes a vector of vertices and creates a selector of
1299
 * edges between those vertices. Vector {0, 3, 4, 7} will select edges
1300
 * (0 -> 3), (3 -> 4), (4 -> 7). If these edges don't exist then trying
1301
 * to create an iterator using this selector will fail.
1302
 *
1303
 * \param es Pointer to an uninitialized edge selector object.
1304
 * \param v Pointer to a vector of vertex IDs along the path.
1305
 * \param directed If edge directions should be taken into account. This
1306
 *                 will be ignored if the graph to select from is undirected.
1307
 * \return Error code.
1308
 * \sa \ref igraph_es_destroy()
1309
 *
1310
 * Time complexity: O(n), the number of vertices.
1311
 */
1312
igraph_error_t igraph_es_path(igraph_es_t *es, const igraph_vector_int_t *v,
1313
0
                   igraph_bool_t directed) {
1314
0
    igraph_vector_int_t *vec;
1315
1316
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1317
0
    IGRAPH_CHECK_OOM(vec, "Cannot create edge selector.");
1318
0
    IGRAPH_FINALLY(igraph_free, vec);
1319
0
    IGRAPH_CHECK(igraph_vector_int_init_copy(vec, v));
1320
0
    IGRAPH_FINALLY_CLEAN(1);
1321
1322
0
    es->type = IGRAPH_ES_PATH;
1323
0
    es->data.path.mode = directed;
1324
0
    es->data.path.ptr = vec;
1325
1326
0
    return IGRAPH_SUCCESS;
1327
0
}
1328
1329
0
igraph_error_t igraph_es_path_small(igraph_es_t *es, igraph_bool_t directed, int first, ...) {
1330
0
    va_list ap;
1331
0
    igraph_integer_t i, n = 0;
1332
0
    igraph_vector_int_t *vec;
1333
0
    int num;
1334
1335
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1336
0
    IGRAPH_CHECK_OOM(vec, "Cannot create edge selector.");
1337
0
    IGRAPH_FINALLY(igraph_free, vec);
1338
1339
0
    va_start(ap, first);
1340
0
    num = first;
1341
0
    while (num != -1) {
1342
0
        n++;
1343
0
        num = va_arg(ap, int);
1344
0
    }
1345
0
    va_end(ap);
1346
1347
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(vec, n);
1348
1349
0
    if (n > 0) {
1350
0
        va_start(ap, first);
1351
0
        VECTOR(*vec)[0] = first;
1352
0
        for (i = 1; i < n; i++) {
1353
0
            VECTOR(*vec)[i] = va_arg(ap, int);
1354
0
        }
1355
0
        va_end(ap);
1356
0
    }
1357
1358
0
    IGRAPH_FINALLY_CLEAN(2);
1359
1360
0
    es->type = IGRAPH_ES_PATH;
1361
0
    es->data.path.mode = directed;
1362
0
    es->data.path.ptr = vec;
1363
1364
0
    return IGRAPH_SUCCESS;
1365
0
}
1366
1367
/**
1368
 * \function igraph_es_all_between
1369
 * \brief Edge selector, all edge IDs between a pair of vertices.
1370
 *
1371
 * This function takes a pair of vertices and creates a selector that matches
1372
 * all edges between those vertices.
1373
 *
1374
 * \param es Pointer to an uninitialized edge selector object.
1375
 * \param from The ID of the source vertex.
1376
 * \param to The ID of the target vertex.
1377
 * \param directed If edge directions should be taken into account. This
1378
 *      will be ignored if the graph to select from is undirected.
1379
 * \return Error code.
1380
 * \sa \ref igraph_es_destroy()
1381
 *
1382
 * Time complexity: O(1).
1383
 */
1384
igraph_error_t igraph_es_all_between(
1385
    igraph_es_t *es, igraph_integer_t from, igraph_integer_t to,
1386
    igraph_bool_t directed
1387
0
) {
1388
0
    es->type = IGRAPH_ES_ALL_BETWEEN;
1389
0
    es->data.between.from = from;
1390
0
    es->data.between.to = to;
1391
0
    es->data.between.directed = directed;
1392
0
    return IGRAPH_SUCCESS;
1393
0
}
1394
1395
/**
1396
 * \function igraph_es_destroy
1397
 * \brief Destroys an edge selector object.
1398
 *
1399
 * Call this function on an edge selector when it is not needed any
1400
 * more. Do \em not call this function on edge selectors created by
1401
 * immediate constructors, those don't need to be destroyed.
1402
 *
1403
 * \param es Pointer to an edge selector object.
1404
 *
1405
 * Time complexity: operating system dependent, usually O(1).
1406
 */
1407
1408
0
void igraph_es_destroy(igraph_es_t *es) {
1409
0
    switch (es->type) {
1410
0
    case IGRAPH_ES_ALL:
1411
0
    case IGRAPH_ES_ALLFROM:
1412
0
    case IGRAPH_ES_ALLTO:
1413
0
    case IGRAPH_ES_INCIDENT:
1414
0
    case IGRAPH_ES_NONE:
1415
0
    case IGRAPH_ES_1:
1416
0
    case IGRAPH_ES_VECTORPTR:
1417
0
    case IGRAPH_ES_RANGE:
1418
0
    case IGRAPH_ES_ALL_BETWEEN:
1419
0
        break;
1420
0
    case IGRAPH_ES_VECTOR:
1421
0
        igraph_vector_int_destroy((igraph_vector_int_t*)es->data.vecptr);
1422
0
        IGRAPH_FREE(es->data.vecptr);
1423
0
        break;
1424
0
    case IGRAPH_ES_PAIRS:
1425
0
    case IGRAPH_ES_PATH:
1426
0
        igraph_vector_int_destroy((igraph_vector_int_t*)es->data.path.ptr);
1427
0
        IGRAPH_FREE(es->data.path.ptr);
1428
0
        break;
1429
0
    default:
1430
0
        break;
1431
0
    }
1432
0
}
1433
1434
/**
1435
 * \function igraph_es_is_all
1436
 * \brief Check whether an edge selector includes all edges.
1437
 *
1438
 * \param es Pointer to an edge selector object.
1439
 * \return \c true if \p es was created with \ref
1440
 * igraph_es_all() or \ref igraph_ess_all(), and \c false otherwise.
1441
 *
1442
 * Time complexity: O(1).
1443
 */
1444
1445
1.27M
igraph_bool_t igraph_es_is_all(const igraph_es_t *es) {
1446
1.27M
    return es->type == IGRAPH_ES_ALL;
1447
1.27M
}
1448
1449
/**
1450
 * \function igraph_es_copy
1451
 * \brief Creates a copy of an edge selector.
1452
 *
1453
 * \param dest An uninitialized selector that will contain the copy.
1454
 * \param src The selector being copied.
1455
 * \return Error code.
1456
 *
1457
 * \sa \ref igraph_es_destroy()
1458
 */
1459
0
igraph_error_t igraph_es_copy(igraph_es_t* dest, const igraph_es_t* src) {
1460
0
    igraph_vector_int_t *vec;
1461
1462
0
    memcpy(dest, src, sizeof(igraph_es_t));
1463
0
    switch (dest->type) {
1464
0
    case IGRAPH_ES_VECTOR:
1465
0
        vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1466
0
        IGRAPH_CHECK_OOM(vec, "Cannot copy edge selector.");
1467
0
        IGRAPH_FINALLY(igraph_free, &vec);
1468
0
        IGRAPH_CHECK(igraph_vector_int_init_copy(vec, src->data.vecptr));
1469
0
        dest->data.vecptr = vec;
1470
0
        IGRAPH_FINALLY_CLEAN(1); /* ownership of vec taken by 'dest' */
1471
0
        break;
1472
0
    case IGRAPH_ES_PATH:
1473
0
    case IGRAPH_ES_PAIRS:
1474
0
        vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1475
0
        IGRAPH_CHECK_OOM(vec, "Cannot copy edge selector.");
1476
0
        IGRAPH_FINALLY(igraph_free, &vec);
1477
0
        IGRAPH_CHECK(igraph_vector_int_init_copy(vec, src->data.path.ptr));
1478
0
        dest->data.path.ptr = vec;
1479
0
        IGRAPH_FINALLY_CLEAN(1); /* ownership of vec taken by 'dest' */
1480
0
        break;
1481
0
    default:
1482
0
        break;
1483
0
    }
1484
0
    return IGRAPH_SUCCESS;
1485
0
}
1486
1487
/**
1488
 * \function igraph_es_as_vector
1489
 * \brief Transform edge selector into vector.
1490
 *
1491
 * </para><para>
1492
 * Call this function on an edge selector to transform it into a vector.
1493
 * This is only implemented for sequence and vector selectors. If the
1494
 * edges do not exist in the graph, this will result in an error.
1495
 *
1496
 * \param graph Pointer to a graph to check if the edges in the selector exist.
1497
 * \param es An edge selector object.
1498
 * \param v Pointer to initialized vector. The result will be stored here.
1499
 * \return Error code.
1500
 *
1501
 * Time complexity: O(n), the number of edges in the selector.
1502
 */
1503
igraph_error_t igraph_es_as_vector(const igraph_t *graph, igraph_es_t es,
1504
0
                        igraph_vector_int_t *v) {
1505
0
    igraph_eit_t eit;
1506
1507
0
    IGRAPH_CHECK(igraph_eit_create(graph, es, &eit));
1508
0
    IGRAPH_FINALLY(igraph_eit_destroy, &eit);
1509
0
    IGRAPH_CHECK(igraph_eit_as_vector(&eit, v));
1510
1511
0
    igraph_eit_destroy(&eit);
1512
0
    IGRAPH_FINALLY_CLEAN(1);
1513
0
    return IGRAPH_SUCCESS;
1514
0
}
1515
1516
/**
1517
 * \function igraph_es_type
1518
 * \brief Returns the type of the edge selector.
1519
 */
1520
0
igraph_es_type_t igraph_es_type(const igraph_es_t *es) {
1521
0
    return es->type;
1522
0
}
1523
1524
static igraph_error_t igraph_i_es_pairs_size(const igraph_t *graph,
1525
                                  const igraph_es_t *es, igraph_integer_t *result);
1526
static igraph_error_t igraph_i_es_path_size(const igraph_t *graph,
1527
                                 const igraph_es_t *es, igraph_integer_t *result);
1528
static igraph_error_t igraph_i_es_all_between_size(const igraph_t *graph,
1529
                                 const igraph_es_t *es, igraph_integer_t *result);
1530
1531
/**
1532
 * \function igraph_es_size
1533
 * \brief Returns the size of the edge selector.
1534
 *
1535
 * The size of the edge selector is the number of edges it will
1536
 * yield when it is iterated over.
1537
 *
1538
 * \param graph The graph over which we will iterate.
1539
 * \param es The edge selector.
1540
 * \param result The result will be returned here.
1541
 * \return Error code.
1542
 */
1543
igraph_error_t igraph_es_size(const igraph_t *graph, const igraph_es_t *es,
1544
0
                   igraph_integer_t *result) {
1545
0
    igraph_vector_int_t v;
1546
1547
0
    switch (es->type) {
1548
0
    case IGRAPH_ES_ALL:
1549
0
        *result = igraph_ecount(graph);
1550
0
        return IGRAPH_SUCCESS;
1551
1552
0
    case IGRAPH_ES_ALLFROM:
1553
0
        *result = igraph_ecount(graph);
1554
0
        return IGRAPH_SUCCESS;
1555
1556
0
    case IGRAPH_ES_ALLTO:
1557
0
        *result = igraph_ecount(graph);
1558
0
        return IGRAPH_SUCCESS;
1559
1560
0
    case IGRAPH_ES_INCIDENT:
1561
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&v, 0);
1562
0
        IGRAPH_CHECK(igraph_incident(
1563
0
            graph, &v, es->data.incident.vid, es->data.incident.mode,
1564
0
            es->data.incident.loops
1565
0
        ));
1566
0
        *result = igraph_vector_int_size(&v);
1567
0
        igraph_vector_int_destroy(&v);
1568
0
        IGRAPH_FINALLY_CLEAN(1);
1569
0
        return IGRAPH_SUCCESS;
1570
1571
0
    case IGRAPH_ES_NONE:
1572
0
        *result = 0;
1573
0
        return IGRAPH_SUCCESS;
1574
1575
0
    case IGRAPH_ES_1:
1576
0
        if (es->data.eid < igraph_ecount(graph) && es->data.eid >= 0) {
1577
0
            *result = 1;
1578
0
        } else {
1579
0
            *result = 0;
1580
0
        }
1581
0
        return IGRAPH_SUCCESS;
1582
1583
0
    case IGRAPH_ES_VECTOR:
1584
0
    case IGRAPH_ES_VECTORPTR:
1585
0
        *result = igraph_vector_int_size(es->data.vecptr);
1586
0
        return IGRAPH_SUCCESS;
1587
1588
0
    case IGRAPH_ES_RANGE:
1589
0
        *result = es->data.range.end - es->data.range.start;
1590
0
        return IGRAPH_SUCCESS;
1591
1592
0
    case IGRAPH_ES_PAIRS:
1593
0
        IGRAPH_CHECK(igraph_i_es_pairs_size(graph, es, result));
1594
0
        return IGRAPH_SUCCESS;
1595
1596
0
    case IGRAPH_ES_PATH:
1597
0
        IGRAPH_CHECK(igraph_i_es_path_size(graph, es, result));
1598
0
        return IGRAPH_SUCCESS;
1599
1600
0
    case IGRAPH_ES_ALL_BETWEEN:
1601
0
        IGRAPH_CHECK(igraph_i_es_all_between_size(graph, es, result));
1602
0
        return IGRAPH_SUCCESS;
1603
1604
0
    default:
1605
0
        IGRAPH_ERROR("Cannot calculate selector length, invalid selector type.",
1606
0
                     IGRAPH_EINVAL);
1607
0
    }
1608
0
}
1609
1610
static igraph_error_t igraph_i_es_pairs_size(const igraph_t *graph,
1611
0
                                  const igraph_es_t *es, igraph_integer_t *result) {
1612
0
    igraph_integer_t i, n = igraph_vector_int_size(es->data.path.ptr);
1613
0
    igraph_integer_t no_of_nodes = igraph_vcount(graph);
1614
1615
0
    if (n % 2 != 0) {
1616
0
        IGRAPH_ERROR("Cannot calculate edge selector length from odd number of vertices.",
1617
0
                     IGRAPH_EINVAL);
1618
0
    }
1619
0
    if (!igraph_vector_int_isininterval(es->data.path.ptr, 0, no_of_nodes - 1)) {
1620
0
        IGRAPH_ERROR("Cannot calculate edge selector length.", IGRAPH_EINVVID);
1621
0
    }
1622
1623
0
    *result = n / 2;
1624
    /* Check for the existence of all edges */
1625
0
    for (i = 0; i < *result; i++) {
1626
0
        igraph_integer_t from = VECTOR(*es->data.path.ptr)[2 * i];
1627
0
        igraph_integer_t to = VECTOR(*es->data.path.ptr)[2 * i + 1];
1628
0
        igraph_integer_t eid;
1629
0
        IGRAPH_CHECK(igraph_get_eid(graph, &eid, from, to, es->data.path.mode,
1630
0
                                    /*error=*/ 1));
1631
0
    }
1632
1633
0
    return IGRAPH_SUCCESS;
1634
0
}
1635
1636
static igraph_error_t igraph_i_es_path_size(const igraph_t *graph,
1637
0
                                 const igraph_es_t *es, igraph_integer_t *result) {
1638
0
    igraph_integer_t i, n = igraph_vector_int_size(es->data.path.ptr);
1639
0
    igraph_integer_t no_of_nodes = igraph_vcount(graph);
1640
1641
0
    if (!igraph_vector_int_isininterval(es->data.path.ptr, 0, no_of_nodes - 1)) {
1642
0
        IGRAPH_ERROR("Cannot calculate selector length.", IGRAPH_EINVVID);
1643
0
    }
1644
1645
0
    if (n <= 1) {
1646
0
        *result = 0;
1647
0
    } else {
1648
0
        *result = n - 1;
1649
0
    }
1650
0
    for (i = 0; i < *result; i++) {
1651
0
        igraph_integer_t from = VECTOR(*es->data.path.ptr)[i];
1652
0
        igraph_integer_t to = VECTOR(*es->data.path.ptr)[i + 1];
1653
0
        igraph_integer_t eid;
1654
0
        IGRAPH_CHECK(igraph_get_eid(graph, &eid, from, to, es->data.path.mode,
1655
0
                                    /*error=*/ 1));
1656
0
    }
1657
1658
0
    return IGRAPH_SUCCESS;
1659
0
}
1660
1661
static igraph_error_t igraph_i_es_all_between_size(const igraph_t *graph,
1662
0
                                 const igraph_es_t *es, igraph_integer_t *result) {
1663
0
    igraph_integer_t no_of_nodes = igraph_vcount(graph);
1664
0
    igraph_integer_t from = es->data.between.from;
1665
0
    igraph_integer_t to = es->data.between.to;
1666
0
    igraph_bool_t directed = es->data.between.directed;
1667
0
    igraph_vector_int_t vec;
1668
1669
0
    if (from < 0 || from >= no_of_nodes || to < 0 || to >= no_of_nodes) {
1670
0
        IGRAPH_ERROR("Cannot calculate selector length.", IGRAPH_EINVVID);
1671
0
    }
1672
1673
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0);
1674
0
    IGRAPH_CHECK(igraph_get_all_eids_between(graph, &vec, from, to, directed));
1675
0
    *result = igraph_vector_int_size(&vec);
1676
0
    igraph_vector_int_destroy(&vec);
1677
0
    IGRAPH_FINALLY_CLEAN(1);
1678
1679
0
    return IGRAPH_SUCCESS;
1680
0
}
1681
1682
/**************************************************/
1683
1684
static igraph_error_t igraph_i_eit_create_allfromto(const igraph_t *graph,
1685
                                         igraph_eit_t *eit,
1686
                                         igraph_neimode_t mode);
1687
static igraph_error_t igraph_i_eit_create_incident(const igraph_t* graph,
1688
                              igraph_es_t es, igraph_eit_t *eit);
1689
static igraph_error_t igraph_i_eit_pairs(const igraph_t *graph,
1690
                              igraph_es_t es, igraph_eit_t *eit);
1691
static igraph_error_t igraph_i_eit_path(const igraph_t *graph,
1692
                             igraph_es_t es, igraph_eit_t *eit);
1693
1694
static igraph_error_t igraph_i_eit_create_allfromto(const igraph_t *graph,
1695
                                         igraph_eit_t *eit,
1696
0
                                         igraph_neimode_t mode) {
1697
0
    igraph_vector_int_t *vec;
1698
0
    igraph_integer_t no_of_nodes = igraph_vcount(graph);
1699
0
    igraph_integer_t no_of_edges = igraph_ecount(graph);
1700
1701
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1702
0
    IGRAPH_CHECK_OOM(vec, "Cannot create edge iterator.");
1703
0
    IGRAPH_FINALLY(igraph_free, vec);
1704
1705
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(vec, 0);
1706
0
    IGRAPH_CHECK(igraph_vector_int_reserve(vec, no_of_edges));
1707
1708
0
    if (igraph_is_directed(graph)) {
1709
0
        igraph_vector_int_t adj;
1710
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&adj, 0);
1711
0
        for (igraph_integer_t i = 0; i < no_of_nodes; i++) {
1712
0
            IGRAPH_CHECK(igraph_incident(graph, &adj, i, mode, IGRAPH_LOOPS));
1713
0
            igraph_vector_int_append(vec, &adj);  /* reserved */
1714
0
        }
1715
0
        igraph_vector_int_destroy(&adj);
1716
0
        IGRAPH_FINALLY_CLEAN(1);
1717
0
    } else {
1718
0
        igraph_vector_int_t adj;
1719
0
        igraph_bool_t *added;
1720
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&adj, 0);
1721
0
        added = IGRAPH_CALLOC(no_of_edges, igraph_bool_t);
1722
0
        IGRAPH_CHECK_OOM(added, "Cannot create edge iterator.");
1723
0
        IGRAPH_FINALLY(igraph_free, added);
1724
0
        for (igraph_integer_t i = 0; i < no_of_nodes; i++) {
1725
0
            IGRAPH_CHECK(igraph_incident(graph, &adj, i, IGRAPH_ALL, IGRAPH_LOOPS));
1726
0
            const igraph_integer_t length = igraph_vector_int_size(&adj);
1727
0
            for (igraph_integer_t j = 0; j < length; j++) {
1728
0
                if (!added[ VECTOR(adj)[j] ]) {
1729
0
                    igraph_vector_int_push_back(vec, VECTOR(adj)[j]);  /* reserved */
1730
0
                    added[ VECTOR(adj)[j] ] = true;
1731
0
                }
1732
0
            }
1733
0
        }
1734
0
        igraph_vector_int_destroy(&adj);
1735
0
        IGRAPH_FREE(added);
1736
0
        IGRAPH_FINALLY_CLEAN(2);
1737
0
    }
1738
1739
0
    eit->type = IGRAPH_EIT_VECTOR;
1740
0
    eit->pos = 0;
1741
0
    eit->start = 0;
1742
0
    eit->vec = vec;
1743
0
    eit->end = igraph_vector_int_size(eit->vec);
1744
1745
0
    IGRAPH_FINALLY_CLEAN(2);
1746
0
    return IGRAPH_SUCCESS;
1747
0
}
1748
1749
static igraph_error_t igraph_i_eit_create_incident(const igraph_t* graph,
1750
0
                              igraph_es_t es, igraph_eit_t *eit) {
1751
0
    igraph_vector_int_t vec;
1752
0
    igraph_vector_int_t* vec_int;
1753
0
    igraph_integer_t i, n;
1754
1755
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&vec, 0);
1756
0
    IGRAPH_CHECK(igraph_incident(
1757
0
        graph, &vec, es.data.incident.vid, es.data.incident.mode,
1758
0
        es.data.incident.loops
1759
0
    ));
1760
1761
0
    vec_int = IGRAPH_CALLOC(1, igraph_vector_int_t);
1762
0
    IGRAPH_CHECK_OOM(vec_int, "Cannot create edge iterator.");
1763
0
    IGRAPH_FINALLY(igraph_free, vec_int);
1764
1765
0
    n = igraph_vector_int_size(&vec);
1766
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(vec_int, n);
1767
1768
0
    for (i = 0; i < n; i++) {
1769
0
        VECTOR(*vec_int)[i] = VECTOR(vec)[i];
1770
0
    }
1771
1772
0
    igraph_vector_int_destroy(&vec);
1773
0
    IGRAPH_FINALLY_CLEAN(3);
1774
1775
0
    eit->type = IGRAPH_EIT_VECTOR;
1776
0
    eit->pos = 0;
1777
0
    eit->start = 0;
1778
0
    eit->vec = vec_int;
1779
0
    eit->end = igraph_vector_int_size(vec_int);
1780
1781
0
    return IGRAPH_SUCCESS;
1782
0
}
1783
1784
static igraph_error_t igraph_i_eit_pairs(const igraph_t *graph,
1785
0
                              igraph_es_t es, igraph_eit_t *eit) {
1786
0
    igraph_integer_t n = igraph_vector_int_size(es.data.path.ptr);
1787
0
    igraph_integer_t no_of_nodes = igraph_vcount(graph);
1788
0
    igraph_integer_t i;
1789
0
    igraph_vector_int_t* vec;
1790
1791
0
    if (n % 2 != 0) {
1792
0
        IGRAPH_ERROR("Cannot create edge iterator from odd number of vertices.",
1793
0
                     IGRAPH_EINVAL);
1794
0
    }
1795
0
    if (!igraph_vector_int_isininterval(es.data.path.ptr, 0, no_of_nodes - 1)) {
1796
0
        IGRAPH_ERROR("Cannot create edge iterator.", IGRAPH_EINVVID);
1797
0
    }
1798
1799
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1800
0
    IGRAPH_CHECK_OOM(vec, "Cannot create edge iterator.");
1801
0
    IGRAPH_FINALLY(igraph_free, vec);
1802
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(vec, n / 2);
1803
1804
0
    for (i = 0; i < n / 2; i++) {
1805
0
        igraph_integer_t from = VECTOR(*es.data.path.ptr)[2 * i];
1806
0
        igraph_integer_t to = VECTOR(*es.data.path.ptr)[2 * i + 1];
1807
0
        igraph_integer_t eid;
1808
0
        IGRAPH_CHECK(igraph_get_eid(graph, &eid, from, to, es.data.path.mode,
1809
0
                                    /*error=*/ 1));
1810
0
        VECTOR(*vec)[i] = eid;
1811
0
    }
1812
1813
0
    IGRAPH_FINALLY_CLEAN(2);
1814
1815
0
    eit->type = IGRAPH_EIT_VECTOR;
1816
0
    eit->pos = 0;
1817
0
    eit->start = 0;
1818
0
    eit->end = n / 2;
1819
0
    eit->vec = vec;
1820
1821
0
    return IGRAPH_SUCCESS;
1822
0
}
1823
1824
static igraph_error_t igraph_i_eit_path(const igraph_t *graph,
1825
0
                             igraph_es_t es, igraph_eit_t *eit) {
1826
0
    igraph_integer_t n = igraph_vector_int_size(es.data.path.ptr);
1827
0
    igraph_integer_t no_of_nodes = igraph_vcount(graph);
1828
0
    igraph_integer_t i, len;
1829
0
    igraph_vector_int_t* vec;
1830
1831
0
    if (!igraph_vector_int_isininterval(es.data.path.ptr, 0, no_of_nodes - 1)) {
1832
0
        IGRAPH_ERROR("Cannot create edge iterator.", IGRAPH_EINVVID);
1833
0
    }
1834
1835
0
    if (n <= 1) {
1836
0
        len = 0;
1837
0
    } else {
1838
0
        len = n - 1;
1839
0
    }
1840
1841
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1842
0
    IGRAPH_CHECK_OOM(vec, "Cannot create edge iterator.");
1843
0
    IGRAPH_FINALLY(igraph_free, vec);
1844
1845
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(vec, len);
1846
1847
0
    for (i = 0; i < len; i++) {
1848
0
        igraph_integer_t from = VECTOR(*es.data.path.ptr)[i];
1849
0
        igraph_integer_t to = VECTOR(*es.data.path.ptr)[i + 1];
1850
0
        igraph_integer_t eid;
1851
0
        IGRAPH_CHECK(igraph_get_eid(graph, &eid, from, to, es.data.path.mode,
1852
0
                                    /*error=*/ 1));
1853
0
        VECTOR(*vec)[i] = eid;
1854
0
    }
1855
1856
0
    IGRAPH_FINALLY_CLEAN(2);
1857
1858
0
    eit->type = IGRAPH_EIT_VECTOR;
1859
0
    eit->pos = 0;
1860
0
    eit->start = 0;
1861
0
    eit->end = len;
1862
0
    eit->vec = vec;
1863
1864
0
    return IGRAPH_SUCCESS;
1865
0
}
1866
1867
static igraph_error_t igraph_i_eit_all_between(
1868
    const igraph_t *graph, igraph_es_t es, igraph_eit_t *eit
1869
0
) {
1870
0
    igraph_integer_t from = es.data.between.from;
1871
0
    igraph_integer_t to = es.data.between.to;
1872
0
    igraph_bool_t directed = es.data.between.directed;
1873
0
    igraph_integer_t no_of_nodes = igraph_vcount(graph);
1874
0
    igraph_vector_int_t* vec;
1875
1876
0
    if (from < 0 || from >= no_of_nodes || to < 0 || to >= no_of_nodes) {
1877
0
        IGRAPH_ERROR("Cannot create edge iterator", IGRAPH_EINVVID);
1878
0
    }
1879
1880
0
    vec = IGRAPH_CALLOC(1, igraph_vector_int_t);
1881
0
    IGRAPH_CHECK_OOM(vec, "Cannot create edge iterator.");
1882
0
    IGRAPH_FINALLY(igraph_free, vec);
1883
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(vec, 0);
1884
0
    IGRAPH_CHECK(igraph_get_all_eids_between(graph, vec, from, to, directed));
1885
0
    IGRAPH_FINALLY_CLEAN(2);
1886
1887
0
    eit->type = IGRAPH_EIT_VECTOR;
1888
0
    eit->pos = 0;
1889
0
    eit->start = 0;
1890
0
    eit->end = igraph_vector_int_size(vec);
1891
0
    eit->vec = vec;
1892
1893
0
    return IGRAPH_SUCCESS;
1894
0
}
1895
1896
/**
1897
 * \function igraph_eit_create
1898
 * \brief Creates an edge iterator from an edge selector.
1899
 *
1900
 * </para><para>
1901
 * This function creates an edge iterator based on an edge selector
1902
 * and a graph.
1903
 *
1904
 * </para><para>
1905
 * The same edge selector can be used to create many edge iterators,
1906
 * also for different graphs.
1907
 *
1908
 * \param graph An \type igraph_t object for which the edge selector
1909
 *        will be instantiated.
1910
 * \param es The edge selector to instantiate.
1911
 * \param eit Pointer to an uninitialized edge iterator.
1912
 * \return Error code.
1913
 * \sa \ref igraph_eit_destroy()
1914
 *
1915
 * Time complexity: depends on the type of the edge selector. For edge
1916
 * selectors created by \ref igraph_es_all(), \ref igraph_es_none(),
1917
 * \ref igraph_es_1(), \ref igraph_es_vector(), \ref igraph_es_range() it is
1918
 * O(1). For \ref igraph_es_incident() it is O(d) where d is the number of
1919
 * incident edges of the vertex.
1920
 */
1921
1922
1.27M
igraph_error_t igraph_eit_create(const igraph_t *graph, igraph_es_t es, igraph_eit_t *eit) {
1923
1.27M
    switch (es.type) {
1924
0
    case IGRAPH_ES_ALL:
1925
0
        eit->type = IGRAPH_EIT_RANGE;
1926
0
        eit->pos = 0;
1927
0
        eit->start = 0;
1928
0
        eit->end = igraph_ecount(graph);
1929
0
        break;
1930
0
    case IGRAPH_ES_ALLFROM:
1931
0
        IGRAPH_CHECK(igraph_i_eit_create_allfromto(graph, eit, IGRAPH_OUT));
1932
0
        break;
1933
0
    case IGRAPH_ES_ALLTO:
1934
0
        IGRAPH_CHECK(igraph_i_eit_create_allfromto(graph, eit, IGRAPH_IN));
1935
0
        break;
1936
0
    case IGRAPH_ES_INCIDENT:
1937
0
        IGRAPH_CHECK(igraph_i_eit_create_incident(graph, es, eit));
1938
0
        break;
1939
0
    case IGRAPH_ES_NONE:
1940
0
        eit->type = IGRAPH_EIT_RANGE;
1941
0
        eit->pos = 0;
1942
0
        eit->start = 0;
1943
0
        eit->end = 0;
1944
0
        break;
1945
1.27M
    case IGRAPH_ES_1:
1946
1.27M
        eit->type = IGRAPH_EIT_RANGE;
1947
1.27M
        eit->pos = es.data.eid;
1948
1.27M
        eit->start = es.data.eid;
1949
1.27M
        eit->end = es.data.eid + 1;
1950
1.27M
        if (eit->pos >= igraph_ecount(graph)) {
1951
0
            IGRAPH_ERROR("Cannot create iterator.", IGRAPH_EINVEID);
1952
0
        }
1953
1.27M
        break;
1954
1.27M
    case IGRAPH_ES_VECTOR:
1955
0
    case IGRAPH_ES_VECTORPTR:
1956
0
        eit->type = IGRAPH_EIT_VECTORPTR;
1957
0
        eit->pos = 0;
1958
0
        eit->start = 0;
1959
0
        eit->vec = es.data.vecptr;
1960
0
        eit->end = igraph_vector_int_size(eit->vec);
1961
0
        if (!igraph_vector_int_isininterval(eit->vec, 0, igraph_ecount(graph) - 1)) {
1962
0
            IGRAPH_ERROR("Cannot create iterator.", IGRAPH_EINVEID);
1963
0
        }
1964
0
        break;
1965
0
    case IGRAPH_ES_RANGE:
1966
0
        {
1967
0
            igraph_integer_t no_of_edges = igraph_ecount(graph);
1968
0
            if (es.data.range.start < 0 ||
1969
0
                es.data.range.start > no_of_edges ||
1970
0
                (no_of_edges > 0 && es.data.range.start == no_of_edges)) {
1971
0
                IGRAPH_ERROR("Cannot create range iterator, starting edge ID out of range.", IGRAPH_EINVEID);
1972
0
            }
1973
0
            if (es.data.range.end < 0 || es.data.range.end > no_of_edges) {
1974
0
                IGRAPH_ERROR("Cannot create range iterator, ending edge ID out of range.", IGRAPH_EINVEID);
1975
0
            }
1976
0
        }
1977
0
        eit->type = IGRAPH_EIT_RANGE;
1978
0
        eit->pos = es.data.range.start;
1979
0
        eit->start = es.data.range.start;
1980
0
        eit->end = es.data.range.end;
1981
0
        break;
1982
0
    case IGRAPH_ES_PAIRS:
1983
0
        IGRAPH_CHECK(igraph_i_eit_pairs(graph, es, eit));
1984
0
        break;
1985
0
    case IGRAPH_ES_PATH:
1986
0
        IGRAPH_CHECK(igraph_i_eit_path(graph, es, eit));
1987
0
        break;
1988
0
    case IGRAPH_ES_ALL_BETWEEN:
1989
0
        IGRAPH_CHECK(igraph_i_eit_all_between(graph, es, eit));
1990
0
        break;
1991
0
    default:
1992
0
        IGRAPH_ERROR("Cannot create iterator, invalid selector.", IGRAPH_EINVAL);
1993
0
        break;
1994
1.27M
    }
1995
1.27M
    return IGRAPH_SUCCESS;
1996
1.27M
}
1997
1998
/**
1999
 * \function igraph_eit_destroy
2000
 * \brief Destroys an edge iterator.
2001
 *
2002
 * \param eit Pointer to an edge iterator to destroy.
2003
 * \sa \ref igraph_eit_create()
2004
 *
2005
 * Time complexity: operating system dependent, usually O(1).
2006
 */
2007
2008
1.27M
void igraph_eit_destroy(const igraph_eit_t *eit) {
2009
1.27M
    switch (eit->type) {
2010
1.27M
    case IGRAPH_EIT_RANGE:
2011
1.27M
    case IGRAPH_EIT_VECTORPTR:
2012
1.27M
        break;
2013
0
    case IGRAPH_EIT_VECTOR:
2014
0
        igraph_vector_int_destroy((igraph_vector_int_t*)eit->vec);
2015
0
        igraph_free((igraph_vector_int_t*)eit->vec);
2016
0
        break;
2017
0
    default:
2018
        /*     IGRAPH_ERROR("Cannot destroy iterator, unknown type", IGRAPH_EINVAL); */
2019
0
        break;
2020
1.27M
    }
2021
1.27M
}
2022
2023
0
igraph_error_t igraph_eit_as_vector(const igraph_eit_t *eit, igraph_vector_int_t *v) {
2024
2025
0
    igraph_integer_t i;
2026
2027
0
    IGRAPH_CHECK(igraph_vector_int_resize(v, IGRAPH_EIT_SIZE(*eit)));
2028
2029
0
    switch (eit->type) {
2030
0
    case IGRAPH_EIT_RANGE:
2031
0
        for (i = 0; i < IGRAPH_EIT_SIZE(*eit); i++) {
2032
0
            VECTOR(*v)[i] = eit->start + i;
2033
0
        }
2034
0
        break;
2035
0
    case IGRAPH_EIT_VECTOR:
2036
0
    case IGRAPH_EIT_VECTORPTR:
2037
0
        for (i = 0; i < IGRAPH_EIT_SIZE(*eit); i++) {
2038
0
            VECTOR(*v)[i] = VECTOR(*eit->vec)[i];
2039
0
        }
2040
0
        break;
2041
0
    default:
2042
0
        IGRAPH_ERROR("Cannot convert to vector, unknown iterator type",
2043
0
                     IGRAPH_EINVAL);
2044
0
        break;
2045
0
    }
2046
2047
0
    return IGRAPH_SUCCESS;
2048
0
}