18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#include "random.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
198bf80f4bSopenharmony_cinamespace {
208bf80f4bSopenharmony_ci// for more information see https://prng.di.unimi.it/
218bf80f4bSopenharmony_ci// xoshiro256++ implementation based on the code from https://prng.di.unimi.it/xoshiro256plusplus.c
228bf80f4bSopenharmony_ciclass Xoroshiro128 : public IRandom {
238bf80f4bSopenharmony_cipublic:
248bf80f4bSopenharmony_ci    Xoroshiro128(uint64_t seed)
258bf80f4bSopenharmony_ci    {
268bf80f4bSopenharmony_ci        Initialize(seed);
278bf80f4bSopenharmony_ci    }
288bf80f4bSopenharmony_ci    ~Xoroshiro128() override = default;
298bf80f4bSopenharmony_ci
308bf80f4bSopenharmony_ci    void Initialize(uint64_t seed) override
318bf80f4bSopenharmony_ci    {
328bf80f4bSopenharmony_ci        // as recommended for xoshiro256++ initialize the state with splitmix64.
338bf80f4bSopenharmony_ci        uint64_t z = (seed += 0x9e3779b97f4a7c15);
348bf80f4bSopenharmony_ci        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
358bf80f4bSopenharmony_ci        z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
368bf80f4bSopenharmony_ci        s_[0] = z ^ (z >> 31);
378bf80f4bSopenharmony_ci        z = (seed += 0x9e3779b97f4a7c15);
388bf80f4bSopenharmony_ci        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
398bf80f4bSopenharmony_ci        z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
408bf80f4bSopenharmony_ci        s_[1] = z ^ (z >> 31);
418bf80f4bSopenharmony_ci        z = (seed += 0x9e3779b97f4a7c15);
428bf80f4bSopenharmony_ci        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
438bf80f4bSopenharmony_ci        z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
448bf80f4bSopenharmony_ci        s_[2] = z ^ (z >> 31);
458bf80f4bSopenharmony_ci        z = (seed += 0x9e3779b97f4a7c15);
468bf80f4bSopenharmony_ci        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
478bf80f4bSopenharmony_ci        z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
488bf80f4bSopenharmony_ci        s_[3] = z ^ (z >> 31);
498bf80f4bSopenharmony_ci    }
508bf80f4bSopenharmony_ci
518bf80f4bSopenharmony_ci    uint64_t GetRandom() override
528bf80f4bSopenharmony_ci    {
538bf80f4bSopenharmony_ci        const uint64_t result = Rotl(s_[0] + s_[3], 23) + s_[0];
548bf80f4bSopenharmony_ci        const uint64_t t = s_[1] << 17;
558bf80f4bSopenharmony_ci        s_[2] ^= s_[0];
568bf80f4bSopenharmony_ci        s_[3] ^= s_[1];
578bf80f4bSopenharmony_ci        s_[1] ^= s_[2];
588bf80f4bSopenharmony_ci        s_[0] ^= s_[3];
598bf80f4bSopenharmony_ci        s_[2] ^= t;
608bf80f4bSopenharmony_ci        s_[3] = Rotl(s_[3], 45);
618bf80f4bSopenharmony_ci        return result;
628bf80f4bSopenharmony_ci    }
638bf80f4bSopenharmony_ci
648bf80f4bSopenharmony_ciprivate:
658bf80f4bSopenharmony_ci    inline uint64_t Rotl(const uint64_t x, int k)
668bf80f4bSopenharmony_ci    {
678bf80f4bSopenharmony_ci        return (x << k) | (x >> (64 - k));
688bf80f4bSopenharmony_ci    }
698bf80f4bSopenharmony_ci
708bf80f4bSopenharmony_ci    uint64_t s_[4];
718bf80f4bSopenharmony_ci};
728bf80f4bSopenharmony_ci} // namespace
738bf80f4bSopenharmony_ci
748bf80f4bSopenharmony_ciBASE_NS::unique_ptr<IRandom> CreateXoroshiro128(uint64_t seed)
758bf80f4bSopenharmony_ci{
768bf80f4bSopenharmony_ci    return BASE_NS::unique_ptr<IRandom>(new Xoroshiro128(seed));
778bf80f4bSopenharmony_ci}
788bf80f4bSopenharmony_ci
798bf80f4bSopenharmony_ciMETA_END_NAMESPACE()
80