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