File: svrand.c

package info (click to toggle)
gretl 2026a-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 65,336 kB
  • sloc: ansic: 427,973; sh: 4,921; makefile: 3,266; cpp: 2,777; xml: 610; perl: 364
file content (62 lines) | stat: -rw-r--r-- 1,186 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* dedicated RNG for use in generating random folds dir use with SVM */

#include <stdint.h>
#include <time.h>
#include <stddef.h>

static uint64_t smx;

static inline uint64_t splitmix64_next() {
    uint64_t z = (smx += 0x9e3779b97f4a7c15);

    z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
    z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
    return z ^ (z >> 31);
}

static inline uint64_t xor_rotl (const uint64_t x, int k) {
    return (x << k) | (x >> (64 - k));
}

static uint64_t s[4];

static void set_xor_state (uint64_t u)
{
    s[0] = smx = u;
    s[1] = splitmix64_next();
    s[2] = splitmix64_next();
    s[3] = splitmix64_next();
}

static uint64_t xor_i64 (void) {
    const uint64_t ret = s[0] + s[3];
    const uint64_t t = s[1] << 17;

    s[2] ^= s[0];
    s[3] ^= s[1];
    s[1] ^= s[2];
    s[0] ^= s[3];

    s[2] ^= t;
    s[3] = xor_rotl(s[3], 45);

    return ret;
}

void svrand_init (uint64_t seed)
{
    if (seed > 0) {
        set_xor_state(seed);
    } else {
#ifdef _WIN32
        set_xor_state((uint64_t) _time64(NULL));
#else
        set_xor_state((uint64_t) time(NULL));
#endif
    }
}

uint32_t svrand (void)
{
    return (uint32_t) (xor_i64() >> 32);
}