2017-04-01 09:19:00 +00:00
|
|
|
#include <Functions/FunctionFactory.h>
|
|
|
|
#include <Functions/FunctionsRandom.h>
|
2018-12-02 01:57:01 +00:00
|
|
|
#include <Common/HashTable/Hash.h>
|
|
|
|
#include <Common/randomSeed.h>
|
|
|
|
#include <common/unaligned.h>
|
|
|
|
|
2014-08-22 00:57:20 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2020-04-13 09:26:56 +00:00
|
|
|
DECLARE_MULTITARGET_CODE(
|
|
|
|
|
2018-12-02 01:57:01 +00:00
|
|
|
namespace
|
2017-07-25 17:00:38 +00:00
|
|
|
{
|
2020-05-15 12:00:20 +00:00
|
|
|
/// NOTE Probably
|
|
|
|
/// http://www.pcg-random.org/
|
|
|
|
/// or http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/
|
|
|
|
/// or http://docs.yeppp.info/c/group__yep_random___w_e_l_l1024a.html
|
|
|
|
/// could go better.
|
|
|
|
|
2018-12-02 01:57:01 +00:00
|
|
|
struct LinearCongruentialGenerator
|
|
|
|
{
|
2020-05-15 12:00:20 +00:00
|
|
|
/// Constants from `man lrand48_r`.
|
2018-12-02 01:57:01 +00:00
|
|
|
static constexpr UInt64 a = 0x5DEECE66D;
|
|
|
|
static constexpr UInt64 c = 0xB;
|
|
|
|
|
2020-05-15 12:00:20 +00:00
|
|
|
/// And this is from `head -c8 /dev/urandom | xxd -p`
|
2018-12-02 01:57:01 +00:00
|
|
|
UInt64 current = 0x09826f4a081cee35ULL;
|
|
|
|
|
|
|
|
void seed(UInt64 value)
|
|
|
|
{
|
|
|
|
current = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
UInt32 next()
|
|
|
|
{
|
|
|
|
current = current * a + c;
|
|
|
|
return current >> 16;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-07-25 17:00:38 +00:00
|
|
|
void seed(LinearCongruentialGenerator & generator, intptr_t additional_seed)
|
|
|
|
{
|
|
|
|
generator.seed(intHash64(randomSeed() ^ intHash64(additional_seed)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-02 01:57:01 +00:00
|
|
|
void RandImpl::execute(char * output, size_t size)
|
|
|
|
{
|
|
|
|
LinearCongruentialGenerator generator0;
|
|
|
|
LinearCongruentialGenerator generator1;
|
|
|
|
LinearCongruentialGenerator generator2;
|
|
|
|
LinearCongruentialGenerator generator3;
|
2017-07-25 17:00:38 +00:00
|
|
|
|
2018-12-02 01:57:01 +00:00
|
|
|
seed(generator0, 0xfb4121280b2ab902ULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator1, 0x0121cf76df39c673ULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator2, 0x17ae86e3a19a602fULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator3, 0x8b6e16da7e06d622ULL + reinterpret_cast<intptr_t>(output));
|
2017-07-25 17:00:38 +00:00
|
|
|
|
2018-12-02 01:57:01 +00:00
|
|
|
for (const char * end = output + size; output < end; output += 16)
|
|
|
|
{
|
2019-06-28 16:21:05 +00:00
|
|
|
unalignedStore<UInt32>(output, generator0.next());
|
|
|
|
unalignedStore<UInt32>(output + 4, generator1.next());
|
|
|
|
unalignedStore<UInt32>(output + 8, generator2.next());
|
|
|
|
unalignedStore<UInt32>(output + 12, generator3.next());
|
2018-12-02 01:57:01 +00:00
|
|
|
}
|
2020-05-15 12:00:20 +00:00
|
|
|
/// It is guaranteed (by PaddedPODArray) that we can overwrite up to 15 bytes after end.
|
2014-08-22 00:57:20 +00:00
|
|
|
}
|
|
|
|
|
2020-05-18 07:24:22 +00:00
|
|
|
void RandImpl2::execute(char * output, size_t size)
|
|
|
|
{
|
|
|
|
if (size == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
LinearCongruentialGenerator generator0;
|
|
|
|
LinearCongruentialGenerator generator1;
|
|
|
|
LinearCongruentialGenerator generator2;
|
|
|
|
LinearCongruentialGenerator generator3;
|
|
|
|
LinearCongruentialGenerator generator4;
|
|
|
|
LinearCongruentialGenerator generator5;
|
|
|
|
LinearCongruentialGenerator generator6;
|
|
|
|
LinearCongruentialGenerator generator7;
|
|
|
|
|
|
|
|
seed(generator0, 0xfb4121280b2ab902ULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator1, 0x0121cf76df39c673ULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator2, 0x17ae86e3a19a602fULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator3, 0x8b6e16da7e06d622ULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator4, 0xfb4122280b2ab102ULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator5, 0x0121c276df39c173ULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator6, 0x17ae82e3a19a612fULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
seed(generator7, 0x8b6e12da7e06d122ULL + reinterpret_cast<intptr_t>(output));
|
|
|
|
|
|
|
|
const char * end = output + size;
|
|
|
|
|
|
|
|
for (; (end - output + 15) <= 32; output += 32)
|
|
|
|
{
|
|
|
|
unalignedStore<UInt32>(output, generator0.next());
|
|
|
|
unalignedStore<UInt32>(output + 4, generator1.next());
|
|
|
|
unalignedStore<UInt32>(output + 8, generator2.next());
|
|
|
|
unalignedStore<UInt32>(output + 12, generator3.next());
|
|
|
|
unalignedStore<UInt32>(output + 16, generator4.next());
|
|
|
|
unalignedStore<UInt32>(output + 20, generator5.next());
|
|
|
|
unalignedStore<UInt32>(output + 24, generator6.next());
|
|
|
|
unalignedStore<UInt32>(output + 28, generator7.next());
|
|
|
|
}
|
|
|
|
|
2020-05-18 17:07:36 +00:00
|
|
|
if (end - output > 0)
|
|
|
|
{
|
2020-05-18 07:24:22 +00:00
|
|
|
unalignedStore<UInt32>(output, generator0.next());
|
|
|
|
unalignedStore<UInt32>(output + 4, generator1.next());
|
|
|
|
unalignedStore<UInt32>(output + 8, generator2.next());
|
|
|
|
unalignedStore<UInt32>(output + 12, generator3.next());
|
|
|
|
output += 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-13 09:26:56 +00:00
|
|
|
) //DECLARE_MULTITARGET_CODE
|
|
|
|
|
2014-08-22 00:57:20 +00:00
|
|
|
}
|