[libcxx-commits] [libcxx] [libc++] Simplify more <random> engines (PR #195504)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Sat May 2 23:33:51 PDT 2026
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/195504
This uses `if _LIBCPP_CONSTEXPR` to simplify and deduplicate some of the code for the random engines.
>From 422110a7082b50099c461d1e366384e91445a8d5 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sun, 3 May 2026 08:33:10 +0200
Subject: [PATCH] [libc++] Simplify more <random> engines
---
.../__random/independent_bits_engine.h | 52 ++++++------
.../__random/linear_congruential_engine.h | 55 +++++--------
.../include/__random/shuffle_order_engine.h | 39 ++++-----
.../__random/subtract_with_carry_engine.h | 79 ++++++-------------
4 files changed, 83 insertions(+), 142 deletions(-)
diff --git a/libcxx/include/__random/independent_bits_engine.h b/libcxx/include/__random/independent_bits_engine.h
index 947ed1f55ddc9..c8faa9a5bfa46 100644
--- a/libcxx/include/__random/independent_bits_engine.h
+++ b/libcxx/include/__random/independent_bits_engine.h
@@ -105,7 +105,29 @@ class independent_bits_engine {
}
// generating functions
- _LIBCPP_HIDE_FROM_ABI result_type operator()() { return __eval(integral_constant<bool, _Rp != 0>()); }
+ _LIBCPP_HIDE_FROM_ABI result_type operator()() {
+ if _LIBCPP_CONSTEXPR (_Rp != 0) {
+ result_type __sp = 0;
+ for (size_t __k = 0; __k < __n0; ++__k) {
+ _Engine_result_type __u;
+ do {
+ __u = __e_() - _Engine::min();
+ } while (__u >= __y0);
+ __sp = static_cast<result_type>(__lshift<__w0>(__sp) + (__u & __mask0));
+ }
+ for (size_t __k = __n0; __k < __n; ++__k) {
+ _Engine_result_type __u;
+ do {
+ __u = __e_() - _Engine::min();
+ } while (__u >= __y1);
+ __sp = static_cast<result_type>(__lshift<__w0 + 1>(__sp) + (__u & __mask1));
+ }
+ return __sp;
+ } else {
+ return static_cast<result_type>(__e_() & __mask0);
+ }
+ }
+
_LIBCPP_HIDE_FROM_ABI void discard(unsigned long long __z) {
for (; __z; --__z)
operator()();
@@ -131,9 +153,6 @@ class independent_bits_engine {
operator>>(basic_istream<_CharT, _Traits>& __is, independent_bits_engine<_Eng, _Wp, _UInt>& __x);
private:
- _LIBCPP_HIDE_FROM_ABI result_type __eval(false_type);
- _LIBCPP_HIDE_FROM_ABI result_type __eval(true_type);
-
template <size_t __count,
__enable_if_t<__count< _Dt, int> = 0> _LIBCPP_HIDE_FROM_ABI static result_type __lshift(result_type __x) {
return __x << __count;
@@ -145,31 +164,6 @@ class independent_bits_engine {
}
};
-template <class _Engine, size_t __w, class _UIntType>
-inline _UIntType independent_bits_engine<_Engine, __w, _UIntType>::__eval(false_type) {
- return static_cast<result_type>(__e_() & __mask0);
-}
-
-template <class _Engine, size_t __w, class _UIntType>
-_UIntType independent_bits_engine<_Engine, __w, _UIntType>::__eval(true_type) {
- result_type __sp = 0;
- for (size_t __k = 0; __k < __n0; ++__k) {
- _Engine_result_type __u;
- do {
- __u = __e_() - _Engine::min();
- } while (__u >= __y0);
- __sp = static_cast<result_type>(__lshift<__w0>(__sp) + (__u & __mask0));
- }
- for (size_t __k = __n0; __k < __n; ++__k) {
- _Engine_result_type __u;
- do {
- __u = __e_() - _Engine::min();
- } while (__u >= __y1);
- __sp = static_cast<result_type>(__lshift<__w0 + 1>(__sp) + (__u & __mask1));
- }
- return __sp;
-}
-
template <class _Eng, size_t _Wp, class _UInt>
inline _LIBCPP_HIDE_FROM_ABI bool
operator==(const independent_bits_engine<_Eng, _Wp, _UInt>& __x, const independent_bits_engine<_Eng, _Wp, _UInt>& __y) {
diff --git a/libcxx/include/__random/linear_congruential_engine.h b/libcxx/include/__random/linear_congruential_engine.h
index e8d3425097e07..0c0bc42a5cbfa 100644
--- a/libcxx/include/__random/linear_congruential_engine.h
+++ b/libcxx/include/__random/linear_congruential_engine.h
@@ -269,15 +269,30 @@ class linear_congruential_engine {
_LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(_Sseq& __q) {
seed(__q);
}
+
_LIBCPP_HIDE_FROM_ABI void seed(result_type __s = default_seed) {
- seed(integral_constant<bool, __m == 0>(), integral_constant<bool, __c == 0>(), __s);
+ if _LIBCPP_CONSTEXPR (__m == 0) {
+ if _LIBCPP_CONSTEXPR (__c == 0)
+ __x_ = __s == 0 ? 1 : __s;
+ else
+ __x_ = __s;
+ } else {
+ if _LIBCPP_CONSTEXPR (__c == 0)
+ __x_ = __s % __m == 0 ? 1 : __s % __m;
+ else
+ __x_ = __s % __m;
+ }
}
+
template <class _Sseq, __enable_if_t<__is_seed_sequence_v<_Sseq, linear_congruential_engine>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void seed(_Sseq& __q) {
- __seed(
- __q,
- integral_constant<unsigned,
- 1 + (__m == 0 ? (sizeof(result_type) * __CHAR_BIT__ - 1) / 32 : (__m > 0x100000000ull))>());
+ const _LIBCPP_CONSTEXPR unsigned __k =
+ 1 + (__m == 0 ? (sizeof(result_type) * __CHAR_BIT__ - 1) / 32 : (__m > 0x100000000ull));
+ static_assert(__k <= 2);
+ uint32_t __ar[__k + 3];
+ __q.generate(__ar, __ar + __k + 3);
+ result_type __s = static_cast<result_type>((__ar[3] + (__k == 1 ? 0 : (uint64_t)__ar[4] << 32)) % __m);
+ __x_ = __c == 0 && __s == 0 ? result_type(1) : __s;
}
// generating functions
@@ -299,16 +314,6 @@ class linear_congruential_engine {
}
private:
- _LIBCPP_HIDE_FROM_ABI void seed(true_type, true_type, result_type __s) { __x_ = __s == 0 ? 1 : __s; }
- _LIBCPP_HIDE_FROM_ABI void seed(true_type, false_type, result_type __s) { __x_ = __s; }
- _LIBCPP_HIDE_FROM_ABI void seed(false_type, true_type, result_type __s) { __x_ = __s % __m == 0 ? 1 : __s % __m; }
- _LIBCPP_HIDE_FROM_ABI void seed(false_type, false_type, result_type __s) { __x_ = __s % __m; }
-
- template <class _Sseq>
- _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 1>);
- template <class _Sseq>
- _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 2>);
-
template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
friend basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_Up, _Ap, _Cp, _Np>&);
@@ -318,26 +323,6 @@ class linear_congruential_engine {
operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_Up, _Ap, _Cp, _Np>& __x);
};
-template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
-template <class _Sseq>
-void linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q, integral_constant<unsigned, 1>) {
- const unsigned __k = 1;
- uint32_t __ar[__k + 3];
- __q.generate(__ar, __ar + __k + 3);
- result_type __s = static_cast<result_type>(__ar[3] % __m);
- __x_ = __c == 0 && __s == 0 ? result_type(1) : __s;
-}
-
-template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
-template <class _Sseq>
-void linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q, integral_constant<unsigned, 2>) {
- const unsigned __k = 2;
- uint32_t __ar[__k + 3];
- __q.generate(__ar, __ar + __k + 3);
- result_type __s = static_cast<result_type>((__ar[3] + ((uint64_t)__ar[4] << 32)) % __m);
- __x_ = __c == 0 && __s == 0 ? result_type(1) : __s;
-}
-
template <class _CharT, class _Traits, class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
inline _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_UIntType, __a, __c, __m>& __x) {
diff --git a/libcxx/include/__random/shuffle_order_engine.h b/libcxx/include/__random/shuffle_order_engine.h
index febce5c7198dc..72fd27042e724 100644
--- a/libcxx/include/__random/shuffle_order_engine.h
+++ b/libcxx/include/__random/shuffle_order_engine.h
@@ -109,7 +109,21 @@ class shuffle_order_engine {
}
// generating functions
- _LIBCPP_HIDE_FROM_ABI result_type operator()() { return __eval(integral_constant<bool, _Rp != 0>()); }
+ _LIBCPP_HIDE_FROM_ABI result_type operator()() {
+ if _LIBCPP_CONSTEXPR (_Rp != 0 || !(__k & 1)) {
+ using _Ratio = __uratio<__k, _Rp != 0 ? _Rp : 0x8000000000000000ull>;
+ if _LIBCPP_CONSTEXPR (_Ratio::num > 0xFFFFFFFFFFFFFFFFull / (_Max - _Min)) {
+ return __evalf<_Ratio::num, _Ratio::den>();
+ } else {
+ const size_t __j = static_cast<size_t>(_Ratio::num * (__y_ - _Min) / _Ratio::den);
+ __y_ = __v_[__j];
+ __v_[__j] = __e_();
+ return __y_;
+ }
+ } else
+ return __evalf<__k, 0>();
+ }
+
_LIBCPP_HIDE_FROM_ABI void discard(unsigned long long __z) {
for (; __z; --__z)
operator()();
@@ -139,29 +153,6 @@ class shuffle_order_engine {
__y_ = __e_();
}
- _LIBCPP_HIDE_FROM_ABI result_type __eval(false_type) { return __eval2(integral_constant<bool, __k & 1>()); }
- _LIBCPP_HIDE_FROM_ABI result_type __eval(true_type) { return __eval(__uratio<__k, _Rp>()); }
-
- _LIBCPP_HIDE_FROM_ABI result_type __eval2(false_type) { return __eval(__uratio<__k / 2, 0x8000000000000000ull>()); }
- _LIBCPP_HIDE_FROM_ABI result_type __eval2(true_type) { return __evalf<__k, 0>(); }
-
- template <uint64_t _Np,
- uint64_t _Dp,
- __enable_if_t<(__uratio<_Np, _Dp>::num > 0xFFFFFFFFFFFFFFFFull / (_Max - _Min)), int> = 0>
- _LIBCPP_HIDE_FROM_ABI result_type __eval(__uratio<_Np, _Dp>) {
- return __evalf<__uratio<_Np, _Dp>::num, __uratio<_Np, _Dp>::den>();
- }
-
- template <uint64_t _Np,
- uint64_t _Dp,
- __enable_if_t<__uratio<_Np, _Dp>::num <= 0xFFFFFFFFFFFFFFFFull / (_Max - _Min), int> = 0>
- _LIBCPP_HIDE_FROM_ABI result_type __eval(__uratio<_Np, _Dp>) {
- const size_t __j = static_cast<size_t>(__uratio<_Np, _Dp>::num * (__y_ - _Min) / __uratio<_Np, _Dp>::den);
- __y_ = __v_[__j];
- __v_[__j] = __e_();
- return __y_;
- }
-
template <uint64_t __n, uint64_t __d>
_LIBCPP_HIDE_FROM_ABI result_type __evalf() {
const double __fp = __d == 0 ? __n / (2. * 0x8000000000000000ull) : __n / (double)__d;
diff --git a/libcxx/include/__random/subtract_with_carry_engine.h b/libcxx/include/__random/subtract_with_carry_engine.h
index cbff7c8fa18a2..755c7d9346eb5 100644
--- a/libcxx/include/__random/subtract_with_carry_engine.h
+++ b/libcxx/include/__random/subtract_with_carry_engine.h
@@ -90,12 +90,35 @@ class subtract_with_carry_engine {
_LIBCPP_HIDE_FROM_ABI explicit subtract_with_carry_engine(_Sseq& __q) {
seed(__q);
}
+
_LIBCPP_HIDE_FROM_ABI void seed(result_type __sd = default_seed) {
- seed(__sd, integral_constant<unsigned, 1 + (__w - 1) / 32>());
+ linear_congruential_engine<result_type, 40014u, 0u, 2147483563u> __e(__sd == 0u ? default_seed : __sd);
+ for (size_t __i = 0; __i < __r; ++__i) {
+ if _LIBCPP_CONSTEXPR ((1 + (__w - 1) / 32) == 1) {
+ __x_[__i] = static_cast<result_type>(__e() & _Max);
+ } else {
+ result_type __e0 = __e();
+ __x_[__i] = static_cast<result_type>((__e0 + ((uint64_t)__e() << 32)) & _Max);
+ }
+ }
+ __c_ = __x_[__r - 1] == 0;
+ __i_ = 0;
}
+
template <class _Sseq, __enable_if_t<__is_seed_sequence_v<_Sseq, subtract_with_carry_engine>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void seed(_Sseq& __q) {
- __seed(__q, integral_constant<unsigned, 1 + (__w - 1) / 32>());
+ const unsigned __k = 1 + (__w - 1) / 32;
+ static_assert(__k <= 2);
+ uint32_t __ar[__r * __k];
+ __q.generate(__ar, __ar + __r * __k);
+ for (size_t __i = 0; __i < __r; ++__i) {
+ if _LIBCPP_CONSTEXPR (__k == 1)
+ __x_[__i] = static_cast<result_type>(__ar[__i] & _Max);
+ else
+ __x_[__i] = static_cast<result_type>((__ar[2 * __i] + ((uint64_t)__ar[2 * __i + 1] << 32)) & _Max);
+ }
+ __c_ = __x_[__r - 1] == 0;
+ __i_ = 0;
}
// generating functions
@@ -120,60 +143,8 @@ class subtract_with_carry_engine {
template <class _CharT, class _Traits, class _UInt, size_t _Wp, size_t _Sp, size_t _Rp>
friend basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, subtract_with_carry_engine<_UInt, _Wp, _Sp, _Rp>& __x);
-
-private:
- _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd, integral_constant<unsigned, 1>);
- _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd, integral_constant<unsigned, 2>);
- template <class _Sseq>
- _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 1>);
- template <class _Sseq>
- _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 2>);
};
-template <class _UIntType, size_t __w, size_t __s, size_t __r>
-void subtract_with_carry_engine<_UIntType, __w, __s, __r>::seed(result_type __sd, integral_constant<unsigned, 1>) {
- linear_congruential_engine<result_type, 40014u, 0u, 2147483563u> __e(__sd == 0u ? default_seed : __sd);
- for (size_t __i = 0; __i < __r; ++__i)
- __x_[__i] = static_cast<result_type>(__e() & _Max);
- __c_ = __x_[__r - 1] == 0;
- __i_ = 0;
-}
-
-template <class _UIntType, size_t __w, size_t __s, size_t __r>
-void subtract_with_carry_engine<_UIntType, __w, __s, __r>::seed(result_type __sd, integral_constant<unsigned, 2>) {
- linear_congruential_engine<result_type, 40014u, 0u, 2147483563u> __e(__sd == 0u ? default_seed : __sd);
- for (size_t __i = 0; __i < __r; ++__i) {
- result_type __e0 = __e();
- __x_[__i] = static_cast<result_type>((__e0 + ((uint64_t)__e() << 32)) & _Max);
- }
- __c_ = __x_[__r - 1] == 0;
- __i_ = 0;
-}
-
-template <class _UIntType, size_t __w, size_t __s, size_t __r>
-template <class _Sseq>
-void subtract_with_carry_engine<_UIntType, __w, __s, __r>::__seed(_Sseq& __q, integral_constant<unsigned, 1>) {
- const unsigned __k = 1;
- uint32_t __ar[__r * __k];
- __q.generate(__ar, __ar + __r * __k);
- for (size_t __i = 0; __i < __r; ++__i)
- __x_[__i] = static_cast<result_type>(__ar[__i] & _Max);
- __c_ = __x_[__r - 1] == 0;
- __i_ = 0;
-}
-
-template <class _UIntType, size_t __w, size_t __s, size_t __r>
-template <class _Sseq>
-void subtract_with_carry_engine<_UIntType, __w, __s, __r>::__seed(_Sseq& __q, integral_constant<unsigned, 2>) {
- const unsigned __k = 2;
- uint32_t __ar[__r * __k];
- __q.generate(__ar, __ar + __r * __k);
- for (size_t __i = 0; __i < __r; ++__i)
- __x_[__i] = static_cast<result_type>((__ar[2 * __i] + ((uint64_t)__ar[2 * __i + 1] << 32)) & _Max);
- __c_ = __x_[__r - 1] == 0;
- __i_ = 0;
-}
-
template <class _UIntType, size_t __w, size_t __s, size_t __r>
_UIntType subtract_with_carry_engine<_UIntType, __w, __s, __r>::operator()() {
const result_type& __xs = __x_[(__i_ + (__r - __s)) % __r];
More information about the libcxx-commits
mailing list