1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "random.h" 17 18 META_BEGIN_NAMESPACE() 19 namespace { 20 // for more information see https://prng.di.unimi.it/ 21 // xoshiro256++ implementation based on the code from https://prng.di.unimi.it/xoshiro256plusplus.c 22 class Xoroshiro128 : public IRandom { 23 public: Xoroshiro128(uint64_t seed)24 Xoroshiro128(uint64_t seed) 25 { 26 Initialize(seed); 27 } 28 ~Xoroshiro128() override = default; 29 Initialize(uint64_t seed)30 void Initialize(uint64_t seed) override 31 { 32 // as recommended for xoshiro256++ initialize the state with splitmix64. 33 uint64_t z = (seed += 0x9e3779b97f4a7c15); 34 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; 35 z = (z ^ (z >> 27)) * 0x94d049bb133111eb; 36 s_[0] = z ^ (z >> 31); 37 z = (seed += 0x9e3779b97f4a7c15); 38 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; 39 z = (z ^ (z >> 27)) * 0x94d049bb133111eb; 40 s_[1] = z ^ (z >> 31); 41 z = (seed += 0x9e3779b97f4a7c15); 42 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; 43 z = (z ^ (z >> 27)) * 0x94d049bb133111eb; 44 s_[2] = z ^ (z >> 31); 45 z = (seed += 0x9e3779b97f4a7c15); 46 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; 47 z = (z ^ (z >> 27)) * 0x94d049bb133111eb; 48 s_[3] = z ^ (z >> 31); 49 } 50 GetRandom()51 uint64_t GetRandom() override 52 { 53 const uint64_t result = Rotl(s_[0] + s_[3], 23) + s_[0]; 54 const uint64_t t = s_[1] << 17; 55 s_[2] ^= s_[0]; 56 s_[3] ^= s_[1]; 57 s_[1] ^= s_[2]; 58 s_[0] ^= s_[3]; 59 s_[2] ^= t; 60 s_[3] = Rotl(s_[3], 45); 61 return result; 62 } 63 64 private: Rotl(const uint64_t x,int k)65 inline uint64_t Rotl(const uint64_t x, int k) 66 { 67 return (x << k) | (x >> (64 - k)); 68 } 69 70 uint64_t s_[4]; 71 }; 72 } // namespace 73 CreateXoroshiro128(uint64_t seed)74BASE_NS::unique_ptr<IRandom> CreateXoroshiro128(uint64_t seed) 75 { 76 return BASE_NS::unique_ptr<IRandom>(new Xoroshiro128(seed)); 77 } 78 79 META_END_NAMESPACE() 80