Dear maintainers of the GCC Compiler,

I am writing to you to submit a patch, pls see more information below.

The C++ Standard specifies that
std::negative_binomial_distribution::param(std::negative_binomial_distribution::param_type),
std::fisher_f_distribution::param(std::fisher_f_distribution::param_type),
and std::student_t_distribution::param(std::student_t_distribution::param_type)
should each update the internal parameters of the distribution to
match that specified by the arguments. These 3 distributions each
internally contain at least one member variable of type
std::gamma_distribution, the parameters of which are not modified when
the distribution parameters update. This causes
std::negative_binomial_distribution to fail to update entirely, while
the other two problematic distributions return inconsistent results as
their internal parameters are partially updated.

This patch addresses the issue by updating the relevant
std::gamma_distribution<double> member variable within each call to
param().

Due to hardware constraints of my computer (a laptop from 2012), I am
unable to run the entire test suite in a reasonable amount of time. I
would really appreciate if a GCC Compiler maintainer could help me run
the test suite. However, I did run my own unit test and it passes.

2026-07-01 Infinity Integral (05524F) <[email protected]>

libstdc++-v3/
    PR libstdc++/123409
    * include/bits/random.h (fisher_f_distribution::param): Update
parameters of internal gamma distributions.
    (student_t_distribution::param): Likewise.
    (negative_binomial_distribution::param): Likewise.
    * testsuite/26_numerics/random/pr123409.cc: New test.

Signed-off-by: Infinity Integral (05524F) <[email protected]>

---

diff --git a/libstdc++-v3/include/bits/random.h
b/libstdc++-v3/include/bits/random.h
index fd7b8b4fb..1eab18cf3 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -3980,7 +3980,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
        */
       void
       param(const param_type& __param)
-      { _M_param = __param; }
+      {
+ _M_param = __param;
+ _M_gd_x.param
+          (typename std::gamma_distribution<result_type>::param_type
+    (__param.m () / 2));
+ _M_gd_y.param
+  (typename std::gamma_distribution<result_type>::param_type
+    (__param.n () / 2));
+      }

       /**
        * @brief Returns the greatest lower bound value of the distribution.
@@ -4209,7 +4217,12 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
        */
       void
       param(const param_type& __param)
-      { _M_param = __param; }
+      {
+ _M_param = __param;
+ _M_gd.param
+  (typename std::gamma_distribution<result_type>::param_type
+    (__param.n () / 2, 2));
+      }

       /**
        * @brief Returns the greatest lower bound value of the distribution.
@@ -5140,7 +5153,13 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
        */
       void
       param(const param_type& __param)
-      { _M_param = __param; }
+      {
+        _M_param = __param;
+        _M_gd.param
+          (typename std::gamma_distribution<double>::param_type
+            (__param.k (),
+    (1.0 - __param.p ()) / __param.p ()));
+      }

       /**
        * @brief Returns the greatest lower bound value of the distribution.
diff --git a/libstdc++-v3/testsuite/26_numerics/random/pr123409.cc
b/libstdc++-v3/testsuite/26_numerics/random/pr123409.cc
new file mode 100644
index 000000000..eb033951b
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/pr123409.cc
@@ -0,0 +1,65 @@
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+// PR libstdc++/123409
+
+#include <random>
+#include <testsuite_hooks.h>
+
+std::mt19937_64 random_engine;
+unsigned long long seed = 0x19650809ull;
+
+void
+test01 ()
+{
+  std::negative_binomial_distribution<int> distribution (726, 0.65);
+  distribution.param
+    (std::negative_binomial_distribution<int>::param_type
+      (26, 0.26));
+  random_engine.seed (seed);
+  int first_num = distribution (random_engine);
+  distribution = std::negative_binomial_distribution<int> (26, 0.26);
+  random_engine.seed (seed);
+  int second_num = distribution (random_engine);
+  VERIFY (first_num == second_num);
+}
+
+void
+test02 ()
+{
+  std::fisher_f_distribution<float> distribution (7.0, 26.0);
+  distribution.param
+    (std::fisher_f_distribution<float>::param_type
+      (26.0, 7.0));
+  random_engine.seed (seed);
+  float first_num = distribution (random_engine);
+  distribution = std::fisher_f_distribution<float> (26.0, 7.0);
+  random_engine.seed (seed);
+  float second_num = distribution (random_engine);
+  VERIFY (first_num == second_num);
+}
+
+void
+test03 ()
+{
+  std::student_t_distribution<float> distribution (0.26);
+  distribution.param
+    (std::student_t_distribution<float>::param_type
+      (65.0));
+  random_engine.seed (seed);
+  float first_num = distribution (random_engine);
+  distribution = std::student_t_distribution<float> (65.0);
+  random_engine.seed (seed);
+  float second_num = distribution (random_engine);
+  VERIFY (first_num == second_num);
+}
+
+int
+main ()
+{
+  test01 ();
+  test02 ();
+  test03 ();
+  return 0;
+}
+

sincerely πŸ‡ΈπŸ‡¬ Singaporean,
05524F (Infinity Integral)

Reply via email to