diff --git a/README.md b/README.md index d68dd9a..38772b6 100644 --- a/README.md +++ b/README.md @@ -252,14 +252,14 @@ If you want to contribute or have bugfixes, drop me a note at +// +// 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 +# include +# include +# include +# 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 >* = 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 >* = 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 + [[nodiscard]] + constexpr std::array 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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 >*> +inline constexpr float FloatFromBits(const Uint32 i) noexcept { + return (i >> 8) * 0x1.0p - 24f; +} + +template >*> +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 +inline constexpr std::array SplitMix64::generateSeedSequence() noexcept { + std::array seeds = {}; + + for (auto& seed : seeds) { + seed = operator()(); + } + + return seeds; +} + +inline constexpr SplitMix64::result_type SplitMix64::min() noexcept { + return std::numeric_limits::lowest(); +} + +inline constexpr SplitMix64::result_type SplitMix64::max() noexcept { + return std::numeric_limits::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::lowest(); +} + +inline constexpr Xoshiro256Plus::result_type Xoshiro256Plus::max() noexcept { + return std::numeric_limits::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::lowest(); +} + +inline constexpr Xoshiro256PlusPlus::result_type Xoshiro256PlusPlus::max() noexcept { + return std::numeric_limits::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::lowest(); +} + +inline constexpr Xoshiro256StarStar::result_type Xoshiro256StarStar::max() noexcept { + return std::numeric_limits::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::lowest(); +} + +inline constexpr Xoroshiro128Plus::result_type Xoroshiro128Plus::max() noexcept { + return std::numeric_limits::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::lowest(); +} + +inline constexpr Xoroshiro128PlusPlus::result_type Xoroshiro128PlusPlus::max() noexcept { + return std::numeric_limits::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::lowest(); +} + +inline constexpr Xoroshiro128StarStar::result_type Xoroshiro128StarStar::max() noexcept { + return std::numeric_limits::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(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::lowest(); +} + +inline constexpr Xoshiro128Plus::result_type Xoshiro128Plus::max() noexcept { + return std::numeric_limits::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(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::lowest(); +} + +inline constexpr Xoshiro128PlusPlus::result_type Xoshiro128PlusPlus::max() noexcept { + return std::numeric_limits::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(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::lowest(); +} + +inline constexpr Xoshiro128StarStar::result_type Xoshiro128StarStar::max() noexcept { + return std::numeric_limits::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; +} +} diff --git a/cores/rp2040/lwip_wrap.cpp b/cores/rp2040/lwip_wrap.cpp index a1390b1..6de14a8 100644 --- a/cores/rp2040/lwip_wrap.cpp +++ b/cores/rp2040/lwip_wrap.cpp @@ -29,6 +29,7 @@ #include #include #include +#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; } diff --git a/include/lwipopts.h b/include/lwipopts.h index 0dc0ed6..d4981e1 100644 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -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) diff --git a/lib/libpico.a b/lib/libpico.a index df7730a..60a145f 100644 Binary files a/lib/libpico.a and b/lib/libpico.a differ diff --git a/lib/libpicow-ipv6-btc-ble.a b/lib/libpicow-ipv6-btc-ble.a index 093a601..892cd68 100644 Binary files a/lib/libpicow-ipv6-btc-ble.a and b/lib/libpicow-ipv6-btc-ble.a differ diff --git a/lib/libpicow-ipv6-nobtc-noble.a b/lib/libpicow-ipv6-nobtc-noble.a index 2591056..42a064f 100644 Binary files a/lib/libpicow-ipv6-nobtc-noble.a and b/lib/libpicow-ipv6-nobtc-noble.a differ diff --git a/lib/libpicow-noipv6-btc-ble.a b/lib/libpicow-noipv6-btc-ble.a index 5731d42..93b3f3d 100644 Binary files a/lib/libpicow-noipv6-btc-ble.a and b/lib/libpicow-noipv6-btc-ble.a differ diff --git a/lib/libpicow-noipv6-nobtc-noble.a b/lib/libpicow-noipv6-nobtc-noble.a index acf3d3b..3d6e667 100644 Binary files a/lib/libpicow-noipv6-nobtc-noble.a and b/lib/libpicow-noipv6-nobtc-noble.a differ diff --git a/lib/platform_wrap.txt b/lib/platform_wrap.txt index c805bb3..eef50cf 100644 --- a/lib/platform_wrap.txt +++ b/lib/platform_wrap.txt @@ -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 diff --git a/tools/libpico/lwipopts.h b/tools/libpico/lwipopts.h index 0dc0ed6..d4981e1 100644 --- a/tools/libpico/lwipopts.h +++ b/tools/libpico/lwipopts.h @@ -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)