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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
#ifndef FIO_RAND_H
#define FIO_RAND_H
#include <inttypes.h>
#include <assert.h>
#include "types.h"
#define FRAND32_MAX (-1U)
#define FRAND32_MAX_PLUS_ONE (1.0 * (1ULL << 32))
#define FRAND64_MAX (-1ULL)
#define FRAND64_MAX_PLUS_ONE (1.0 * (1ULL << 32) * (1ULL << 32))
struct taus88_state {
unsigned int s1, s2, s3;
};
struct taus258_state {
uint64_t s1, s2, s3, s4, s5;
};
struct frand_state {
unsigned int use64;
union {
struct taus88_state state32;
struct taus258_state state64;
};
};
static inline uint64_t rand_max(struct frand_state *state)
{
if (state->use64)
return FRAND64_MAX;
else
return FRAND32_MAX;
}
static inline void __frand32_copy(struct taus88_state *dst,
struct taus88_state *src)
{
dst->s1 = src->s1;
dst->s2 = src->s2;
dst->s3 = src->s3;
}
static inline void __frand64_copy(struct taus258_state *dst,
struct taus258_state *src)
{
dst->s1 = src->s1;
dst->s2 = src->s2;
dst->s3 = src->s3;
dst->s4 = src->s4;
dst->s5 = src->s5;
}
static inline void frand_copy(struct frand_state *dst, struct frand_state *src)
{
if (src->use64)
__frand64_copy(&dst->state64, &src->state64);
else
__frand32_copy(&dst->state32, &src->state32);
dst->use64 = src->use64;
}
static inline unsigned int __rand32(struct taus88_state *state)
{
#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
return (state->s1 ^ state->s2 ^ state->s3);
}
static inline uint64_t __rand64(struct taus258_state *state)
{
uint64_t xval;
xval = ((state->s1 << 1) ^ state->s1) >> 53;
state->s1 = ((state->s1 & 18446744073709551614ULL) << 10) ^ xval;
xval = ((state->s2 << 24) ^ state->s2) >> 50;
state->s2 = ((state->s2 & 18446744073709551104ULL) << 5) ^ xval;
xval = ((state->s3 << 3) ^ state->s3) >> 23;
state->s3 = ((state->s3 & 18446744073709547520ULL) << 29) ^ xval;
xval = ((state->s4 << 5) ^ state->s4) >> 24;
state->s4 = ((state->s4 & 18446744073709420544ULL) << 23) ^ xval;
xval = ((state->s5 << 3) ^ state->s5) >> 33;
state->s5 = ((state->s5 & 18446744073701163008ULL) << 8) ^ xval;
return (state->s1 ^ state->s2 ^ state->s3 ^ state->s4 ^ state->s5);
}
static inline uint64_t __rand(struct frand_state *state)
{
if (state->use64)
return __rand64(&state->state64);
else
return __rand32(&state->state32);
}
static inline double __rand_0_1(struct frand_state *state)
{
if (state->use64) {
uint64_t val = __rand64(&state->state64);
return (val + 1.0) / FRAND64_MAX_PLUS_ONE;
} else {
uint32_t val = __rand32(&state->state32);
return (val + 1.0) / FRAND32_MAX_PLUS_ONE;
}
}
static inline uint32_t rand32_upto(struct frand_state *state, uint32_t end)
{
uint32_t r;
assert(!state->use64);
r = __rand32(&state->state32);
end++;
return (int) ((double)end * (r / FRAND32_MAX_PLUS_ONE));
}
static inline uint64_t rand64_upto(struct frand_state *state, uint64_t end)
{
uint64_t r;
assert(state->use64);
r = __rand64(&state->state64);
end++;
return (uint64_t) ((double)end * (r / FRAND64_MAX_PLUS_ONE));
}
/*
* Generate a random value between 'start' and 'end', both inclusive
*/
static inline uint64_t rand_between(struct frand_state *state, uint64_t start,
uint64_t end)
{
if (state->use64)
return start + rand64_upto(state, end - start);
else
return start + rand32_upto(state, end - start);
}
static inline uint64_t __get_next_seed(struct frand_state *fs)
{
uint64_t r = __rand(fs);
if (sizeof(int) != sizeof(long *))
r *= (unsigned long) __rand(fs);
return r;
}
extern void init_rand(struct frand_state *, bool);
extern void init_rand_seed(struct frand_state *, uint64_t seed, bool);
void __init_rand64(struct taus258_state *state, uint64_t seed);
extern void __fill_random_buf(void *buf, unsigned int len, uint64_t seed);
extern uint64_t fill_random_buf(struct frand_state *, void *buf, unsigned int len);
extern void __fill_random_buf_percentage(uint64_t, void *, unsigned int, unsigned int, unsigned int, char *, unsigned int);
extern uint64_t fill_random_buf_percentage(struct frand_state *, void *, unsigned int, unsigned int, unsigned int, char *, unsigned int);
#endif
|