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)
