main xs_random.h
 1/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */
 2
 3#ifndef _XS_RANDOM_H
 4
 5#define _XS_RANDOM_H
 6
 7#include "xs.h"
 8
 9unsigned int xs_rnd_int32_d(unsigned int *seed);
10void *xs_rnd_buf(void *buf, int size);
11
12#ifdef XS_IMPLEMENTATION
13
14#include <stdio.h>
15#include <sys/time.h>
16#include <unistd.h>
17#include <stdlib.h>
18
19unsigned int xs_rnd_int32_d(unsigned int *seed)
20/* returns a deterministic random integer. If seed is NULL, uses a static one */
21{
22    static unsigned int s = 0;
23
24    if (seed == NULL)
25        seed = &s;
26
27    if (*seed == 0) {
28        struct timeval tv;
29
30        gettimeofday(&tv, NULL);
31        *seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
32    }
33
34    /* Linear congruential generator by Numerical Recipes */
35    *seed = (*seed * 1664525) + 1013904223;
36
37    return *seed;
38}
39
40
41void *xs_rnd_buf(void *buf, int size)
42/* fills buf with random data */
43{
44#ifdef __OpenBSD__
45
46    /* available since OpenBSD 2.2 */
47    arc4random_buf(buf, size);
48
49#else
50
51    FILE *f;
52    int done = 0;
53
54    if ((f = fopen("/dev/urandom", "r")) != NULL) {
55        /* fill with great random data from the system */
56        if (fread(buf, size, 1, f) == 1)
57            done = 1;
58
59        fclose(f);
60    }
61
62    if (!done) {
63        /* fill the buffer with poor quality, deterministic data */
64        unsigned int s   = 0;
65        unsigned char *p = (unsigned char *)buf;
66        int n            = size / sizeof(s);
67
68        /* fill with full integers */
69        while (n--) {
70            xs_rnd_int32_d(&s);
71            memcpy(p, &s, sizeof(s));
72            p += sizeof(s);
73        }
74
75        if ((n = size % sizeof(s))) {
76            /* fill the remaining */
77            xs_rnd_int32_d(&s);
78            memcpy(p, &s, n);
79        }
80    }
81
82#endif /* __OpenBSD__ */
83
84    return buf;
85}
86
87
88#endif /* XS_IMPLEMENTATION */
89
90#endif /* XS_RANDOM_H */