Blame lib/rand.c

Packit Service 0e769b
/*
Packit Service 0e769b
  This is a maximally equidistributed combined Tausworthe generator
Packit Service 0e769b
  based on code from GNU Scientific Library 1.5 (30 Jun 2004)
Packit Service 0e769b
Packit Service 0e769b
   x_n = (s1_n ^ s2_n ^ s3_n)
Packit Service 0e769b
Packit Service 0e769b
   s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
Packit Service 0e769b
   s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
Packit Service 0e769b
   s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
Packit Service 0e769b
Packit Service 0e769b
   The period of this generator is about 2^88.
Packit Service 0e769b
Packit Service 0e769b
   From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
Packit Service 0e769b
   Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
Packit Service 0e769b
Packit Service 0e769b
   This is available on the net from L'Ecuyer's home page,
Packit Service 0e769b
Packit Service 0e769b
   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
Packit Service 0e769b
   ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps
Packit Service 0e769b
Packit Service 0e769b
   There is an erratum in the paper "Tables of Maximally
Packit Service 0e769b
   Equidistributed Combined LFSR Generators", Mathematics of
Packit Service 0e769b
   Computation, 68, 225 (1999), 261--269:
Packit Service 0e769b
   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
Packit Service 0e769b
Packit Service 0e769b
        ... the k_j most significant bits of z_j must be non-
Packit Service 0e769b
        zero, for each j. (Note: this restriction also applies to the
Packit Service 0e769b
        computer code given in [4], but was mistakenly not mentioned in
Packit Service 0e769b
        that paper.)
Packit Service 0e769b
Packit Service 0e769b
   This affects the seeding procedure by imposing the requirement
Packit Service 0e769b
   s1 > 1, s2 > 7, s3 > 15.
Packit Service 0e769b
Packit Service 0e769b
*/
Packit Service 0e769b
Packit Service 0e769b
#include <string.h>
Packit Service 0e769b
#include "rand.h"
Packit Service 0e769b
#include "pattern.h"
Packit Service 0e769b
#include "../hash.h"
Packit Service 0e769b
Packit Service 0e769b
int arch_random;
Packit Service 0e769b
Packit Service 0e769b
static inline uint64_t __seed(uint64_t x, uint64_t m)
Packit Service 0e769b
{
Packit Service 0e769b
	return (x < m) ? x + m : x;
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
static void __init_rand32(struct taus88_state *state, unsigned int seed)
Packit Service 0e769b
{
Packit Service 0e769b
	int cranks = 6;
Packit Service 0e769b
Packit Service 0e769b
#define LCG(x, seed)  ((x) * 69069 ^ (seed))
Packit Service 0e769b
Packit Service 0e769b
	state->s1 = __seed(LCG((2^31) + (2^17) + (2^7), seed), 1);
Packit Service 0e769b
	state->s2 = __seed(LCG(state->s1, seed), 7);
Packit Service 0e769b
	state->s3 = __seed(LCG(state->s2, seed), 15);
Packit Service 0e769b
Packit Service 0e769b
	while (cranks--)
Packit Service 0e769b
		__rand32(state);
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
static void __init_rand64(struct taus258_state *state, uint64_t seed)
Packit Service 0e769b
{
Packit Service 0e769b
	int cranks = 6;
Packit Service 0e769b
Packit Service 0e769b
#define LCG64(x, seed)  ((x) * 6906969069ULL ^ (seed))
Packit Service 0e769b
Packit Service 0e769b
	state->s1 = __seed(LCG64((2^31) + (2^17) + (2^7), seed), 1);
Packit Service 0e769b
	state->s2 = __seed(LCG64(state->s1, seed), 7);
Packit Service 0e769b
	state->s3 = __seed(LCG64(state->s2, seed), 15);
Packit Service 0e769b
	state->s4 = __seed(LCG64(state->s3, seed), 33);
Packit Service 0e769b
	state->s5 = __seed(LCG64(state->s4, seed), 49);
Packit Service 0e769b
Packit Service 0e769b
	while (cranks--)
Packit Service 0e769b
		__rand64(state);
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
void init_rand(struct frand_state *state, bool use64)
Packit Service 0e769b
{
Packit Service 0e769b
	state->use64 = use64;
Packit Service 0e769b
Packit Service 0e769b
	if (!use64)
Packit Service 0e769b
		__init_rand32(&state->state32, 1);
Packit Service 0e769b
	else
Packit Service 0e769b
		__init_rand64(&state->state64, 1);
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
void init_rand_seed(struct frand_state *state, unsigned int seed, bool use64)
Packit Service 0e769b
{
Packit Service 0e769b
	state->use64 = use64;
Packit Service 0e769b
Packit Service 0e769b
	if (!use64)
Packit Service 0e769b
		__init_rand32(&state->state32, seed);
Packit Service 0e769b
	else
Packit Service 0e769b
		__init_rand64(&state->state64, seed);
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
void __fill_random_buf(void *buf, unsigned int len, uint64_t seed)
Packit Service 0e769b
{
Packit Service 0e769b
	void *ptr = buf;
Packit Service 0e769b
Packit Service 0e769b
	while (len) {
Packit Service 0e769b
		int this_len;
Packit Service 0e769b
Packit Service 0e769b
		if (len >= sizeof(int64_t)) {
Packit Service 0e769b
			*((int64_t *) ptr) = seed;
Packit Service 0e769b
			this_len = sizeof(int64_t);
Packit Service 0e769b
		} else if (len >= sizeof(int32_t)) {
Packit Service 0e769b
			*((int32_t *) ptr) = seed;
Packit Service 0e769b
			this_len = sizeof(int32_t);
Packit Service 0e769b
		} else if (len >= sizeof(int16_t)) {
Packit Service 0e769b
			*((int16_t *) ptr) = seed;
Packit Service 0e769b
			this_len = sizeof(int16_t);
Packit Service 0e769b
		} else {
Packit Service 0e769b
			*((int8_t *) ptr) = seed;
Packit Service 0e769b
			this_len = sizeof(int8_t);
Packit Service 0e769b
		}
Packit Service 0e769b
		ptr += this_len;
Packit Service 0e769b
		len -= this_len;
Packit Service 0e769b
		seed *= GOLDEN_RATIO_PRIME;
Packit Service 0e769b
		seed >>= 3;
Packit Service 0e769b
	}
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
uint64_t fill_random_buf(struct frand_state *fs, void *buf,
Packit Service 0e769b
			 unsigned int len)
Packit Service 0e769b
{
Packit Service 0e769b
	uint64_t r = __rand(fs);
Packit Service 0e769b
Packit Service 0e769b
	if (sizeof(int) != sizeof(long *))
Packit Service 0e769b
		r *= (unsigned long) __rand(fs);
Packit Service 0e769b
Packit Service 0e769b
	__fill_random_buf(buf, len, r);
Packit Service 0e769b
	return r;
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
void __fill_random_buf_percentage(uint64_t seed, void *buf,
Packit Service 0e769b
				  unsigned int percentage,
Packit Service 0e769b
				  unsigned int segment, unsigned int len,
Packit Service 0e769b
				  char *pattern, unsigned int pbytes)
Packit Service 0e769b
{
Packit Service 0e769b
	unsigned int this_len;
Packit Service 0e769b
Packit Service 0e769b
	if (percentage == 100) {
Packit Service 0e769b
		if (pbytes)
Packit Service 0e769b
			(void)cpy_pattern(pattern, pbytes, buf, len);
Packit Service 0e769b
		else
Packit Service 0e769b
			memset(buf, 0, len);
Packit Service 0e769b
		return;
Packit Service 0e769b
	}
Packit Service 0e769b
Packit Service 0e769b
	if (segment > len)
Packit Service 0e769b
		segment = len;
Packit Service 0e769b
Packit Service 0e769b
	while (len) {
Packit Service 0e769b
		/*
Packit Service 0e769b
		 * Fill random chunk
Packit Service 0e769b
		 */
Packit Service 0e769b
		this_len = ((unsigned long long)segment * (100 - percentage)) / 100;
Packit Service 0e769b
		if (this_len > len)
Packit Service 0e769b
			this_len = len;
Packit Service 0e769b
Packit Service 0e769b
		__fill_random_buf(buf, this_len, seed);
Packit Service 0e769b
Packit Service 0e769b
		len -= this_len;
Packit Service 0e769b
		if (!len)
Packit Service 0e769b
			break;
Packit Service 0e769b
		buf += this_len;
Packit Service 0e769b
		this_len = segment - this_len;
Packit Service 0e769b
Packit Service 0e769b
		if (this_len > len)
Packit Service 0e769b
			this_len = len;
Packit Service 0e769b
		else if (len - this_len <= sizeof(long))
Packit Service 0e769b
			this_len = len;
Packit Service 0e769b
Packit Service 0e769b
		if (pbytes)
Packit Service 0e769b
			(void)cpy_pattern(pattern, pbytes, buf, this_len);
Packit Service 0e769b
		else
Packit Service 0e769b
			memset(buf, 0, this_len);
Packit Service 0e769b
Packit Service 0e769b
		len -= this_len;
Packit Service 0e769b
		buf += this_len;
Packit Service 0e769b
	}
Packit Service 0e769b
}
Packit Service 0e769b
Packit Service 0e769b
uint64_t fill_random_buf_percentage(struct frand_state *fs, void *buf,
Packit Service 0e769b
				    unsigned int percentage,
Packit Service 0e769b
				    unsigned int segment, unsigned int len,
Packit Service 0e769b
				    char *pattern, unsigned int pbytes)
Packit Service 0e769b
{
Packit Service 0e769b
	uint64_t r = __rand(fs);
Packit Service 0e769b
Packit Service 0e769b
	if (sizeof(int) != sizeof(long *))
Packit Service 0e769b
		r *= (unsigned long) __rand(fs);
Packit Service 0e769b
Packit Service 0e769b
	__fill_random_buf_percentage(r, buf, percentage, segment, len,
Packit Service 0e769b
					pattern, pbytes);
Packit Service 0e769b
	return r;
Packit Service 0e769b
}