Coverage Report

Created: 2025-11-14 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/igraph/src/random/rng_pcg32.c
Line
Count
Source
1
/*
2
   igraph library.
3
   Copyright (C) 2022  The igraph development team <igraph@igraph.org>
4
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 2 of the License, or
8
   (at your option) any later version.
9
10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14
15
   You should have received a copy of the GNU General Public License
16
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
*/
18
19
#include "igraph_random.h"
20
21
#include "igraph_memory.h"
22
#include "igraph_types.h"
23
24
#include "pcg/pcg_variants.h"
25
26
/* The original implementation of the 32-bit PCG random number generator in this
27
 * file was obtained from https://github.com/imneme/pcg-c
28
 *
29
 * PCG is dual-licensed under Apache-2.0 and MIT Licenses. MIT is compatible
30
 * with igraph's GPLv2 license. License notices for PCG are to be found in the
31
 * pcg_variants.h header
32
 */
33
34
static const pcg32_random_t pcg32_initializer = PCG32_INITIALIZER;
35
36
0
static igraph_uint_t igraph_rng_pcg32_get(void *vstate) {
37
0
    pcg32_random_t *state = (pcg32_random_t*) vstate;
38
0
    return pcg32_random_r(state);
39
0
}
40
41
0
static igraph_error_t igraph_rng_pcg32_seed(void *vstate, igraph_uint_t seed) {
42
0
    pcg32_random_t *state = (pcg32_random_t*) vstate;
43
44
    /* PCG32 is seeded by a 64-bit state and a 64-bit sequence number (well, only
45
     * 63 bits are used from the sequence number, though). Since the unified
46
     * igraph RNG seeding interface provides a single igraph_uint_t as the seed,
47
     * we use the seed to fill in the sequence number and use the state from
48
     * PCG32_INITIALIZER */
49
0
    if (seed == 0) {
50
        /* If you feel the temptation to unify the two branches by running
51
         * seed = pcg32_initializer.inc >> 1, don't.
52
         * seed is an igraph_uint_t, so it can be 32-bit or 64-bit.
53
         * pcg32_initializer.inc is always 64-bit.
54
         */
55
0
        pcg32_srandom_r(state, pcg32_initializer.state, pcg32_initializer.inc >> 1);
56
0
    } else {
57
0
        pcg32_srandom_r(state, pcg32_initializer.state, seed);
58
0
    }
59
60
0
    return IGRAPH_SUCCESS;
61
0
}
62
63
0
static igraph_error_t igraph_rng_pcg32_init(void **state) {
64
0
    pcg32_random_t *st;
65
66
0
    st = IGRAPH_CALLOC(1, pcg32_random_t);
67
0
    IGRAPH_CHECK_OOM(st, "Cannot initialize PCG32 RNG.");
68
0
    (*state) = st;
69
70
0
    igraph_rng_pcg32_seed(st, 0);
71
72
0
    return IGRAPH_SUCCESS;
73
0
}
74
75
0
static void igraph_rng_pcg32_destroy(void *vstate) {
76
0
    pcg32_random_t *state = (pcg32_random_t*) vstate;
77
    IGRAPH_FREE(state);
78
0
}
79
80
/**
81
 * \var igraph_rngtype_pcg32
82
 * \brief The PCG random number generator (32-bit version).
83
 *
84
 * This is an implementation of the PCG random number generator; see
85
 * https://www.pcg-random.org for more details. This implementation returns
86
 * 32 random bits in a single iteration.
87
 *
88
 * </para><para>
89
 * The generator was ported from the original source code published by the
90
 * authors at https://github.com/imneme/pcg-c.
91
 */
92
93
const igraph_rng_type_t igraph_rngtype_pcg32 = {
94
    /* name= */      "PCG32",
95
    /* bits=  */     32,
96
    /* init= */      igraph_rng_pcg32_init,
97
    /* destroy= */   igraph_rng_pcg32_destroy,
98
    /* seed= */      igraph_rng_pcg32_seed,
99
    /* get= */       igraph_rng_pcg32_get,
100
    /* get_int= */   NULL,
101
    /* get_real= */  NULL,
102
    /* get_norm= */  NULL,
103
    /* get_geom= */  NULL,
104
    /* get_binom= */ NULL,
105
    /* get_exp= */   NULL,
106
    /* get_gamma= */ NULL,
107
    /* get_pois= */  NULL
108
};
109
110
/***** Default RNG, used upon igraph startup *****/
111
112
#define addr(a) (&a)
113
114
static pcg32_random_t igraph_i_rng_default_state = PCG32_INITIALIZER;
115
116
igraph_rng_t igraph_i_rng_default = {
117
    addr(igraph_rngtype_pcg32),
118
    addr(igraph_i_rng_default_state),
119
    /* is_seeded = */ false
120
};
121
122
#undef addr