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