Unverified Commit 2bf249ff authored by Earle F. Philhower, III's avatar Earle F. Philhower, III Committed by GitHub

Avoid freezeing the core from LWIP under FreeRTOS (#1884)

Avoid issues with interrupts and priority inversions and other deadlocks
and use a SW based random generator for LWIP when under FreeRTOS.

This means removing any overrides for sleep_until and the two
get_rand_xx calls from the SDK, making things much saner.

Related to #1883, #1872, and other random FreeRTOS lockups.
parent 81070a0b
......@@ -252,14 +252,14 @@ If you want to contribute or have bugfixes, drop me a note at <earlephilhower@ya
* [UF2CONV.PY](https://github.com/microsoft/uf2) is by Microsoft Corporation and licensed under the MIT license.
* Networking and filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
* DHCP server for AP host mode from the [Micropython Project](https://micropython.org), distributed under the MIT License.
* [FreeRTOS](https://freertos.org) is Copyright Amazon.com, Inc. or its affiliates, and distributed under the MIT license.
* [FreeRTOS](https://freertos.org) is copyright Amazon.com, Inc. or its affiliates, and distributed under the MIT license.
* [lwIP](https://savannah.nongnu.org/projects/lwip/) is (c) the Swedish Institute of Computer Science and licenced under the BSD license.
* [BearSSL](https://bearssl.org) library written by Thomas Pornin, is distributed under the [MIT License](https://bearssl.org/#legal-details).
* [UZLib](https://github.com/pfalcon/uzlib) is copyright (c) 2003 Joergen Ibsen and distributed under the zlib license.
* [LEAmDNS](https://github.com/LaborEtArs/ESP8266mDNS) is copyright multiple authors and distributed under the MIT license.
* [http-parser](https://github.com/nodejs/http-parser) is copyright Joyent, Inc. and other Node contributors.
* WebServer code modified from the [ESP32 WebServer](https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer) and is copyright (c) 2015 Ivan Grokhotkov and others
* WebServer code modified from the [ESP32 WebServer](https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer) and is copyright (c) 2015 Ivan Grokhotkov and others.
* [Xoshiro-cpp](https://github.com/Reputeless/Xoshiro-cpp) is copyright (c) 2020 Ryo Suzuki and distributed under the MIT license.
-Earle F. Philhower, III
earlephilhower@yahoo.com
......@@ -60,45 +60,3 @@ SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive) {
}
return nullptr; // Need to make space for more mutex maps!
}
// The HW Random code needs a precise sleep_until() in order to assure it
// grabs the ROSC bit when it wants. Unfortunately, under FreeRTOS the
// sleep_until() becomes imprecise and the "did I get the bit when I wanted"
// check in the pico_rand code always fails and you get an infinite loop.
// This block wraps the 2 get_rand calls to set a flag to convert
// sleep_until() (which can do a task swap and cause bad timing) into a
// busy wait.
extern "C" {
static bool __inRand = false;
extern uint64_t __real_get_rand_64();
uint64_t __wrap_get_rand_64() {
if (__isFreeRTOS) {
rp2040.idleOtherCore();
__inRand = true;
auto r = __real_get_rand_64();
__inRand = false;
rp2040.resumeOtherCore();
return r;
} else {
return __real_get_rand_64();
}
}
uint32_t __wrap_get_rand_32() {
return (uint32_t) __wrap_get_rand_64();
}
extern void __real_sleep_until(absolute_time_t t);
void __wrap_sleep_until(absolute_time_t t) {
if (__inRand) {
busy_wait_until(t);
} else {
__real_sleep_until(t);
}
}
}
//----------------------------------------------------------------------------------------
//
// Xoshiro-cpp
// Xoshiro PRNG wrapper library for C++17 / C++20
//
// Copyright (C) 2020 Ryo Suzuki <reputeless@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//----------------------------------------------------------------------------------------
# pragma once
# include <cstdint>
# include <array>
# include <limits>
# include <type_traits>
# if __has_cpp_attribute(nodiscard) >= 201907L
# define XOSHIROCPP_NODISCARD_CXX20 [[nodiscard]]
# else
# define XOSHIROCPP_NODISCARD_CXX20
# endif
namespace XoshiroCpp {
// A default seed value for the generators
inline constexpr std::uint64_t DefaultSeed = 1234567890ULL;
// Converts given uint32 value `i` into a 32-bit floating
// point value in the range of [0.0f, 1.0f)
template <class Uint32, std::enable_if_t<std::is_same_v<Uint32, std::uint32_t>>* = nullptr>
[[nodiscard]]
inline constexpr float FloatFromBits(Uint32 i) noexcept;
// Converts given uint64 value `i` into a 64-bit floating
// point value in the range of [0.0, 1.0)
template <class Uint64, std::enable_if_t<std::is_same_v<Uint64, std::uint64_t>>* = nullptr>
[[nodiscard]]
inline constexpr double DoubleFromBits(Uint64 i) noexcept;
// SplitMix64
// Output: 64 bits
// Period: 2^64
// Footprint: 8 bytes
// Original implementation: http://prng.di.unimi.it/splitmix64.c
class SplitMix64 {
public:
using state_type = std::uint64_t;
using result_type = std::uint64_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr SplitMix64(state_type state = DefaultSeed) noexcept;
constexpr result_type operator()() noexcept;
template <std::size_t N>
[[nodiscard]]
constexpr std::array<std::uint64_t, N> generateSeedSequence() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const SplitMix64& lhs, const SplitMix64& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const SplitMix64& lhs, const SplitMix64& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
// xoshiro256+
// Output: 64 bits
// Period: 2^256 - 1
// Footprint: 32 bytes
// Original implementation: http://prng.di.unimi.it/xoshiro256plus.c
// Version: 1.0
class Xoshiro256Plus {
public:
using state_type = std::array<std::uint64_t, 4>;
using result_type = std::uint64_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro256Plus(std::uint64_t seed = DefaultSeed) noexcept;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro256Plus(state_type state) noexcept;
constexpr result_type operator()() noexcept;
// This is the jump function for the generator. It is equivalent
// to 2^128 calls to operator(); it can be used to generate 2^128
// non-overlapping subsequences for parallel computations.
constexpr void jump() noexcept;
// This is the long-jump function for the generator. It is equivalent to
// 2^192 calls to next(); it can be used to generate 2^64 starting points,
// from each of which jump() will generate 2^64 non-overlapping
// subsequences for parallel distributed computations.
constexpr void longJump() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const Xoshiro256Plus& lhs, const Xoshiro256Plus& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const Xoshiro256Plus& lhs, const Xoshiro256Plus& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
// xoshiro256++
// Output: 64 bits
// Period: 2^256 - 1
// Footprint: 32 bytes
// Original implementation: http://prng.di.unimi.it/xoshiro256plusplus.c
// Version: 1.0
class Xoshiro256PlusPlus {
public:
using state_type = std::array<std::uint64_t, 4>;
using result_type = std::uint64_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro256PlusPlus(std::uint64_t seed = DefaultSeed) noexcept;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro256PlusPlus(state_type state) noexcept;
constexpr result_type operator()() noexcept;
// This is the jump function for the generator. It is equivalent
// to 2^128 calls to next(); it can be used to generate 2^128
// non-overlapping subsequences for parallel computations.
constexpr void jump() noexcept;
// This is the long-jump function for the generator. It is equivalent to
// 2^192 calls to next(); it can be used to generate 2^64 starting points,
// from each of which jump() will generate 2^64 non-overlapping
// subsequences for parallel distributed computations.
constexpr void longJump() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const Xoshiro256PlusPlus& lhs, const Xoshiro256PlusPlus& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const Xoshiro256PlusPlus& lhs, const Xoshiro256PlusPlus& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
// xoshiro256**
// Output: 64 bits
// Period: 2^256 - 1
// Footprint: 32 bytes
// Original implementation: http://prng.di.unimi.it/xoshiro256starstar.c
// Version: 1.0
class Xoshiro256StarStar {
public:
using state_type = std::array<std::uint64_t, 4>;
using result_type = std::uint64_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro256StarStar(std::uint64_t seed = DefaultSeed) noexcept;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro256StarStar(state_type state) noexcept;
constexpr result_type operator()() noexcept;
// This is the jump function for the generator. It is equivalent
// to 2^128 calls to next(); it can be used to generate 2^128
// non-overlapping subsequences for parallel computations.
constexpr void jump() noexcept;
// This is the long-jump function for the generator. It is equivalent to
// 2^192 calls to next(); it can be used to generate 2^64 starting points,
// from each of which jump() will generate 2^64 non-overlapping
// subsequences for parallel distributed computations.
constexpr void longJump() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const Xoshiro256StarStar& lhs, const Xoshiro256StarStar& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const Xoshiro256StarStar& lhs, const Xoshiro256StarStar& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
// xoroshiro128+
// Output: 64 bits
// Period: 2^128 - 1
// Footprint: 16 bytes
// Original implementation: http://prng.di.unimi.it/xoroshiro128plus.c
// Version: 1.0
class Xoroshiro128Plus {
public:
using state_type = std::array<std::uint64_t, 2>;
using result_type = std::uint64_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoroshiro128Plus(std::uint64_t seed = DefaultSeed) noexcept;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoroshiro128Plus(state_type state) noexcept;
constexpr result_type operator()() noexcept;
// This is the jump function for the generator. It is equivalent
// to 2^64 calls to next(); it can be used to generate 2^64
// non-overlapping subsequences for parallel computations.
constexpr void jump() noexcept;
// This is the long-jump function for the generator. It is equivalent to
// 2^96 calls to next(); it can be used to generate 2^32 starting points,
// from each of which jump() will generate 2^32 non-overlapping
// subsequences for parallel distributed computations.
constexpr void longJump() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const Xoroshiro128Plus& lhs, const Xoroshiro128Plus& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const Xoroshiro128Plus& lhs, const Xoroshiro128Plus& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
// xoroshiro128++
// Output: 64 bits
// Period: 2^128 - 1
// Footprint: 16 bytes
// Original implementation: http://prng.di.unimi.it/xoroshiro128plusplus.c
// Version: 1.0
class Xoroshiro128PlusPlus {
public:
using state_type = std::array<std::uint64_t, 2>;
using result_type = std::uint64_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoroshiro128PlusPlus(std::uint64_t seed = DefaultSeed) noexcept;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoroshiro128PlusPlus(state_type state) noexcept;
constexpr result_type operator()() noexcept;
// This is the jump function for the generator. It is equivalent
// to 2^64 calls to next(); it can be used to generate 2^64
// non-overlapping subsequences for parallel computations.
constexpr void jump() noexcept;
// This is the long-jump function for the generator. It is equivalent to
// 2^96 calls to next(); it can be used to generate 2^32 starting points,
// from each of which jump() will generate 2^32 non-overlapping
// subsequences for parallel distributed computations.
constexpr void longJump() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const Xoroshiro128PlusPlus& lhs, const Xoroshiro128PlusPlus& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const Xoroshiro128PlusPlus& lhs, const Xoroshiro128PlusPlus& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
// xoroshiro128**
// Output: 64 bits
// Period: 2^128 - 1
// Footprint: 16 bytes
// Original implementation: http://prng.di.unimi.it/xoroshiro128starstar.c
// Version: 1.0
class Xoroshiro128StarStar {
public:
using state_type = std::array<std::uint64_t, 2>;
using result_type = std::uint64_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoroshiro128StarStar(std::uint64_t seed = DefaultSeed) noexcept;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoroshiro128StarStar(state_type state) noexcept;
constexpr result_type operator()() noexcept;
// This is the jump function for the generator. It is equivalent
// to 2^64 calls to next(); it can be used to generate 2^64
// non-overlapping subsequences for parallel computations.
constexpr void jump() noexcept;
// This is the long-jump function for the generator. It is equivalent to
// 2^96 calls to next(); it can be used to generate 2^32 starting points,
// from each of which jump() will generate 2^32 non-overlapping
// subsequences for parallel distributed computations.
constexpr void longJump() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const Xoroshiro128StarStar& lhs, const Xoroshiro128StarStar& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const Xoroshiro128StarStar& lhs, const Xoroshiro128StarStar& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
// xoshiro128+
// Output: 32 bits
// Period: 2^128 - 1
// Footprint: 16 bytes
// Original implementation: http://prng.di.unimi.it/xoshiro128plus.c
// Version: 1.0
class Xoshiro128Plus {
public:
using state_type = std::array<std::uint32_t, 4>;
using result_type = std::uint32_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro128Plus(std::uint64_t seed = DefaultSeed) noexcept;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro128Plus(state_type state) noexcept;
constexpr result_type operator()() noexcept;
// This is the jump function for the generator. It is equivalent
// to 2^64 calls to next(); it can be used to generate 2^64
// non-overlapping subsequences for parallel computations.
constexpr void jump() noexcept;
// This is the long-jump function for the generator. It is equivalent to
// 2^96 calls to next(); it can be used to generate 2^32 starting points,
// from each of which jump() will generate 2^32 non-overlapping
// subsequences for parallel distributed computations.
constexpr void longJump() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const Xoshiro128Plus& lhs, const Xoshiro128Plus& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const Xoshiro128Plus& lhs, const Xoshiro128Plus& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
// xoshiro128++
// Output: 32 bits
// Period: 2^128 - 1
// Footprint: 16 bytes
// Original implementation: http://prng.di.unimi.it/xoshiro128plusplus.c
// Version: 1.0
class Xoshiro128PlusPlus {
public:
using state_type = std::array<std::uint32_t, 4>;
using result_type = std::uint32_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro128PlusPlus(std::uint64_t seed = DefaultSeed) noexcept;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro128PlusPlus(state_type state) noexcept;
constexpr result_type operator()() noexcept;
// This is the jump function for the generator. It is equivalent
// to 2^64 calls to next(); it can be used to generate 2^64
// non-overlapping subsequences for parallel computations.
constexpr void jump() noexcept;
// This is the long-jump function for the generator. It is equivalent to
// 2^96 calls to next(); it can be used to generate 2^32 starting points,
// from each of which jump() will generate 2^32 non-overlapping
// subsequences for parallel distributed computations.
constexpr void longJump() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const Xoshiro128PlusPlus& lhs, const Xoshiro128PlusPlus& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const Xoshiro128PlusPlus& lhs, const Xoshiro128PlusPlus& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
// xoshiro128**
// Output: 32 bits
// Period: 2^128 - 1
// Footprint: 16 bytes
// Original implementation: http://prng.di.unimi.it/xoshiro128starstar.c
// Version: 1.1
class Xoshiro128StarStar {
public:
using state_type = std::array<std::uint32_t, 4>;
using result_type = std::uint32_t;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro128StarStar(std::uint64_t seed = DefaultSeed) noexcept;
XOSHIROCPP_NODISCARD_CXX20
explicit constexpr Xoshiro128StarStar(state_type state) noexcept;
constexpr result_type operator()() noexcept;
// This is the jump function for the generator. It is equivalent
// to 2^64 calls to next(); it can be used to generate 2^64
// non-overlapping subsequences for parallel computations.
constexpr void jump() noexcept;
// This is the long-jump function for the generator. It is equivalent to
// 2^96 calls to next(); it can be used to generate 2^32 starting points,
// from each of which jump() will generate 2^32 non-overlapping
// subsequences for parallel distributed computations.
constexpr void longJump() noexcept;
[[nodiscard]]
static constexpr result_type min() noexcept;
[[nodiscard]]
static constexpr result_type max() noexcept;
[[nodiscard]]
constexpr state_type serialize() const noexcept;
constexpr void deserialize(state_type state) noexcept;
[[nodiscard]]
friend bool operator ==(const Xoshiro128StarStar& lhs, const Xoshiro128StarStar& rhs) noexcept {
return (lhs.m_state == rhs.m_state);
}
[[nodiscard]]
friend bool operator !=(const Xoshiro128StarStar& lhs, const Xoshiro128StarStar& rhs) noexcept {
return (lhs.m_state != rhs.m_state);
}
private:
state_type m_state;
};
}
////////////////////////////////////////////////////////////////
namespace XoshiroCpp {
#if 0
template <class Uint32, std::enable_if_t<std::is_same_v<Uint32, std::uint32_t>>*>
inline constexpr float FloatFromBits(const Uint32 i) noexcept {
return (i >> 8) * 0x1.0p - 24f;
}
template <class Uint64, std::enable_if_t<std::is_same_v<Uint64, std::uint64_t>>*>
inline constexpr double DoubleFromBits(const Uint64 i) noexcept {
return (i >> 11) * 0x1.0p - 53;
}
#endif
namespace detail {
[[nodiscard]]
static constexpr std::uint64_t RotL(const std::uint64_t x, const int s) noexcept {
return (x << s) | (x >> (64 - s));
}
[[nodiscard]]
static constexpr std::uint32_t RotL(const std::uint32_t x, const int s) noexcept {
return (x << s) | (x >> (32 - s));
}
}
////////////////////////////////////////////////////////////////
//
// SplitMix64
//
inline constexpr SplitMix64::SplitMix64(const state_type state) noexcept
: m_state(state) {}
inline constexpr SplitMix64::result_type SplitMix64::operator()() noexcept {
std::uint64_t z = (m_state += 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
template <std::size_t N>
inline constexpr std::array<std::uint64_t, N> SplitMix64::generateSeedSequence() noexcept {
std::array<std::uint64_t, N> seeds = {};
for (auto& seed : seeds) {
seed = operator()();
}
return seeds;
}
inline constexpr SplitMix64::result_type SplitMix64::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr SplitMix64::result_type SplitMix64::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr SplitMix64::state_type SplitMix64::serialize() const noexcept {
return m_state;
}
inline constexpr void SplitMix64::deserialize(const state_type state) noexcept {
m_state = state;
}
////////////////////////////////////////////////////////////////
//
// xoshiro256+
//
inline constexpr Xoshiro256Plus::Xoshiro256Plus(const std::uint64_t seed) noexcept
: m_state(SplitMix64 {
seed
} .generateSeedSequence<4>()) {}
inline constexpr Xoshiro256Plus::Xoshiro256Plus(const state_type state) noexcept
: m_state(state) {}
inline constexpr Xoshiro256Plus::result_type Xoshiro256Plus::operator()() noexcept {
const std::uint64_t result = m_state[0] + m_state[3];
const std::uint64_t t = m_state[1] << 17;
m_state[2] ^= m_state[0];
m_state[3] ^= m_state[1];
m_state[1] ^= m_state[2];
m_state[0] ^= m_state[3];
m_state[2] ^= t;
m_state[3] = detail::RotL(m_state[3], 45);
return result;
}
inline constexpr void Xoshiro256Plus::jump() noexcept {
constexpr std::uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
std::uint64_t s2 = 0;
std::uint64_t s3 = 0;
for (std::uint64_t jump : JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr void Xoshiro256Plus::longJump() noexcept {
constexpr std::uint64_t LONG_JUMP[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
std::uint64_t s2 = 0;
std::uint64_t s3 = 0;
for (std::uint64_t jump : LONG_JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr Xoshiro256Plus::result_type Xoshiro256Plus::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr Xoshiro256Plus::result_type Xoshiro256Plus::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr Xoshiro256Plus::state_type Xoshiro256Plus::serialize() const noexcept {
return m_state;
}
inline constexpr void Xoshiro256Plus::deserialize(const state_type state) noexcept {
m_state = state;
}
////////////////////////////////////////////////////////////////
//
// xoshiro256++
//
inline constexpr Xoshiro256PlusPlus::Xoshiro256PlusPlus(const std::uint64_t seed) noexcept
: m_state(SplitMix64 {
seed
} .generateSeedSequence<4>()) {}
inline constexpr Xoshiro256PlusPlus::Xoshiro256PlusPlus(const state_type state) noexcept
: m_state(state) {}
inline constexpr Xoshiro256PlusPlus::result_type Xoshiro256PlusPlus::operator()() noexcept {
const std::uint64_t result = detail::RotL(m_state[0] + m_state[3], 23) + m_state[0];
const std::uint64_t t = m_state[1] << 17;
m_state[2] ^= m_state[0];
m_state[3] ^= m_state[1];
m_state[1] ^= m_state[2];
m_state[0] ^= m_state[3];
m_state[2] ^= t;
m_state[3] = detail::RotL(m_state[3], 45);
return result;
}
inline constexpr void Xoshiro256PlusPlus::jump() noexcept {
constexpr std::uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
std::uint64_t s2 = 0;
std::uint64_t s3 = 0;
for (std::uint64_t jump : JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr void Xoshiro256PlusPlus::longJump() noexcept {
constexpr std::uint64_t LONG_JUMP[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
std::uint64_t s2 = 0;
std::uint64_t s3 = 0;
for (std::uint64_t jump : LONG_JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr Xoshiro256PlusPlus::result_type Xoshiro256PlusPlus::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr Xoshiro256PlusPlus::result_type Xoshiro256PlusPlus::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr Xoshiro256PlusPlus::state_type Xoshiro256PlusPlus::serialize() const noexcept {
return m_state;
}
inline constexpr void Xoshiro256PlusPlus::deserialize(const state_type state) noexcept {
m_state = state;
}
////////////////////////////////////////////////////////////////
//
// xoshiro256**
//
inline constexpr Xoshiro256StarStar::Xoshiro256StarStar(const std::uint64_t seed) noexcept
: m_state(SplitMix64 {
seed
} .generateSeedSequence<4>()) {}
inline constexpr Xoshiro256StarStar::Xoshiro256StarStar(const state_type state) noexcept
: m_state(state) {}
inline constexpr Xoshiro256StarStar::result_type Xoshiro256StarStar::operator()() noexcept {
const std::uint64_t result = detail::RotL(m_state[1] * 5, 7) * 9;
const std::uint64_t t = m_state[1] << 17;
m_state[2] ^= m_state[0];
m_state[3] ^= m_state[1];
m_state[1] ^= m_state[2];
m_state[0] ^= m_state[3];
m_state[2] ^= t;
m_state[3] = detail::RotL(m_state[3], 45);
return result;
}
inline constexpr void Xoshiro256StarStar::jump() noexcept {
constexpr std::uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
std::uint64_t s2 = 0;
std::uint64_t s3 = 0;
for (std::uint64_t jump : JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr void Xoshiro256StarStar::longJump() noexcept {
constexpr std::uint64_t LONG_JUMP[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
std::uint64_t s2 = 0;
std::uint64_t s3 = 0;
for (std::uint64_t jump : LONG_JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr Xoshiro256StarStar::result_type Xoshiro256StarStar::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr Xoshiro256StarStar::result_type Xoshiro256StarStar::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr Xoshiro256StarStar::state_type Xoshiro256StarStar::serialize() const noexcept {
return m_state;
}
inline constexpr void Xoshiro256StarStar::deserialize(const state_type state) noexcept {
m_state = state;
}
////////////////////////////////////////////////////////////////
//
// xoroshiro128+
//
inline constexpr Xoroshiro128Plus::Xoroshiro128Plus(const std::uint64_t seed) noexcept
: m_state(SplitMix64 {
seed
} .generateSeedSequence<2>()) {}
inline constexpr Xoroshiro128Plus::Xoroshiro128Plus(const state_type state) noexcept
: m_state(state) {}
inline constexpr Xoroshiro128Plus::result_type Xoroshiro128Plus::operator()() noexcept {
const std::uint64_t s0 = m_state[0];
std::uint64_t s1 = m_state[1];
const std::uint64_t result = s0 + s1;
s1 ^= s0;
m_state[0] = detail::RotL(s0, 24) ^ s1 ^ (s1 << 16);
m_state[1] = detail::RotL(s1, 37);
return result;
}
inline constexpr void Xoroshiro128Plus::jump() noexcept {
constexpr std::uint64_t JUMP[] = { 0xdf900294d8f554a5, 0x170865df4b3201fc };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
for (std::uint64_t jump : JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
}
inline constexpr void Xoroshiro128Plus::longJump() noexcept {
constexpr std::uint64_t LONG_JUMP[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
for (std::uint64_t jump : LONG_JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
}
inline constexpr Xoroshiro128Plus::result_type Xoroshiro128Plus::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr Xoroshiro128Plus::result_type Xoroshiro128Plus::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr Xoroshiro128Plus::state_type Xoroshiro128Plus::serialize() const noexcept {
return m_state;
}
inline constexpr void Xoroshiro128Plus::deserialize(const state_type state) noexcept {
m_state = state;
}
////////////////////////////////////////////////////////////////
//
// xoroshiro128++
//
inline constexpr Xoroshiro128PlusPlus::Xoroshiro128PlusPlus(const std::uint64_t seed) noexcept
: m_state(SplitMix64 {
seed
} .generateSeedSequence<2>()) {}
inline constexpr Xoroshiro128PlusPlus::Xoroshiro128PlusPlus(const state_type state) noexcept
: m_state(state) {}
inline constexpr Xoroshiro128PlusPlus::result_type Xoroshiro128PlusPlus::operator()() noexcept {
const std::uint64_t s0 = m_state[0];
std::uint64_t s1 = m_state[1];
const std::uint64_t result = detail::RotL(s0 + s1, 17) + s0;
s1 ^= s0;
m_state[0] = detail::RotL(s0, 49) ^ s1 ^ (s1 << 21);
m_state[1] = detail::RotL(s1, 28);
return result;
}
inline constexpr void Xoroshiro128PlusPlus::jump() noexcept {
constexpr std::uint64_t JUMP[] = { 0x2bd7a6a6e99c2ddc, 0x0992ccaf6a6fca05 };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
for (std::uint64_t jump : JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
}
inline constexpr void Xoroshiro128PlusPlus::longJump() noexcept {
constexpr std::uint64_t LONG_JUMP[] = { 0x360fd5f2cf8d5d99, 0x9c6e6877736c46e3 };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
for (std::uint64_t jump : LONG_JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
}
inline constexpr Xoroshiro128PlusPlus::result_type Xoroshiro128PlusPlus::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr Xoroshiro128PlusPlus::result_type Xoroshiro128PlusPlus::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr Xoroshiro128PlusPlus::state_type Xoroshiro128PlusPlus::serialize() const noexcept {
return m_state;
}
inline constexpr void Xoroshiro128PlusPlus::deserialize(const state_type state) noexcept {
m_state = state;
}
////////////////////////////////////////////////////////////////
//
// xoroshiro128**
//
inline constexpr Xoroshiro128StarStar::Xoroshiro128StarStar(const std::uint64_t seed) noexcept
: m_state(SplitMix64 {
seed
} .generateSeedSequence<2>()) {}
inline constexpr Xoroshiro128StarStar::Xoroshiro128StarStar(const state_type state) noexcept
: m_state(state) {}
inline constexpr Xoroshiro128StarStar::result_type Xoroshiro128StarStar::operator()() noexcept {
const std::uint64_t s0 = m_state[0];
std::uint64_t s1 = m_state[1];
const std::uint64_t result = detail::RotL(s0 * 5, 7) * 9;
s1 ^= s0;
m_state[0] = detail::RotL(s0, 24) ^ s1 ^ (s1 << 16);
m_state[1] = detail::RotL(s1, 37);
return result;
}
inline constexpr void Xoroshiro128StarStar::jump() noexcept {
constexpr std::uint64_t JUMP[] = { 0xdf900294d8f554a5, 0x170865df4b3201fc };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
for (std::uint64_t jump : JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
}
inline constexpr void Xoroshiro128StarStar::longJump() noexcept {
constexpr std::uint64_t LONG_JUMP[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 };
std::uint64_t s0 = 0;
std::uint64_t s1 = 0;
for (std::uint64_t jump : LONG_JUMP) {
for (int b = 0; b < 64; ++b) {
if (jump & UINT64_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
}
inline constexpr Xoroshiro128StarStar::result_type Xoroshiro128StarStar::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr Xoroshiro128StarStar::result_type Xoroshiro128StarStar::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr Xoroshiro128StarStar::state_type Xoroshiro128StarStar::serialize() const noexcept {
return m_state;
}
inline constexpr void Xoroshiro128StarStar::deserialize(const state_type state) noexcept {
m_state = state;
}
////////////////////////////////////////////////////////////////
//
// xoshiro128+
//
inline constexpr Xoshiro128Plus::Xoshiro128Plus(const std::uint64_t seed) noexcept
: m_state() {
SplitMix64 splitmix{ seed };
for (auto& state : m_state) {
state = static_cast<std::uint32_t>(splitmix());
}
}
inline constexpr Xoshiro128Plus::Xoshiro128Plus(const state_type state) noexcept
: m_state(state) {}
inline constexpr Xoshiro128Plus::result_type Xoshiro128Plus::operator()() noexcept {
const std::uint32_t result = m_state[0] + m_state[3];
const std::uint32_t t = m_state[1] << 9;
m_state[2] ^= m_state[0];
m_state[3] ^= m_state[1];
m_state[1] ^= m_state[2];
m_state[0] ^= m_state[3];
m_state[2] ^= t;
m_state[3] = detail::RotL(m_state[3], 11);
return result;
}
inline constexpr void Xoshiro128Plus::jump() noexcept {
constexpr std::uint32_t JUMP[] = { 0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b };
std::uint32_t s0 = 0;
std::uint32_t s1 = 0;
std::uint32_t s2 = 0;
std::uint32_t s3 = 0;
for (std::uint32_t jump : JUMP) {
for (int b = 0; b < 32; ++b) {
if (jump & UINT32_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr void Xoshiro128Plus::longJump() noexcept {
constexpr std::uint32_t LONG_JUMP[] = { 0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662 };
std::uint32_t s0 = 0;
std::uint32_t s1 = 0;
std::uint32_t s2 = 0;
std::uint32_t s3 = 0;
for (std::uint32_t jump : LONG_JUMP) {
for (int b = 0; b < 32; ++b) {
if (jump & UINT32_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr Xoshiro128Plus::result_type Xoshiro128Plus::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr Xoshiro128Plus::result_type Xoshiro128Plus::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr Xoshiro128Plus::state_type Xoshiro128Plus::serialize() const noexcept {
return m_state;
}
inline constexpr void Xoshiro128Plus::deserialize(const state_type state) noexcept {
m_state = state;
}
////////////////////////////////////////////////////////////////
//
// xoshiro128++
//
inline constexpr Xoshiro128PlusPlus::Xoshiro128PlusPlus(const std::uint64_t seed) noexcept
: m_state() {
SplitMix64 splitmix{ seed };
for (auto& state : m_state) {
state = static_cast<std::uint32_t>(splitmix());
}
}
inline constexpr Xoshiro128PlusPlus::Xoshiro128PlusPlus(const state_type state) noexcept
: m_state(state) {}
inline constexpr Xoshiro128PlusPlus::result_type Xoshiro128PlusPlus::operator()() noexcept {
const std::uint32_t result = detail::RotL(m_state[0] + m_state[3], 7) + m_state[0];
const std::uint32_t t = m_state[1] << 9;
m_state[2] ^= m_state[0];
m_state[3] ^= m_state[1];
m_state[1] ^= m_state[2];
m_state[0] ^= m_state[3];
m_state[2] ^= t;
m_state[3] = detail::RotL(m_state[3], 11);
return result;
}
inline constexpr void Xoshiro128PlusPlus::jump() noexcept {
constexpr std::uint32_t JUMP[] = { 0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b };
std::uint32_t s0 = 0;
std::uint32_t s1 = 0;
std::uint32_t s2 = 0;
std::uint32_t s3 = 0;
for (std::uint32_t jump : JUMP) {
for (int b = 0; b < 32; ++b) {
if (jump & UINT32_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr void Xoshiro128PlusPlus::longJump() noexcept {
constexpr std::uint32_t LONG_JUMP[] = { 0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662 };
std::uint32_t s0 = 0;
std::uint32_t s1 = 0;
std::uint32_t s2 = 0;
std::uint32_t s3 = 0;
for (std::uint32_t jump : LONG_JUMP) {
for (int b = 0; b < 32; ++b) {
if (jump & UINT32_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr Xoshiro128PlusPlus::result_type Xoshiro128PlusPlus::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr Xoshiro128PlusPlus::result_type Xoshiro128PlusPlus::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr Xoshiro128PlusPlus::state_type Xoshiro128PlusPlus::serialize() const noexcept {
return m_state;
}
inline constexpr void Xoshiro128PlusPlus::deserialize(const state_type state) noexcept {
m_state = state;
}
////////////////////////////////////////////////////////////////
//
// xoshiro128**
//
inline constexpr Xoshiro128StarStar::Xoshiro128StarStar(const std::uint64_t seed) noexcept
: m_state() {
SplitMix64 splitmix{ seed };
for (auto& state : m_state) {
state = static_cast<std::uint32_t>(splitmix());
}
}
inline constexpr Xoshiro128StarStar::Xoshiro128StarStar(const state_type state) noexcept
: m_state(state) {}
inline constexpr Xoshiro128StarStar::result_type Xoshiro128StarStar::operator()() noexcept {
const std::uint32_t result = detail::RotL(m_state[1] * 5, 7) * 9;
const std::uint32_t t = m_state[1] << 9;
m_state[2] ^= m_state[0];
m_state[3] ^= m_state[1];
m_state[1] ^= m_state[2];
m_state[0] ^= m_state[3];
m_state[2] ^= t;
m_state[3] = detail::RotL(m_state[3], 11);
return result;
}
inline constexpr void Xoshiro128StarStar::jump() noexcept {
constexpr std::uint32_t JUMP[] = { 0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b };
std::uint32_t s0 = 0;
std::uint32_t s1 = 0;
std::uint32_t s2 = 0;
std::uint32_t s3 = 0;
for (std::uint32_t jump : JUMP) {
for (int b = 0; b < 32; ++b) {
if (jump & UINT32_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr void Xoshiro128StarStar::longJump() noexcept {
constexpr std::uint32_t LONG_JUMP[] = { 0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662 };
std::uint32_t s0 = 0;
std::uint32_t s1 = 0;
std::uint32_t s2 = 0;
std::uint32_t s3 = 0;
for (std::uint32_t jump : LONG_JUMP) {
for (int b = 0; b < 32; ++b) {
if (jump & UINT32_C(1) << b) {
s0 ^= m_state[0];
s1 ^= m_state[1];
s2 ^= m_state[2];
s3 ^= m_state[3];
}
operator()();
}
}
m_state[0] = s0;
m_state[1] = s1;
m_state[2] = s2;
m_state[3] = s3;
}
inline constexpr Xoshiro128StarStar::result_type Xoshiro128StarStar::min() noexcept {
return std::numeric_limits<result_type>::lowest();
}
inline constexpr Xoshiro128StarStar::result_type Xoshiro128StarStar::max() noexcept {
return std::numeric_limits<result_type>::max();
}
inline constexpr Xoshiro128StarStar::state_type Xoshiro128StarStar::serialize() const noexcept {
return m_state;
}
inline constexpr void Xoshiro128StarStar::deserialize(const state_type state) noexcept {
m_state = state;
}
}
......@@ -29,6 +29,7 @@
#include <pico/cyw43_arch.h>
#include <pico/mutex.h>
#include <sys/lock.h>
#include "_xoshiro.h"
extern void ethernet_arch_lwip_begin() __attribute__((weak));
extern void ethernet_arch_lwip_end() __attribute__((weak));
......@@ -68,11 +69,25 @@ public:
extern "C" {
static XoshiroCpp::Xoshiro256PlusPlus *_lwip_rng = nullptr;
// Random number generator for LWIP. Bare metal, use the HW. FreeRTOS, use xoshiro generator to avoid needing to freeze the other core
unsigned long __lwip_rand() {
if (__isFreeRTOS) {
return (unsigned long)(*_lwip_rng)();
} else {
return get_rand_32();
}
}
// Avoid calling lwip_init multiple times
extern void __real_lwip_init();
void __wrap_lwip_init() {
static bool initted = false;
if (!initted) {
if (__isFreeRTOS) {
_lwip_rng = new XoshiroCpp::Xoshiro256PlusPlus(rp2040.getCycleCount());
}
__real_lwip_init();
initted = true;
}
......
......@@ -13,8 +13,8 @@ extern void interrupts();
#define SYS_ARCH_PROTECT(lev) noInterrupts
#define SYS_ARCH_UNPROTECT(lev) interrupts
extern unsigned long get_rand_32(void);
#define LWIP_RAND() get_rand_32()
extern unsigned long __lwip_rand(void);
#define LWIP_RAND() __lwip_rand()
// Common settings used in most of the pico_w examples
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
......
No preview for this file type
......@@ -209,7 +209,3 @@
-Wl,--wrap=cyw43_tcpip_link_status
-Wl,--wrap=cyw43_cb_tcpip_init
-Wl,--wrap=cyw43_cb_tcpip_deinit
-Wl,--wrap=get_rand_64
-Wl,--wrap=get_rand_32
-Wl,--wrap=sleep_until
......@@ -13,8 +13,8 @@ extern void interrupts();
#define SYS_ARCH_PROTECT(lev) noInterrupts
#define SYS_ARCH_UNPROTECT(lev) interrupts
extern unsigned long get_rand_32(void);
#define LWIP_RAND() get_rand_32()
extern unsigned long __lwip_rand(void);
#define LWIP_RAND() __lwip_rand()
// Common settings used in most of the pico_w examples
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment