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 */