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