| 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 |  | 
|---|