[libcxx-commits] [libcxx] [libc++] Simplify more <random> engines (PR #195504)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun May 3 23:30:43 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

<details>
<summary>Changes</summary>

This uses `if _LIBCPP_CONSTEXPR` to simplify and deduplicate some of the code for the random engines.


---
Full diff: https://github.com/llvm/llvm-project/pull/195504.diff


4 Files Affected:

- (modified) libcxx/include/__random/independent_bits_engine.h (+23-29) 
- (modified) libcxx/include/__random/linear_congruential_engine.h (+20-35) 
- (modified) libcxx/include/__random/shuffle_order_engine.h (+15-24) 
- (modified) libcxx/include/__random/subtract_with_carry_engine.h (+25-54) 


``````````diff
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];

``````````

</details>


https://github.com/llvm/llvm-project/pull/195504


More information about the libcxx-commits mailing list