From 5a581b025ed32ddfe031139cb077a4fb8f360f0e Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Thu, 8 Oct 2026 12:58:14 +0200 Subject: [PATCH 1/8] fix(exec): avoid degenerate xorshift zero seed --- include/exec/detail/xorshift.hpp | 2 +- test/exec/CMakeLists.txt | 1 + test/exec/test_xorshift.cpp | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/exec/test_xorshift.cpp diff --git a/include/exec/detail/xorshift.hpp b/include/exec/detail/xorshift.hpp index 9371e7920..da9e6ca96 100644 --- a/include/exec/detail/xorshift.hpp +++ b/include/exec/detail/xorshift.hpp @@ -63,7 +63,7 @@ namespace experimental::execution } explicit xorshift(std::uint64_t seed) - : m_seed(seed) + : m_seed(seed == 0 ? 0xc1f651c67c62c6e0ull : seed) {} void seed(std::random_device &rd) diff --git a/test/exec/CMakeLists.txt b/test/exec/CMakeLists.txt index 8b24f960b..1d967bd96 100644 --- a/test/exec/CMakeLists.txt +++ b/test/exec/CMakeLists.txt @@ -45,6 +45,7 @@ set(exec_test_sources test_scheduler_concept.cpp test_sequence_senders.cpp test_static_thread_pool.cpp + test_xorshift.cpp test_just_from.cpp test_fork_join.cpp test_cpo_split.cpp diff --git a/test/exec/test_xorshift.cpp b/test/exec/test_xorshift.cpp new file mode 100644 index 000000000..bc665fd3e --- /dev/null +++ b/test/exec/test_xorshift.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 stdexec contributors + * + * Licensed under the Apache License Version 2.0 with LLVM Exceptions + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://llvm.org/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include + +TEST_CASE("xorshift does not get stuck with a zero seed", "[xorshift]") +{ + exec::xorshift zero_seed{std::uint64_t{0}}; + exec::xorshift default_seed{}; + + for (int i = 0; i < 8; ++i) + { + CHECK(zero_seed() == default_seed()); + } +} From bcd9f246164f0a442b041cfdac2411f3619d66cb Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Thu, 8 Oct 2026 13:50:03 +0200 Subject: [PATCH 2/8] Fix zero-state reseeding through random_device --- include/exec/detail/xorshift.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/include/exec/detail/xorshift.hpp b/include/exec/detail/xorshift.hpp index da9e6ca96..f581355de 100644 --- a/include/exec/detail/xorshift.hpp +++ b/include/exec/detail/xorshift.hpp @@ -54,7 +54,7 @@ namespace experimental::execution friend auto operator==(xorshift const &, xorshift const &) -> bool = default; xorshift() - : m_seed(0xc1f651c67c62c6e0ull) + : m_seed(default_seed) {} explicit xorshift(std::random_device &rd) @@ -63,12 +63,16 @@ namespace experimental::execution } explicit xorshift(std::uint64_t seed) - : m_seed(seed == 0 ? 0xc1f651c67c62c6e0ull : seed) + : m_seed(seed == 0 ? default_seed : seed) {} void seed(std::random_device &rd) { m_seed = std::uint64_t(rd()) << 31 | std::uint64_t(rd()); + if (m_seed == 0) + { + m_seed = default_seed; + } } auto operator()() -> result_type @@ -87,7 +91,8 @@ namespace experimental::execution } private: - std::uint64_t m_seed; + static constexpr std::uint64_t default_seed = 0xc1f651c67c62c6e0ull; + std::uint64_t m_seed; }; } // namespace experimental::execution From c67ac643e0791cff24eae3a88b026d6ccce33a71 Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Thu, 8 Oct 2026 14:12:58 +0200 Subject: [PATCH 3/8] Assert zero-seeded xorshift produces nonzero output --- test/exec/test_xorshift.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/exec/test_xorshift.cpp b/test/exec/test_xorshift.cpp index bc665fd3e..ce2d3baec 100644 --- a/test/exec/test_xorshift.cpp +++ b/test/exec/test_xorshift.cpp @@ -25,8 +25,12 @@ TEST_CASE("xorshift does not get stuck with a zero seed", "[xorshift]") exec::xorshift zero_seed{std::uint64_t{0}}; exec::xorshift default_seed{}; + bool produced_nonzero = false; for (int i = 0; i < 8; ++i) { - CHECK(zero_seed() == default_seed()); + auto const sample = zero_seed(); + CHECK(sample == default_seed()); + produced_nonzero = produced_nonzero || sample != 0; } + CHECK(produced_nonzero); } From eac30a2cd29d78a69de8ed252afe557b3b6381d7 Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Thu, 8 Oct 2026 14:25:33 +0200 Subject: [PATCH 4/8] Cover nonzero seed behavior and remove unused test include --- test/exec/test_xorshift.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/exec/test_xorshift.cpp b/test/exec/test_xorshift.cpp index ce2d3baec..9114d5fdf 100644 --- a/test/exec/test_xorshift.cpp +++ b/test/exec/test_xorshift.cpp @@ -15,7 +15,6 @@ */ #include -#include #include #include @@ -34,3 +33,9 @@ TEST_CASE("xorshift does not get stuck with a zero seed", "[xorshift]") } CHECK(produced_nonzero); } + +TEST_CASE("xorshift preserves nonzero seed behavior", "[xorshift]") +{ + exec::xorshift nonzero_seed{std::uint64_t{1}}; + CHECK(nonzero_seed() == 0xd989bcacU); +} From 400d1da5562f591bcba2f0fbb313d2aec64fa30d Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Thu, 8 Oct 2026 14:31:46 +0200 Subject: [PATCH 5/8] Sort xorshift test includes --- test/exec/test_xorshift.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/exec/test_xorshift.cpp b/test/exec/test_xorshift.cpp index 9114d5fdf..c4c004a80 100644 --- a/test/exec/test_xorshift.cpp +++ b/test/exec/test_xorshift.cpp @@ -14,8 +14,8 @@ * limitations under the License. */ -#include #include +#include #include From 04ed7a18c3ceedc284d053864e93deed02531ab5 Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Fri, 9 Oct 2026 20:43:00 +0200 Subject: [PATCH 6/8] style: fix clang-format alignment --- include/exec/detail/xorshift.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/exec/detail/xorshift.hpp b/include/exec/detail/xorshift.hpp index f581355de..0bd7133cc 100644 --- a/include/exec/detail/xorshift.hpp +++ b/include/exec/detail/xorshift.hpp @@ -92,7 +92,7 @@ namespace experimental::execution private: static constexpr std::uint64_t default_seed = 0xc1f651c67c62c6e0ull; - std::uint64_t m_seed; + std::uint64_t m_seed; }; } // namespace experimental::execution From 77c96a4d2e03e644cd3a30f58a6c95568ceb26e0 Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Sat, 10 Oct 2026 01:06:43 +0200 Subject: [PATCH 7/8] style: align xorshift declarations for clang-format 21 --- include/exec/detail/xorshift.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/exec/detail/xorshift.hpp b/include/exec/detail/xorshift.hpp index 0bd7133cc..f581355de 100644 --- a/include/exec/detail/xorshift.hpp +++ b/include/exec/detail/xorshift.hpp @@ -92,7 +92,7 @@ namespace experimental::execution private: static constexpr std::uint64_t default_seed = 0xc1f651c67c62c6e0ull; - std::uint64_t m_seed; + std::uint64_t m_seed; }; } // namespace experimental::execution From 8f0c5e01fdb7a1b07945e3c8fe5aca1e44379871 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Fri, 9 Oct 2026 16:14:38 -0700 Subject: [PATCH 8/8] formatting fix --- include/exec/detail/xorshift.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/exec/detail/xorshift.hpp b/include/exec/detail/xorshift.hpp index f581355de..28a91405d 100644 --- a/include/exec/detail/xorshift.hpp +++ b/include/exec/detail/xorshift.hpp @@ -92,7 +92,7 @@ namespace experimental::execution private: static constexpr std::uint64_t default_seed = 0xc1f651c67c62c6e0ull; - std::uint64_t m_seed; + std::uint64_t m_seed; }; } // namespace experimental::execution