Commit | Line | Data |
---|---|---|
1fbbf72e JA |
1 | #ifndef FIO_RAND_H |
2 | #define FIO_RAND_H | |
3 | ||
c3546b53 | 4 | #include <inttypes.h> |
36dd3379 | 5 | #include <assert.h> |
de4096e8 | 6 | #include "types.h" |
16dc0710 | 7 | |
c3546b53 JA |
8 | #define FRAND32_MAX (-1U) |
9 | #define FRAND64_MAX (-1ULL) | |
2615cc4b | 10 | |
c3546b53 | 11 | struct taus88_state { |
1fbbf72e JA |
12 | unsigned int s1, s2, s3; |
13 | }; | |
14 | ||
c3546b53 JA |
15 | struct taus258_state { |
16 | uint64_t s1, s2, s3, s4, s5; | |
17 | }; | |
18 | ||
19 | struct frand_state { | |
20 | unsigned int use64; | |
21 | union { | |
22 | struct taus88_state state32; | |
23 | struct taus258_state state64; | |
24 | }; | |
25 | }; | |
26 | ||
c3546b53 JA |
27 | static inline uint64_t rand_max(struct frand_state *state) |
28 | { | |
29 | if (state->use64) | |
30 | return FRAND64_MAX; | |
31 | else | |
32 | return FRAND32_MAX; | |
33 | } | |
34 | ||
35 | static inline void __frand32_copy(struct taus88_state *dst, | |
36 | struct taus88_state *src) | |
37 | { | |
38 | dst->s1 = src->s1; | |
39 | dst->s2 = src->s2; | |
40 | dst->s3 = src->s3; | |
41 | } | |
42 | ||
43 | static inline void __frand64_copy(struct taus258_state *dst, | |
44 | struct taus258_state *src) | |
5c94b008 JA |
45 | { |
46 | dst->s1 = src->s1; | |
47 | dst->s2 = src->s2; | |
48 | dst->s3 = src->s3; | |
c3546b53 JA |
49 | dst->s4 = src->s4; |
50 | dst->s5 = src->s5; | |
5c94b008 JA |
51 | } |
52 | ||
c3546b53 JA |
53 | static inline void frand_copy(struct frand_state *dst, struct frand_state *src) |
54 | { | |
55 | if (src->use64) | |
56 | __frand64_copy(&dst->state64, &src->state64); | |
57 | else | |
58 | __frand32_copy(&dst->state32, &src->state32); | |
59 | ||
60 | dst->use64 = src->use64; | |
61 | } | |
62 | ||
63 | static inline unsigned int __rand32(struct taus88_state *state) | |
1fbbf72e JA |
64 | { |
65 | #define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b) | |
66 | ||
67 | state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12); | |
68 | state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4); | |
69 | state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17); | |
70 | ||
71 | return (state->s1 ^ state->s2 ^ state->s3); | |
72 | } | |
73 | ||
c3546b53 JA |
74 | static inline uint64_t __rand64(struct taus258_state *state) |
75 | { | |
76 | uint64_t xval; | |
77 | ||
78 | xval = ((state->s1 << 1) ^ state->s1) >> 53; | |
79 | state->s1 = ((state->s1 & 18446744073709551614ULL) << 10) ^ xval; | |
80 | ||
81 | xval = ((state->s2 << 24) ^ state->s2) >> 50; | |
82 | state->s2 = ((state->s2 & 18446744073709551104ULL) << 5) ^ xval; | |
83 | ||
84 | xval = ((state->s3 << 3) ^ state->s3) >> 23; | |
85 | state->s3 = ((state->s3 & 18446744073709547520ULL) << 29) ^ xval; | |
86 | ||
87 | xval = ((state->s4 << 5) ^ state->s4) >> 24; | |
88 | state->s4 = ((state->s4 & 18446744073709420544ULL) << 23) ^ xval; | |
89 | ||
90 | xval = ((state->s5 << 3) ^ state->s5) >> 33; | |
91 | state->s5 = ((state->s5 & 18446744073701163008ULL) << 8) ^ xval; | |
92 | ||
93 | return (state->s1 ^ state->s2 ^ state->s3 ^ state->s4 ^ state->s5); | |
94 | } | |
95 | ||
96 | static inline uint64_t __rand(struct frand_state *state) | |
97 | { | |
98 | if (state->use64) | |
99 | return __rand64(&state->state64); | |
100 | else | |
101 | return __rand32(&state->state32); | |
102 | } | |
103 | ||
e7b24047 JA |
104 | static inline double __rand_0_1(struct frand_state *state) |
105 | { | |
106 | if (state->use64) { | |
107 | uint64_t val = __rand64(&state->state64); | |
108 | ||
592bf458 | 109 | return (val + 1.0) / (FRAND64_MAX + 1.0); |
e7b24047 JA |
110 | } else { |
111 | uint32_t val = __rand32(&state->state32); | |
112 | ||
592bf458 | 113 | return (val + 1.0) / (FRAND32_MAX + 1.0); |
e7b24047 JA |
114 | } |
115 | } | |
116 | ||
1bd5d213 | 117 | static inline uint32_t rand32_upto(struct frand_state *state, uint32_t end) |
e0a04ac1 | 118 | { |
36dd3379 JA |
119 | uint32_t r; |
120 | ||
121 | assert(!state->use64); | |
e0a04ac1 | 122 | |
36dd3379 | 123 | r = __rand32(&state->state32); |
cdfb5a85 | 124 | end++; |
1bd5d213 | 125 | return (int) ((double)end * (r / (FRAND32_MAX + 1.0))); |
e0a04ac1 JA |
126 | } |
127 | ||
1bd5d213 | 128 | static inline uint64_t rand64_upto(struct frand_state *state, uint64_t end) |
56c77c10 JA |
129 | { |
130 | uint64_t r; | |
131 | ||
1bd5d213 JA |
132 | assert(state->use64); |
133 | ||
56c77c10 | 134 | r = __rand64(&state->state64); |
cdfb5a85 | 135 | end++; |
1bd5d213 | 136 | return (uint64_t) ((double)end * (r / (FRAND64_MAX + 1.0))); |
56c77c10 JA |
137 | } |
138 | ||
cdfb5a85 JA |
139 | /* |
140 | * Generate a random value between 'start' and 'end', both inclusive | |
141 | */ | |
56c77c10 JA |
142 | static inline uint64_t rand_between(struct frand_state *state, uint64_t start, |
143 | uint64_t end) | |
144 | { | |
145 | if (state->use64) | |
cdfb5a85 | 146 | return start + rand64_upto(state, end - start); |
56c77c10 | 147 | else |
cdfb5a85 | 148 | return start + rand32_upto(state, end - start); |
56c77c10 JA |
149 | } |
150 | ||
de4096e8 JA |
151 | extern void init_rand(struct frand_state *, bool); |
152 | extern void init_rand_seed(struct frand_state *, unsigned int seed, bool); | |
7d9fb455 | 153 | extern void __fill_random_buf(void *buf, unsigned int len, unsigned long seed); |
3545a109 | 154 | extern unsigned long fill_random_buf(struct frand_state *, void *buf, unsigned int len); |
bc769898 | 155 | extern void __fill_random_buf_percentage(unsigned long, void *, unsigned int, unsigned int, unsigned int, char *, unsigned int); |
d1af2894 | 156 | extern unsigned long fill_random_buf_percentage(struct frand_state *, void *, unsigned int, unsigned int, unsigned int, char *, unsigned int); |
1fbbf72e JA |
157 | |
158 | #endif |