blob: bd235233d75fa2d375bc1d616e8ad0fc262e7a96 (
plain)
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
|
/* libmisc/rand.c - Non-crytpographic random-number utilities
*
* Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libmisc/assert.h>
#include <libmisc/_intercept.h>
#include <libmisc/rand.h>
uint32_t rand_uint32(void) {
return __lm_rand_uint32();
}
uint64_t rand_uint64(void) {
return __lm_rand_uint64();
}
uint32_t rand_uint31n(uint32_t cnt) {
assert(cnt != 0 && ((cnt-1) & 0x80000000) == 0);
uint32_t fair_cnt = ((UINT32_C(1)<<31) / cnt) * cnt;
uint32_t rnd;
do {
rnd = __lm_rand_uint31();
} while (rnd >= fair_cnt);
return rnd % cnt;
}
uint64_t rand_uint63n(uint64_t cnt) {
assert(cnt != 0 && ((cnt-1) & 0x8000000000000000) == 0);
if (cnt <= UINT64_C(1)<<31) {
return rand_uint31n(cnt);
} else if (cnt <= UINT64_C(1)<<32) {
uint64_t fair_cnt = ((UINT64_C(1)<<32) / cnt) * cnt;
uint64_t rnd;
do {
rnd = __lm_rand_uint32();
} while (rnd >= fair_cnt);
return rnd % cnt;
} else if (cnt <= UINT64_C(1)<<62) {
uint64_t fair_cnt = ((UINT64_C(1)<<62) / cnt) * cnt;
uint64_t rnd;
do {
rnd = __lm_rand_uint62();
} while (rnd >= fair_cnt);
return rnd % cnt;
} else {
uint64_t fair_cnt = ((UINT64_C(1)<<63) / cnt) * cnt;
uint64_t rnd;
do {
rnd = __lm_rand_uint63();
} while (rnd >= fair_cnt);
return rnd % cnt;
}
}
|