mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-10-18 14:30:49 +00:00
130 lines
2.4 KiB
C++
130 lines
2.4 KiB
C++
/// Taken from SMHasher.
|
|
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Xorshift RNG based on code by George Marsaglia
|
|
// http://en.wikipedia.org/wiki/Xorshift
|
|
|
|
struct Rand
|
|
{
|
|
uint32_t x;
|
|
uint32_t y;
|
|
uint32_t z;
|
|
uint32_t w;
|
|
|
|
Rand()
|
|
{
|
|
reseed(static_cast<uint32_t>(0));
|
|
}
|
|
|
|
explicit Rand(uint32_t seed)
|
|
{
|
|
reseed(seed);
|
|
}
|
|
|
|
void reseed(uint32_t seed)
|
|
{
|
|
x = 0x498b3bc5 ^ seed;
|
|
y = 0;
|
|
z = 0;
|
|
w = 0;
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
mix();
|
|
}
|
|
|
|
void reseed(uint64_t seed)
|
|
{
|
|
x = 0x498b3bc5 ^ static_cast<uint32_t>(seed >> 0);
|
|
y = 0x5a05089a ^ static_cast<uint32_t>(seed >> 32);
|
|
z = 0;
|
|
w = 0;
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
mix();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void mix(void)
|
|
{
|
|
uint32_t t = x ^ (x << 11);
|
|
x = y;
|
|
y = z;
|
|
z = w;
|
|
w = w ^ (w >> 19) ^ t ^ (t >> 8);
|
|
}
|
|
|
|
uint32_t rand_u32(void)
|
|
{
|
|
mix();
|
|
|
|
return x;
|
|
}
|
|
|
|
uint64_t rand_u64(void)
|
|
{
|
|
mix();
|
|
|
|
uint64_t a = x;
|
|
uint64_t b = y;
|
|
|
|
return (a << 32) | b;
|
|
}
|
|
|
|
void rand_p(void * blob, int bytes)
|
|
{
|
|
uint32_t * blocks = reinterpret_cast<uint32_t *>(blob);
|
|
|
|
while (bytes >= 4)
|
|
{
|
|
blocks[0] = rand_u32();
|
|
blocks++;
|
|
bytes -= 4;
|
|
}
|
|
|
|
uint8_t * tail = reinterpret_cast<uint8_t *>(blocks);
|
|
|
|
for (int i = 0; i < bytes; i++)
|
|
{
|
|
tail[i] = static_cast<uint8_t>(rand_u32());
|
|
}
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
extern Rand g_rand1;
|
|
|
|
inline uint32_t rand_u32(void)
|
|
{
|
|
return g_rand1.rand_u32();
|
|
}
|
|
inline uint64_t rand_u64(void)
|
|
{
|
|
return g_rand1.rand_u64();
|
|
}
|
|
|
|
inline void rand_p(void * blob, int bytes)
|
|
{
|
|
uint32_t * blocks = static_cast<uint32_t *>(blob);
|
|
|
|
while (bytes >= 4)
|
|
{
|
|
*blocks++ = rand_u32();
|
|
bytes -= 4;
|
|
}
|
|
|
|
uint8_t * tail = reinterpret_cast<uint8_t *>(blocks);
|
|
|
|
for (int i = 0; i < bytes; i++)
|
|
{
|
|
tail[i] = static_cast<uint8_t>(rand_u32());
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|