Coverage Report

Created: 2025-04-11 06:16

/src/igraph/src/random/rng_pcg32.c
Line
Count
Source (jump to first uncovered line)
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
#include "config.h" /* IGRAPH_THREAD_LOCAL */
27
28
/* The original implementation of the 32-bit PCG random number generator in this
29
 * file was obtained from https://github.com/imneme/pcg-c
30
 *
31
 * PCG is dual-licensed under Apache-2.0 and MIT Licenses. MIT is compatible
32
 * with igraph's GPLv2 license. License notices for PCG are to be found in the
33
 * pcg_variants.h header
34
 */
35
36
static const pcg32_random_t pcg32_initializer = PCG32_INITIALIZER;
37
38
419M
static igraph_uint_t igraph_rng_pcg32_get(void *vstate) {
39
419M
    pcg32_random_t *state = (pcg32_random_t*) vstate;
40
419M
    return pcg32_random_r(state);
41
419M
}
42
43
3.48k
static igraph_error_t igraph_rng_pcg32_seed(void *vstate, igraph_uint_t seed) {
44
3.48k
    pcg32_random_t *state = (pcg32_random_t*) vstate;
45
46
    /* PCG32 is seeded by a 64-bit state and a 64-bit sequence number (well, only
47
     * 63 bits are used from the sequence number, though). Since the unified
48
     * igraph RNG seeding interface provides a single igraph_uint_t as the seed,
49
     * we use the seed to fill in the sequence number and use the state from
50
     * PCG32_INITIALIZER */
51
3.48k
    if (seed == 0) {
52
        /* If you feel the temptation to unify the two branches by running
53
         * seed = pcg32_initializer.inc >> 1, don't.
54
         * seed is an igraph_uint_t, so it can be 32-bit or 64-bit.
55
         * pcg32_initializer.inc is always 64-bit.
56
         */
57
0
        pcg32_srandom_r(state, pcg32_initializer.state, pcg32_initializer.inc >> 1);
58
3.48k
    } else {
59
3.48k
        pcg32_srandom_r(state, pcg32_initializer.state, seed);
60
3.48k
    }
61
62
3.48k
    return IGRAPH_SUCCESS;
63
3.48k
}
64
65
0
static igraph_error_t igraph_rng_pcg32_init(void **state) {
66
0
    pcg32_random_t *st;
67
68
0
    st = IGRAPH_CALLOC(1, pcg32_random_t);
69
0
    IGRAPH_CHECK_OOM(st, "Cannot initialize PCG32 RNG.");
70
0
    (*state) = st;
71
72
0
    igraph_rng_pcg32_seed(st, 0);
73
74
0
    return IGRAPH_SUCCESS;
75
0
}
76
77
0
static void igraph_rng_pcg32_destroy(void *vstate) {
78
0
    pcg32_random_t *state = (pcg32_random_t*) vstate;
79
0
    IGRAPH_FREE(state);
80
0
}
81
82
/**
83
 * \var igraph_rngtype_pcg32
84
 * \brief The PCG random number generator (32-bit version).
85
 *
86
 * This is an implementation of the PCG random number generator; see
87
 * https://www.pcg-random.org for more details. This implementation returns
88
 * 32 random bits in a single iteration.
89
 *
90
 * </para><para>
91
 * The generator was ported from the original source code published by the
92
 * authors at https://github.com/imneme/pcg-c.
93
 */
94
95
const igraph_rng_type_t igraph_rngtype_pcg32 = {
96
    /* name= */      "PCG32",
97
    /* bits=  */     32,
98
    /* init= */      igraph_rng_pcg32_init,
99
    /* destroy= */   igraph_rng_pcg32_destroy,
100
    /* seed= */      igraph_rng_pcg32_seed,
101
    /* get= */       igraph_rng_pcg32_get,
102
    /* get_int= */   NULL,
103
    /* get_real= */  NULL,
104
    /* get_norm= */  NULL,
105
    /* get_geom= */  NULL,
106
    /* get_binom= */ NULL,
107
    /* get_exp= */   NULL,
108
    /* get_gamma= */ NULL,
109
    /* get_pois= */  NULL
110
};
111
112
/***** Default RNG, used upon igraph startup *****/
113
114
#define addr(a) (&a)
115
116
static pcg32_random_t igraph_i_rng_default_state = PCG32_INITIALIZER;
117
118
igraph_rng_t igraph_i_rng_default = {
119
    addr(igraph_rngtype_pcg32),
120
    addr(igraph_i_rng_default_state),
121
    /* is_seeded = */ true
122
};
123
124
#undef addr