1#include <Functions/FunctionFactory.h>
2#include <Functions/FunctionsRandom.h>
3#include <Common/HashTable/Hash.h>
4#include <Common/randomSeed.h>
5#include <common/unaligned.h>
6
7
8namespace DB
9{
10
11namespace
12{
13 /// NOTE Probably
14 /// http://www.pcg-random.org/
15 /// or http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/
16 /// or http://docs.yeppp.info/c/group__yep_random___w_e_l_l1024a.html
17 /// could go better.
18
19 struct LinearCongruentialGenerator
20 {
21 /// Constants from `man lrand48_r`.
22 static constexpr UInt64 a = 0x5DEECE66D;
23 static constexpr UInt64 c = 0xB;
24
25 /// And this is from `head -c8 /dev/urandom | xxd -p`
26 UInt64 current = 0x09826f4a081cee35ULL;
27
28 void seed(UInt64 value)
29 {
30 current = value;
31 }
32
33 UInt32 next()
34 {
35 current = current * a + c;
36 return current >> 16;
37 }
38 };
39
40 void seed(LinearCongruentialGenerator & generator, intptr_t additional_seed)
41 {
42 generator.seed(intHash64(randomSeed() ^ intHash64(additional_seed)));
43 }
44}
45
46void RandImpl::execute(char * output, size_t size)
47{
48 LinearCongruentialGenerator generator0;
49 LinearCongruentialGenerator generator1;
50 LinearCongruentialGenerator generator2;
51 LinearCongruentialGenerator generator3;
52
53 seed(generator0, 0xfb4121280b2ab902ULL + reinterpret_cast<intptr_t>(output));
54 seed(generator1, 0x0121cf76df39c673ULL + reinterpret_cast<intptr_t>(output));
55 seed(generator2, 0x17ae86e3a19a602fULL + reinterpret_cast<intptr_t>(output));
56 seed(generator3, 0x8b6e16da7e06d622ULL + reinterpret_cast<intptr_t>(output));
57
58 for (const char * end = output + size; output < end; output += 16)
59 {
60 unalignedStore<UInt32>(output, generator0.next());
61 unalignedStore<UInt32>(output + 4, generator1.next());
62 unalignedStore<UInt32>(output + 8, generator2.next());
63 unalignedStore<UInt32>(output + 12, generator3.next());
64 }
65
66 /// It is guaranteed (by PaddedPODArray) that we can overwrite up to 15 bytes after end.
67}
68
69}
70