Coverage Report

Created: 2025-04-11 06:16

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