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 | |
8 | namespace DB |
9 | { |
10 | |
11 | namespace |
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 | |
46 | void 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 | |