/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "random.h" META_BEGIN_NAMESPACE() namespace { // for more information see https://prng.di.unimi.it/ // xoshiro256++ implementation based on the code from https://prng.di.unimi.it/xoshiro256plusplus.c class Xoroshiro128 : public IRandom { public: Xoroshiro128(uint64_t seed) { Initialize(seed); } ~Xoroshiro128() override = default; void Initialize(uint64_t seed) override { // as recommended for xoshiro256++ initialize the state with splitmix64. uint64_t z = (seed += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s_[0] = z ^ (z >> 31); z = (seed += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s_[1] = z ^ (z >> 31); z = (seed += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s_[2] = z ^ (z >> 31); z = (seed += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s_[3] = z ^ (z >> 31); } uint64_t GetRandom() override { const uint64_t result = Rotl(s_[0] + s_[3], 23) + s_[0]; const uint64_t t = s_[1] << 17; s_[2] ^= s_[0]; s_[3] ^= s_[1]; s_[1] ^= s_[2]; s_[0] ^= s_[3]; s_[2] ^= t; s_[3] = Rotl(s_[3], 45); return result; } private: inline uint64_t Rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } uint64_t s_[4]; }; } // namespace BASE_NS::unique_ptr CreateXoroshiro128(uint64_t seed) { return BASE_NS::unique_ptr(new Xoroshiro128(seed)); } META_END_NAMESPACE()