From c3e29e128dd86c4124ab5d2c76445e0426198f1c Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Sun, 13 Dec 2020 22:51:39 -0800 Subject: [PATCH 01/11] Fixes inaccurate binomial_distribution for certain parameters - For small mean, replaces Poisson approximation with exact waiting time method based on cumulative sum of exponential variates. - Uses cheap but rigorous approximation of exit condition for fast return on first iteration. --- stl/inc/random | 28 +++++++++++-- tests/std/test.lst | 1 + .../tests/GH_001530_binomial_accuracy/env.lst | 4 ++ .../GH_001530_binomial_accuracy/test.cpp | 41 +++++++++++++++++++ 4 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 tests/std/tests/GH_001530_binomial_accuracy/env.lst create mode 100644 tests/std/tests/GH_001530_binomial_accuracy/test.cpp diff --git a/stl/inc/random b/stl/inc/random index a0a9d74b0de..98837e43264 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2447,7 +2447,7 @@ public: _Ty1 _Logp; _Ty1 _Logp1; - _Small_poisson_distribution<_Ty> _Small; + _Small_poisson_distribution<_Ty> _Small; // TRANSITION, ABI: unused }; binomial_distribution() : _Par(1, _Ty1(0.5)) {} @@ -2524,8 +2524,30 @@ private: return _Res; } else if (_Par0._Mean < 1.0) { - // events are rare, use Poisson distribution - _Res = _Par0._Small(_Eng); + // Events are rare, use waiting time method. + const _Ty1 _Rand = _NRAND(_Eng, _Ty1); + { + // The exit condition is -log(1 - _Rand)/t > -log(1-p), which is equivalent to _Rand > 1 - (1-p)^t. If + // we have a cheap upper bound for 1-(1-p)^t, we can exit early without having to call log. We use two + // such bounds, one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's + // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t = + // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e. + const _Ty1 _Ub = + std::min(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Px + _Ty1{6.32120558828557678e-1}); + if (_Rand > _Ub) + return 0; + } + + _Ty1 _Sum = -_CSTD log(_Ty1{1.0} - _Rand) / _Par0._Tx; + if (_Sum > -_Par0._Logp1) + return 0; + _Res = 1; + + do { + _Sum += -_CSTD log(_Ty1{1.0} - _NRAND(_Eng, _Ty1)) / (_Par0._Tx - _Res); + ++_Res; + } while (_Sum <= -_Par0._Logp1 && _Res != _Par0._Tx); + return (_Sum > -_Par0._Logp1) ? _Res - 1 : _Par0._Tx; } else { // no shortcuts using _Uty = make_unsigned_t<_Ty>; const auto _Ty1_Tx{_Float_upper_bound<_Ty1>(static_cast<_Uty>(_Par0._Tx))}; diff --git a/tests/std/test.lst b/tests/std/test.lst index 3d71f043206..dea9514e174 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -172,6 +172,7 @@ tests\GH_001103_countl_zero_correctness tests\GH_001105_custom_streambuf_throws tests\GH_001123_random_cast_out_of_range tests\GH_001411_core_headers +tests\GH_001530_binomial_accuracy tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function tests\P0019R8_atomic_ref diff --git a/tests/std/tests/GH_001530_binomial_accuracy/env.lst b/tests/std/tests/GH_001530_binomial_accuracy/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_001530_binomial_accuracy/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_001530_binomial_accuracy/test.cpp b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp new file mode 100644 index 00000000000..d1e49e77fab --- /dev/null +++ b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +using namespace std; + +int main() { + constexpr int it_max = 100'000; + constexpr int n = 25; + constexpr double mean = 0.99; + constexpr double p = mean / n; + constexpr double var = n * p * (1.0 - p); + + mt19937 gen; + binomial_distribution<> dist(n, p); + + vector counts(n + 1); + for (int i = 0; i < it_max; ++i) { + ++counts[static_cast(dist(gen))]; + } + + double sample_mean = 0.0; + for (size_t i = 1; i < counts.size(); ++i) { + sample_mean += static_cast(i) * counts[i]; + } + sample_mean /= it_max; + + double sample_var = 0.0; + for (size_t i = 0; i < counts.size(); ++i) { + sample_var += counts[i] * pow(i - sample_mean, 2); + } + sample_var /= it_max - 1; + + assert(abs(sample_mean / mean - 1.0) < 0.01); + assert(abs(sample_var / var - 1.0) < 0.01); + return 0; +} From 8ab30a08806f6069c14ac02afcb102654179b87b Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Mon, 14 Dec 2020 00:18:10 -0800 Subject: [PATCH 02/11] buildfix --- stl/inc/random | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/random b/stl/inc/random index 98837e43264..dfb012c5a78 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2541,13 +2541,13 @@ private: _Ty1 _Sum = -_CSTD log(_Ty1{1.0} - _Rand) / _Par0._Tx; if (_Sum > -_Par0._Logp1) return 0; - _Res = 1; + _Res = _Ty{1}; do { _Sum += -_CSTD log(_Ty1{1.0} - _NRAND(_Eng, _Ty1)) / (_Par0._Tx - _Res); ++_Res; } while (_Sum <= -_Par0._Logp1 && _Res != _Par0._Tx); - return (_Sum > -_Par0._Logp1) ? _Res - 1 : _Par0._Tx; + return (_Sum > -_Par0._Logp1) ? static_cast<_Ty>(_Res - _Ty{1}) : _Par0._Tx; } else { // no shortcuts using _Uty = make_unsigned_t<_Ty>; const auto _Ty1_Tx{_Float_upper_bound<_Ty1>(static_cast<_Uty>(_Par0._Tx))}; From ff17926057fcaa7347c87abfdc6d6b77e06564e8 Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Sun, 27 Dec 2020 08:36:07 -0800 Subject: [PATCH 03/11] code review --- stl/inc/random | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/random b/stl/inc/random index dfb012c5a78..3676152b9a4 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2533,7 +2533,7 @@ private: // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t = // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e. const _Ty1 _Ub = - std::min(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Px + _Ty1{6.32120558828557678e-1}); + (_STD min)(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Px + _Ty1{6.32120558828557678e-1}); if (_Rand > _Ub) return 0; } From 8dfeba45e03023c2901a334987c1fb5261316259 Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Sun, 27 Dec 2020 10:22:17 -0800 Subject: [PATCH 04/11] code review: simplify control flow --- stl/inc/random | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/stl/inc/random b/stl/inc/random index 3676152b9a4..544d7860ad2 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2524,30 +2524,26 @@ private: return _Res; } else if (_Par0._Mean < 1.0) { - // Events are rare, use waiting time method. + // Events are rare, use waiting time method (Luc Devroye, Non-Uniform Random Variate Generation, p. 525). const _Ty1 _Rand = _NRAND(_Eng, _Ty1); { - // The exit condition is -log(1 - _Rand)/t > -log(1-p), which is equivalent to _Rand > 1 - (1-p)^t. If - // we have a cheap upper bound for 1-(1-p)^t, we can exit early without having to call log. We use two - // such bounds, one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's - // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t = - // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e. - const _Ty1 _Ub = - (_STD min)(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Px + _Ty1{6.32120558828557678e-1}); - if (_Rand > _Ub) + // The exit condition is log(Rand)/t < log(1-p), which is equivalent to _Rand < (1-p)^t. If we have a + // cheap lower bound for (1-p)^t, we can exit early without having to call log. We use two such bounds, + // one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's inequality + // gives (1-p)^t >= 1-p*t = 1 - mean. For the other bound, (1-p)^t = (1-p)(1-mean/t)^(t-1) >= + // (1-p)(1-1/t)^(t-1) > (1-p)/e. + const _Ty1 _Lb = + (_STD max)(_Ty1{1.0} - _Par0._Mean, _Ty1{3.678794411714423216e-1} * (_Ty1{1.0} - _Par0._Px)); + if (_Rand < _Lb) return 0; } - _Ty1 _Sum = -_CSTD log(_Ty1{1.0} - _Rand) / _Par0._Tx; - if (_Sum > -_Par0._Logp1) - return 0; - _Res = _Ty{1}; - - do { - _Sum += -_CSTD log(_Ty1{1.0} - _NRAND(_Eng, _Ty1)) / (_Par0._Tx - _Res); - ++_Res; - } while (_Sum <= -_Par0._Logp1 && _Res != _Par0._Tx); - return (_Sum > -_Par0._Logp1) ? static_cast<_Ty>(_Res - _Ty{1}) : _Par0._Tx; + _Ty _Denom = _Par0._Tx; + _Ty1 _Sum = _CSTD log(_Rand) / _Denom; + while (_Sum >= _Par0._Logp1 && --_Denom != 0) { + _Sum += _CSTD log(_NRAND(_Eng, _Ty1)) / _Denom; + } + return _Par0._Tx - _Denom; } else { // no shortcuts using _Uty = make_unsigned_t<_Ty>; const auto _Ty1_Tx{_Float_upper_bound<_Ty1>(static_cast<_Uty>(_Par0._Tx))}; From a107fd48f78f42f6745a0ddba56f3b9c02b24545 Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Sun, 27 Dec 2020 10:58:35 -0800 Subject: [PATCH 05/11] buildfix --- stl/inc/random | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/stl/inc/random b/stl/inc/random index 544d7860ad2..3af9461bf32 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2527,23 +2527,23 @@ private: // Events are rare, use waiting time method (Luc Devroye, Non-Uniform Random Variate Generation, p. 525). const _Ty1 _Rand = _NRAND(_Eng, _Ty1); { - // The exit condition is log(Rand)/t < log(1-p), which is equivalent to _Rand < (1-p)^t. If we have a - // cheap lower bound for (1-p)^t, we can exit early without having to call log. We use two such bounds, - // one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's inequality - // gives (1-p)^t >= 1-p*t = 1 - mean. For the other bound, (1-p)^t = (1-p)(1-mean/t)^(t-1) >= - // (1-p)(1-1/t)^(t-1) > (1-p)/e. - const _Ty1 _Lb = - (_STD max)(_Ty1{1.0} - _Par0._Mean, _Ty1{3.678794411714423216e-1} * (_Ty1{1.0} - _Par0._Px)); - if (_Rand < _Lb) + // The exit condition is -log(1 - _Rand)/t > -log(1-p), which is equivalent to _Rand > 1 - (1-p)^t. If + // we have a cheap upper bound for 1-(1-p)^t, we can exit early without having to call log. We use two + // such bounds, one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's + // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t = + // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e. + const _Ty1 _Ub = + std::min(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Px + _Ty1{6.32120558828557678e-1}); + if (_Rand > _Ub) return 0; } _Ty _Denom = _Par0._Tx; - _Ty1 _Sum = _CSTD log(_Rand) / _Denom; + _Ty1 _Sum = _CSTD log(_Ty1{1.0} - _Rand) / _Denom; while (_Sum >= _Par0._Logp1 && --_Denom != 0) { - _Sum += _CSTD log(_NRAND(_Eng, _Ty1)) / _Denom; + _Sum += _CSTD log(_Ty1{1.0} - _NRAND(_Eng, _Ty1)) / _Denom; } - return _Par0._Tx - _Denom; + return static_cast<_Ty>(_Par0._Tx - _Denom); } else { // no shortcuts using _Uty = make_unsigned_t<_Ty>; const auto _Ty1_Tx{_Float_upper_bound<_Ty1>(static_cast<_Uty>(_Par0._Tx))}; From 498c0243c1fe8935ca5f0b9c7e76e5b1666dedad Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Sun, 27 Dec 2020 11:14:34 -0800 Subject: [PATCH 06/11] Fix copy-paste mistake --- stl/inc/random | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/random b/stl/inc/random index 3af9461bf32..b8a22397f89 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2533,7 +2533,7 @@ private: // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t = // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e. const _Ty1 _Ub = - std::min(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Px + _Ty1{6.32120558828557678e-1}); + (_STD min)(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Px + _Ty1{6.32120558828557678e-1}); if (_Rand > _Ub) return 0; } From 225f510c4de4f7a6a66060f9f7426f26f846a82c Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Sun, 27 Dec 2020 11:18:44 -0800 Subject: [PATCH 07/11] Make comment consistent with code --- stl/inc/random | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/random b/stl/inc/random index b8a22397f89..e061b6178fa 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2527,7 +2527,7 @@ private: // Events are rare, use waiting time method (Luc Devroye, Non-Uniform Random Variate Generation, p. 525). const _Ty1 _Rand = _NRAND(_Eng, _Ty1); { - // The exit condition is -log(1 - _Rand)/t > -log(1-p), which is equivalent to _Rand > 1 - (1-p)^t. If + // The exit condition is log(1 - _Rand)/t < log(1-p), which is equivalent to _Rand > 1 - (1-p)^t. If // we have a cheap upper bound for 1-(1-p)^t, we can exit early without having to call log. We use two // such bounds, one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t = From 9203bafbbfa961615dd9e2c3603bcf33909c7087 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 8 Jan 2021 19:26:02 -0800 Subject: [PATCH 08/11] Code review feedback. --- stl/inc/random | 3 ++- tests/std/tests/GH_001530_binomial_accuracy/test.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/stl/inc/random b/stl/inc/random index e061b6178fa..72df0c8e714 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2534,8 +2534,9 @@ private: // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e. const _Ty1 _Ub = (_STD min)(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Px + _Ty1{6.32120558828557678e-1}); - if (_Rand > _Ub) + if (_Rand > _Ub) { return 0; + } } _Ty _Denom = _Par0._Tx; diff --git a/tests/std/tests/GH_001530_binomial_accuracy/test.cpp b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp index d1e49e77fab..d919b9b028d 100644 --- a/tests/std/tests/GH_001530_binomial_accuracy/test.cpp +++ b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include From 8bad736dbfaa37f172b8dd3fc4e835abee5d925b Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Wed, 13 Jan 2021 20:39:56 -0800 Subject: [PATCH 09/11] Handle p ~1 case. --- stl/inc/random | 33 +++++++++---------- .../GH_001530_binomial_accuracy/test.cpp | 26 +++++++++------ 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/stl/inc/random b/stl/inc/random index 72df0c8e714..c5376b1ac5d 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -2526,25 +2526,24 @@ private: } else if (_Par0._Mean < 1.0) { // Events are rare, use waiting time method (Luc Devroye, Non-Uniform Random Variate Generation, p. 525). const _Ty1 _Rand = _NRAND(_Eng, _Ty1); - { - // The exit condition is log(1 - _Rand)/t < log(1-p), which is equivalent to _Rand > 1 - (1-p)^t. If - // we have a cheap upper bound for 1-(1-p)^t, we can exit early without having to call log. We use two - // such bounds, one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's - // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t = - // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e. - const _Ty1 _Ub = - (_STD min)(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Px + _Ty1{6.32120558828557678e-1}); - if (_Rand > _Ub) { - return 0; - } - } - _Ty _Denom = _Par0._Tx; - _Ty1 _Sum = _CSTD log(_Ty1{1.0} - _Rand) / _Denom; - while (_Sum >= _Par0._Logp1 && --_Denom != 0) { - _Sum += _CSTD log(_Ty1{1.0} - _NRAND(_Eng, _Ty1)) / _Denom; + // The exit condition is log(1 - _Rand)/t < log(1-p), which is equivalent to _Rand > 1 - (1-p)^t. If + // we have a cheap upper bound for 1-(1-p)^t, we can exit early without having to call log. We use two + // such bounds, one that is tight for mean ~0 and another for mean ~1. In the first case, Bernoulli's + // inequality gives -1+p*t >= -(1-p)^t, so 1 - (1-p)^t <= p*t = mean. For the other bound, 1-(1-p)^t = + // 1-(1-p)(1-mean/t)^(t-1) <= 1-(1-p)(1-1/t)^(t-1) <= 1-(1-p)/e. + const _Ty1 _Ub = + (_STD min)(_Par0._Mean, _Ty1{3.678794411714423216e-1} * _Par0._Pp + _Ty1{6.32120558828557678e-1}); + if (_Rand > _Ub) { + _Res = _Ty{0}; + } else { + _Ty _Denom = _Par0._Tx; + _Ty1 _Sum = _CSTD log(_Ty1{1.0} - _Rand) / _Denom; + while (_Sum >= _Par0._Logp1 && --_Denom != 0) { + _Sum += _CSTD log(_Ty1{1.0} - _NRAND(_Eng, _Ty1)) / _Denom; + } + _Res = static_cast<_Ty>(_Par0._Tx - _Denom); } - return static_cast<_Ty>(_Par0._Tx - _Denom); } else { // no shortcuts using _Uty = make_unsigned_t<_Ty>; const auto _Ty1_Tx{_Float_upper_bound<_Ty1>(static_cast<_Uty>(_Par0._Tx))}; diff --git a/tests/std/tests/GH_001530_binomial_accuracy/test.cpp b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp index d919b9b028d..64a8cdc2d87 100644 --- a/tests/std/tests/GH_001530_binomial_accuracy/test.cpp +++ b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp @@ -9,18 +9,17 @@ using namespace std; -int main() { - constexpr int it_max = 100'000; - constexpr int n = 25; - constexpr double mean = 0.99; - constexpr double p = mean / n; - constexpr double var = n * p * (1.0 - p); - - mt19937 gen; +template +void test_binomial(const int n, const double mean, Generator& gen) { + const double p = mean / n; + const double var = n * p * (1.0 - p); + constexpr double tol = 0.01; + constexpr double x = 4.0; + const size_t it_max = 2 * static_cast(pow(var / (tol / x), 2.0)); binomial_distribution<> dist(n, p); - vector counts(n + 1); - for (int i = 0; i < it_max; ++i) { + vector counts(static_cast(n) + 1); + for (size_t i = 0; i < it_max; ++i) { ++counts[static_cast(dist(gen))]; } @@ -38,5 +37,12 @@ int main() { assert(abs(sample_mean / mean - 1.0) < 0.01); assert(abs(sample_var / var - 1.0) < 0.01); +} + +int main() { + mt19937 gen; + constexpr int n = 25; + test_binomial(n, 0.99, gen); + test_binomial(n, n - 0.99, gen); return 0; } From 5182599abbd633f946555650a9dd5b86b4be8361 Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Fri, 15 Jan 2021 23:58:43 -0800 Subject: [PATCH 10/11] typo --- tests/std/tests/GH_001530_binomial_accuracy/test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/GH_001530_binomial_accuracy/test.cpp b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp index 64a8cdc2d87..4c3d704e7e4 100644 --- a/tests/std/tests/GH_001530_binomial_accuracy/test.cpp +++ b/tests/std/tests/GH_001530_binomial_accuracy/test.cpp @@ -14,7 +14,7 @@ void test_binomial(const int n, const double mean, Generator& gen) { const double p = mean / n; const double var = n * p * (1.0 - p); constexpr double tol = 0.01; - constexpr double x = 4.0; + constexpr double x = 4.0; // Standard deviation of sample variance should be less than tol / x. const size_t it_max = 2 * static_cast(pow(var / (tol / x), 2.0)); binomial_distribution<> dist(n, p); @@ -35,8 +35,8 @@ void test_binomial(const int n, const double mean, Generator& gen) { } sample_var /= it_max - 1; - assert(abs(sample_mean / mean - 1.0) < 0.01); - assert(abs(sample_var / var - 1.0) < 0.01); + assert(abs(sample_mean / mean - 1.0) < tol); + assert(abs(sample_var / var - 1.0) < tol); } int main() { From f4807a5d5f022a8c8aa0f8dd88e098b5cdb36d38 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 8 Feb 2021 13:30:56 -0800 Subject: [PATCH 11/11] Casey's guess that #1530 caused these libcxx failures was wrong --- tests/libcxx/expected_results.txt | 4 +--- tests/libcxx/skipped_tests.txt | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index e406827dbd4..ab15161db86 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -483,9 +483,6 @@ std/algorithms/robust_against_adl.pass.cpp FAIL # GH-1595: : bit_ceil(T(-1)) should not be a constant expression std/numerics/bit/bit.pow.two/bit_ceil.fail.cpp:0 FAIL -# GH-1530: : Poisson approximation for binomial_distribution is not accurate -std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.bin/eval.PR44847.pass.cpp FAIL - # *** CRT BUGS *** # We're permanently missing aligned_alloc(). @@ -669,6 +666,7 @@ std/input.output/filesystems/fs.filesystem.synopsis/file_time_type_resolution.co # Not yet analyzed, likely STL bugs. Assertions and other runtime failures. std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.bin/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp FAIL +std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.bin/eval.PR44847.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.geo/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.bern/rand.dist.bern.negbin/eval_param.pass.cpp FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 9482df7db03..e69a02c150b 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -483,9 +483,6 @@ algorithms\robust_against_adl.pass.cpp # GH-1595: : bit_ceil(T(-1)) should not be a constant expression numerics\bit\bit.pow.two\bit_ceil.fail.cpp -# GH-1530: : Poisson approximation for binomial_distribution is not accurate -numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.bin\eval.PR44847.pass.cpp - # *** CRT BUGS *** # We're permanently missing aligned_alloc(). @@ -669,6 +666,7 @@ input.output\filesystems\fs.filesystem.synopsis\file_time_type_resolution.compil # Not yet analyzed, likely STL bugs. Assertions and other runtime failures. numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.bin\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.bin\eval.pass.cpp +numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.bin\eval.PR44847.pass.cpp numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.geo\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.geo\eval.pass.cpp numerics\rand\rand.dis\rand.dist.bern\rand.dist.bern.negbin\eval_param.pass.cpp