1eb1c5037SNikolas Klauser //===----------------------------------------------------------------------===// 2eb1c5037SNikolas Klauser // 3eb1c5037SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4eb1c5037SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5eb1c5037SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6eb1c5037SNikolas Klauser // 7eb1c5037SNikolas Klauser //===----------------------------------------------------------------------===// 8eb1c5037SNikolas Klauser // 9eb1c5037SNikolas Klauser // REQUIRES: long_tests 10eb1c5037SNikolas Klauser 11f376a3bbSEric // This test is super slow, in particular with msan or tsan. In order to avoid timeouts and to 12f376a3bbSEric // spend less time waiting for this particular test to complete we compile with optimizations. 13f376a3bbSEric // ADDITIONAL_COMPILE_FLAGS(msan): -O1 14f376a3bbSEric // ADDITIONAL_COMPILE_FLAGS(tsan): -O1 15f376a3bbSEric 16f376a3bbSEric // FIXME: This and other tests fail under GCC with optimizations enabled. 17f376a3bbSEric // More investigation is needed, but it appears that GCC is performing more constant folding. 18f376a3bbSEric 19eb1c5037SNikolas Klauser // <random> 20eb1c5037SNikolas Klauser 21eb1c5037SNikolas Klauser // template<class IntType = int> 22eb1c5037SNikolas Klauser // class negative_binomial_distribution 23eb1c5037SNikolas Klauser 24eb1c5037SNikolas Klauser // template<class _URNG> result_type operator()(_URNG& g); 25eb1c5037SNikolas Klauser 26eb1c5037SNikolas Klauser #include <random> 27*09e3a360SLouis Dionne #include <cassert> 28*09e3a360SLouis Dionne #include <cmath> 29eb1c5037SNikolas Klauser #include <numeric> 30eb1c5037SNikolas Klauser #include <vector> 31eb1c5037SNikolas Klauser 3207e984bcSLouis Dionne #include "test_macros.h" 3307e984bcSLouis Dionne 34eb1c5037SNikolas Klauser template <class T> 3507e984bcSLouis Dionne T sqr(T x) { 36eb1c5037SNikolas Klauser return x * x; 37eb1c5037SNikolas Klauser } 38eb1c5037SNikolas Klauser 3907e984bcSLouis Dionne template <class T> 4007e984bcSLouis Dionne void test1() { 4107e984bcSLouis Dionne typedef std::negative_binomial_distribution<T> D; 42eb1c5037SNikolas Klauser typedef std::minstd_rand G; 43eb1c5037SNikolas Klauser G g; 44eb1c5037SNikolas Klauser D d(5, .25); 45eb1c5037SNikolas Klauser const int N = 1000000; 4607e984bcSLouis Dionne std::vector<typename D::result_type> u; 47eb1c5037SNikolas Klauser for (int i = 0; i < N; ++i) 48eb1c5037SNikolas Klauser { 4907e984bcSLouis Dionne typename D::result_type v = d(g); 50eb1c5037SNikolas Klauser assert(d.min() <= v && v <= d.max()); 51eb1c5037SNikolas Klauser u.push_back(v); 52eb1c5037SNikolas Klauser } 53eb1c5037SNikolas Klauser double mean = std::accumulate(u.begin(), u.end(), 54eb1c5037SNikolas Klauser double(0)) / u.size(); 55eb1c5037SNikolas Klauser double var = 0; 56eb1c5037SNikolas Klauser double skew = 0; 57eb1c5037SNikolas Klauser double kurtosis = 0; 58eb1c5037SNikolas Klauser for (unsigned i = 0; i < u.size(); ++i) 59eb1c5037SNikolas Klauser { 60eb1c5037SNikolas Klauser double dbl = (u[i] - mean); 61eb1c5037SNikolas Klauser double d2 = sqr(dbl); 62eb1c5037SNikolas Klauser var += d2; 63eb1c5037SNikolas Klauser skew += dbl * d2; 64eb1c5037SNikolas Klauser kurtosis += d2 * d2; 65eb1c5037SNikolas Klauser } 66eb1c5037SNikolas Klauser var /= u.size(); 67eb1c5037SNikolas Klauser double dev = std::sqrt(var); 68eb1c5037SNikolas Klauser skew /= u.size() * dev * var; 69eb1c5037SNikolas Klauser kurtosis /= u.size() * var * var; 70eb1c5037SNikolas Klauser kurtosis -= 3; 71eb1c5037SNikolas Klauser double x_mean = d.k() * (1 - d.p()) / d.p(); 72eb1c5037SNikolas Klauser double x_var = x_mean / d.p(); 73eb1c5037SNikolas Klauser double x_skew = (2 - d.p()) / std::sqrt(d.k() * (1 - d.p())); 74eb1c5037SNikolas Klauser double x_kurtosis = 6. / d.k() + sqr(d.p()) / (d.k() * (1 - d.p())); 75eb1c5037SNikolas Klauser assert(std::abs((mean - x_mean) / x_mean) < 0.01); 76eb1c5037SNikolas Klauser assert(std::abs((var - x_var) / x_var) < 0.01); 77eb1c5037SNikolas Klauser assert(std::abs((skew - x_skew) / x_skew) < 0.01); 7876aa042dSMatt Stephanson assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03); 79eb1c5037SNikolas Klauser } 80eb1c5037SNikolas Klauser 8107e984bcSLouis Dionne template <class T> 8207e984bcSLouis Dionne void test2() { 8307e984bcSLouis Dionne typedef std::negative_binomial_distribution<T> D; 84eb1c5037SNikolas Klauser typedef std::mt19937 G; 85eb1c5037SNikolas Klauser G g; 86eb1c5037SNikolas Klauser D d(30, .03125); 87eb1c5037SNikolas Klauser const int N = 1000000; 8807e984bcSLouis Dionne std::vector<typename D::result_type> u; 89eb1c5037SNikolas Klauser for (int i = 0; i < N; ++i) 90eb1c5037SNikolas Klauser { 9107e984bcSLouis Dionne typename D::result_type v = d(g); 92eb1c5037SNikolas Klauser assert(d.min() <= v && v <= d.max()); 93eb1c5037SNikolas Klauser u.push_back(v); 94eb1c5037SNikolas Klauser } 95eb1c5037SNikolas Klauser double mean = std::accumulate(u.begin(), u.end(), 96eb1c5037SNikolas Klauser double(0)) / u.size(); 97eb1c5037SNikolas Klauser double var = 0; 98eb1c5037SNikolas Klauser double skew = 0; 99eb1c5037SNikolas Klauser double kurtosis = 0; 100eb1c5037SNikolas Klauser for (unsigned i = 0; i < u.size(); ++i) 101eb1c5037SNikolas Klauser { 102eb1c5037SNikolas Klauser double dbl = (u[i] - mean); 103eb1c5037SNikolas Klauser double d2 = sqr(dbl); 104eb1c5037SNikolas Klauser var += d2; 105eb1c5037SNikolas Klauser skew += dbl * d2; 106eb1c5037SNikolas Klauser kurtosis += d2 * d2; 107eb1c5037SNikolas Klauser } 108eb1c5037SNikolas Klauser var /= u.size(); 109eb1c5037SNikolas Klauser double dev = std::sqrt(var); 110eb1c5037SNikolas Klauser skew /= u.size() * dev * var; 111eb1c5037SNikolas Klauser kurtosis /= u.size() * var * var; 112eb1c5037SNikolas Klauser kurtosis -= 3; 113eb1c5037SNikolas Klauser double x_mean = d.k() * (1 - d.p()) / d.p(); 114eb1c5037SNikolas Klauser double x_var = x_mean / d.p(); 115eb1c5037SNikolas Klauser double x_skew = (2 - d.p()) / std::sqrt(d.k() * (1 - d.p())); 116eb1c5037SNikolas Klauser double x_kurtosis = 6. / d.k() + sqr(d.p()) / (d.k() * (1 - d.p())); 117eb1c5037SNikolas Klauser assert(std::abs((mean - x_mean) / x_mean) < 0.01); 118eb1c5037SNikolas Klauser assert(std::abs((var - x_var) / x_var) < 0.01); 11976aa042dSMatt Stephanson assert(std::abs((skew - x_skew) / x_skew) < 0.02); 12076aa042dSMatt Stephanson assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.1); 121eb1c5037SNikolas Klauser } 122eb1c5037SNikolas Klauser 12307e984bcSLouis Dionne template <class T> 12407e984bcSLouis Dionne void test3() { 12507e984bcSLouis Dionne typedef std::negative_binomial_distribution<T> D; 126eb1c5037SNikolas Klauser typedef std::mt19937 G; 127eb1c5037SNikolas Klauser G g; 128eb1c5037SNikolas Klauser D d(40, .25); 129eb1c5037SNikolas Klauser const int N = 1000000; 13007e984bcSLouis Dionne std::vector<typename D::result_type> u; 131eb1c5037SNikolas Klauser for (int i = 0; i < N; ++i) 132eb1c5037SNikolas Klauser { 13307e984bcSLouis Dionne typename D::result_type v = d(g); 134eb1c5037SNikolas Klauser assert(d.min() <= v && v <= d.max()); 135eb1c5037SNikolas Klauser u.push_back(v); 136eb1c5037SNikolas Klauser } 137eb1c5037SNikolas Klauser double mean = std::accumulate(u.begin(), u.end(), 138eb1c5037SNikolas Klauser double(0)) / u.size(); 139eb1c5037SNikolas Klauser double var = 0; 140eb1c5037SNikolas Klauser double skew = 0; 141eb1c5037SNikolas Klauser double kurtosis = 0; 142eb1c5037SNikolas Klauser for (unsigned i = 0; i < u.size(); ++i) 143eb1c5037SNikolas Klauser { 144eb1c5037SNikolas Klauser double dbl = (u[i] - mean); 145eb1c5037SNikolas Klauser double d2 = sqr(dbl); 146eb1c5037SNikolas Klauser var += d2; 147eb1c5037SNikolas Klauser skew += dbl * d2; 148eb1c5037SNikolas Klauser kurtosis += d2 * d2; 149eb1c5037SNikolas Klauser } 150eb1c5037SNikolas Klauser var /= u.size(); 151eb1c5037SNikolas Klauser double dev = std::sqrt(var); 152eb1c5037SNikolas Klauser skew /= u.size() * dev * var; 153eb1c5037SNikolas Klauser kurtosis /= u.size() * var * var; 154eb1c5037SNikolas Klauser kurtosis -= 3; 155eb1c5037SNikolas Klauser double x_mean = d.k() * (1 - d.p()) / d.p(); 156eb1c5037SNikolas Klauser double x_var = x_mean / d.p(); 157eb1c5037SNikolas Klauser double x_skew = (2 - d.p()) / std::sqrt(d.k() * (1 - d.p())); 158eb1c5037SNikolas Klauser double x_kurtosis = 6. / d.k() + sqr(d.p()) / (d.k() * (1 - d.p())); 159eb1c5037SNikolas Klauser assert(std::abs((mean - x_mean) / x_mean) < 0.01); 160eb1c5037SNikolas Klauser assert(std::abs((var - x_var) / x_var) < 0.01); 16176aa042dSMatt Stephanson assert(std::abs((skew - x_skew) / x_skew) < 0.02); 16276aa042dSMatt Stephanson assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.08); 163eb1c5037SNikolas Klauser } 164eb1c5037SNikolas Klauser 16507e984bcSLouis Dionne template <class T> 16607e984bcSLouis Dionne void test4() { 16707e984bcSLouis Dionne typedef std::negative_binomial_distribution<T> D; 168eb1c5037SNikolas Klauser typedef std::mt19937 G; 169eb1c5037SNikolas Klauser G g; 170eb1c5037SNikolas Klauser D d(40, 1); 171eb1c5037SNikolas Klauser const int N = 1000; 17207e984bcSLouis Dionne std::vector<typename D::result_type> u; 173eb1c5037SNikolas Klauser for (int i = 0; i < N; ++i) 174eb1c5037SNikolas Klauser { 17507e984bcSLouis Dionne typename D::result_type v = d(g); 176eb1c5037SNikolas Klauser assert(d.min() <= v && v <= d.max()); 177eb1c5037SNikolas Klauser u.push_back(v); 178eb1c5037SNikolas Klauser } 179eb1c5037SNikolas Klauser double mean = std::accumulate(u.begin(), u.end(), 180eb1c5037SNikolas Klauser double(0)) / u.size(); 181eb1c5037SNikolas Klauser double var = 0; 182eb1c5037SNikolas Klauser double skew = 0; 183eb1c5037SNikolas Klauser double kurtosis = 0; 184eb1c5037SNikolas Klauser for (unsigned i = 0; i < u.size(); ++i) 185eb1c5037SNikolas Klauser { 186eb1c5037SNikolas Klauser double dbl = (u[i] - mean); 187eb1c5037SNikolas Klauser double d2 = sqr(dbl); 188eb1c5037SNikolas Klauser var += d2; 189eb1c5037SNikolas Klauser skew += dbl * d2; 190eb1c5037SNikolas Klauser kurtosis += d2 * d2; 191eb1c5037SNikolas Klauser } 192eb1c5037SNikolas Klauser var /= u.size(); 193eb1c5037SNikolas Klauser double dev = std::sqrt(var); 194eb1c5037SNikolas Klauser skew /= u.size() * dev * var; 195eb1c5037SNikolas Klauser kurtosis /= u.size() * var * var; 196eb1c5037SNikolas Klauser kurtosis -= 3; 197eb1c5037SNikolas Klauser double x_mean = d.k() * (1 - d.p()) / d.p(); 198eb1c5037SNikolas Klauser double x_var = x_mean / d.p(); 199eb1c5037SNikolas Klauser double x_skew = (2 - d.p()) / std::sqrt(d.k() * (1 - d.p())); 200eb1c5037SNikolas Klauser double x_kurtosis = 6. / d.k() + sqr(d.p()) / (d.k() * (1 - d.p())); 201eb1c5037SNikolas Klauser assert(mean == x_mean); 202eb1c5037SNikolas Klauser assert(var == x_var); 203eb1c5037SNikolas Klauser // assert(skew == x_skew); 204eb1c5037SNikolas Klauser (void)skew; (void)x_skew; 205eb1c5037SNikolas Klauser // assert(kurtosis == x_kurtosis); 206eb1c5037SNikolas Klauser (void)kurtosis; (void)x_kurtosis; 207eb1c5037SNikolas Klauser } 208eb1c5037SNikolas Klauser 20907e984bcSLouis Dionne template <class T> 21007e984bcSLouis Dionne void test5() { 21107e984bcSLouis Dionne typedef std::negative_binomial_distribution<T> D; 212eb1c5037SNikolas Klauser typedef std::mt19937 G; 213eb1c5037SNikolas Klauser G g; 21407e984bcSLouis Dionne D d(127, 0.5); 215eb1c5037SNikolas Klauser const int N = 1000000; 21607e984bcSLouis Dionne std::vector<typename D::result_type> u; 217eb1c5037SNikolas Klauser for (int i = 0; i < N; ++i) 218eb1c5037SNikolas Klauser { 21907e984bcSLouis Dionne typename D::result_type v = d(g); 220eb1c5037SNikolas Klauser assert(d.min() <= v && v <= d.max()); 221eb1c5037SNikolas Klauser u.push_back(v); 222eb1c5037SNikolas Klauser } 223eb1c5037SNikolas Klauser double mean = std::accumulate(u.begin(), u.end(), 224eb1c5037SNikolas Klauser double(0)) / u.size(); 225eb1c5037SNikolas Klauser double var = 0; 226eb1c5037SNikolas Klauser double skew = 0; 227eb1c5037SNikolas Klauser double kurtosis = 0; 228eb1c5037SNikolas Klauser for (unsigned i = 0; i < u.size(); ++i) 229eb1c5037SNikolas Klauser { 230eb1c5037SNikolas Klauser double dbl = (u[i] - mean); 231eb1c5037SNikolas Klauser double d2 = sqr(dbl); 232eb1c5037SNikolas Klauser var += d2; 233eb1c5037SNikolas Klauser skew += dbl * d2; 234eb1c5037SNikolas Klauser kurtosis += d2 * d2; 235eb1c5037SNikolas Klauser } 236eb1c5037SNikolas Klauser var /= u.size(); 237eb1c5037SNikolas Klauser double dev = std::sqrt(var); 238eb1c5037SNikolas Klauser skew /= u.size() * dev * var; 239eb1c5037SNikolas Klauser kurtosis /= u.size() * var * var; 240eb1c5037SNikolas Klauser kurtosis -= 3; 241eb1c5037SNikolas Klauser double x_mean = d.k() * (1 - d.p()) / d.p(); 242eb1c5037SNikolas Klauser double x_var = x_mean / d.p(); 243eb1c5037SNikolas Klauser double x_skew = (2 - d.p()) / std::sqrt(d.k() * (1 - d.p())); 244eb1c5037SNikolas Klauser double x_kurtosis = 6. / d.k() + sqr(d.p()) / (d.k() * (1 - d.p())); 245eb1c5037SNikolas Klauser assert(std::abs((mean - x_mean) / x_mean) < 0.01); 246eb1c5037SNikolas Klauser assert(std::abs((var - x_var) / x_var) < 0.01); 24776aa042dSMatt Stephanson assert(std::abs((skew - x_skew) / x_skew) < 0.02); 24876aa042dSMatt Stephanson assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.3); 249eb1c5037SNikolas Klauser } 250eb1c5037SNikolas Klauser 25107e984bcSLouis Dionne template <class T> 25207e984bcSLouis Dionne void test6() { 25307e984bcSLouis Dionne typedef std::negative_binomial_distribution<T> D; 254eb1c5037SNikolas Klauser typedef std::mt19937 G; 255eb1c5037SNikolas Klauser G g; 256eb1c5037SNikolas Klauser D d(1, 0.05); 257eb1c5037SNikolas Klauser const int N = 1000000; 25807e984bcSLouis Dionne std::vector<typename D::result_type> u; 259eb1c5037SNikolas Klauser for (int i = 0; i < N; ++i) 260eb1c5037SNikolas Klauser { 26107e984bcSLouis Dionne typename D::result_type v = d(g); 262eb1c5037SNikolas Klauser assert(d.min() <= v && v <= d.max()); 263eb1c5037SNikolas Klauser u.push_back(v); 264eb1c5037SNikolas Klauser } 265eb1c5037SNikolas Klauser double mean = std::accumulate(u.begin(), u.end(), 266eb1c5037SNikolas Klauser double(0)) / u.size(); 267eb1c5037SNikolas Klauser double var = 0; 268eb1c5037SNikolas Klauser double skew = 0; 269eb1c5037SNikolas Klauser double kurtosis = 0; 270eb1c5037SNikolas Klauser for (unsigned i = 0; i < u.size(); ++i) 271eb1c5037SNikolas Klauser { 272eb1c5037SNikolas Klauser double dbl = (u[i] - mean); 273eb1c5037SNikolas Klauser double d2 = sqr(dbl); 274eb1c5037SNikolas Klauser var += d2; 275eb1c5037SNikolas Klauser skew += dbl * d2; 276eb1c5037SNikolas Klauser kurtosis += d2 * d2; 277eb1c5037SNikolas Klauser } 278eb1c5037SNikolas Klauser var /= u.size(); 279eb1c5037SNikolas Klauser double dev = std::sqrt(var); 280eb1c5037SNikolas Klauser skew /= u.size() * dev * var; 281eb1c5037SNikolas Klauser kurtosis /= u.size() * var * var; 282eb1c5037SNikolas Klauser kurtosis -= 3; 283eb1c5037SNikolas Klauser double x_mean = d.k() * (1 - d.p()) / d.p(); 284eb1c5037SNikolas Klauser double x_var = x_mean / d.p(); 285eb1c5037SNikolas Klauser double x_skew = (2 - d.p()) / std::sqrt(d.k() * (1 - d.p())); 286eb1c5037SNikolas Klauser double x_kurtosis = 6. / d.k() + sqr(d.p()) / (d.k() * (1 - d.p())); 287eb1c5037SNikolas Klauser assert(std::abs((mean - x_mean) / x_mean) < 0.01); 288eb1c5037SNikolas Klauser assert(std::abs((var - x_var) / x_var) < 0.01); 289eb1c5037SNikolas Klauser assert(std::abs((skew - x_skew) / x_skew) < 0.01); 290eb1c5037SNikolas Klauser assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03); 291eb1c5037SNikolas Klauser } 292eb1c5037SNikolas Klauser 29307e984bcSLouis Dionne template <class T> 29407e984bcSLouis Dionne void tests() { 29507e984bcSLouis Dionne test1<T>(); 29607e984bcSLouis Dionne test2<T>(); 29707e984bcSLouis Dionne test3<T>(); 29807e984bcSLouis Dionne test4<T>(); 29907e984bcSLouis Dionne test5<T>(); 30007e984bcSLouis Dionne test6<T>(); 30107e984bcSLouis Dionne } 30207e984bcSLouis Dionne 30307e984bcSLouis Dionne int main(int, char**) { 30407e984bcSLouis Dionne tests<short>(); 30507e984bcSLouis Dionne tests<int>(); 30607e984bcSLouis Dionne tests<long>(); 30707e984bcSLouis Dionne tests<long long>(); 30807e984bcSLouis Dionne 30907e984bcSLouis Dionne tests<unsigned short>(); 31007e984bcSLouis Dionne tests<unsigned int>(); 31107e984bcSLouis Dionne tests<unsigned long>(); 31207e984bcSLouis Dionne tests<unsigned long long>(); 31307e984bcSLouis Dionne 31407e984bcSLouis Dionne #if defined(_LIBCPP_VERSION) // extension 31507e984bcSLouis Dionne // TODO: std::negative_binomial_distribution currently doesn't work reliably with small types. 31607e984bcSLouis Dionne // tests<int8_t>(); 31707e984bcSLouis Dionne // tests<uint8_t>(); 31807e984bcSLouis Dionne #if !defined(TEST_HAS_NO_INT128) 31907e984bcSLouis Dionne tests<__int128_t>(); 32007e984bcSLouis Dionne tests<__uint128_t>(); 32107e984bcSLouis Dionne #endif 32207e984bcSLouis Dionne #endif 323eb1c5037SNikolas Klauser 324eb1c5037SNikolas Klauser return 0; 325eb1c5037SNikolas Klauser } 326