1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// REQUIRES: long_tests
10
11// <random>
12
13// template<class _IntType = int>
14// class uniform_int_distribution
15
16// template<class _URNG> result_type operator()(_URNG& g);
17
18#include <cassert>
19#include <climits>
20#include <cstddef>
21#include <cstdint>
22#include <limits>
23#include <numeric>
24#include <random>
25#include <vector>
26
27#include "test_macros.h"
28
29template <class T>
30T sqr(T x) {
31 return x * x;
32}
33
34template <class ResultType, class EngineType>
35void test_statistics(ResultType a, ResultType b) {
36 ASSERT_SAME_TYPE(typename std::uniform_int_distribution<ResultType>::result_type, ResultType);
37
38 EngineType g;
39 std::uniform_int_distribution<ResultType> dist(a, b);
40 assert(dist.a() == a);
41 assert(dist.b() == b);
42 std::vector<ResultType> u;
43 for (int i = 0; i < 10000; ++i) {
44 ResultType v = dist(g);
45 assert(a <= v && v <= b);
46 u.push_back(v);
47 }
48
49 // Quick check: The chance of getting *no* hits in any given tenth of the range
50 // is (0.9)^10000, or "ultra-astronomically low."
51 bool bottom_tenth = false;
52 bool top_tenth = false;
53 for (std::size_t i = 0; i < u.size(); ++i) {
54 bottom_tenth = bottom_tenth || (u[i] <= (a + (b / 10) - (a / 10)));
55 top_tenth = top_tenth || (u[i] >= (b - (b / 10) + (a / 10)));
56 }
57 assert(bottom_tenth); // ...is populated
58 assert(top_tenth); // ...is populated
59
60 // Now do some more involved statistical math.
61 double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
62 double var = 0;
63 double skew = 0;
64 double kurtosis = 0;
65 for (std::size_t i = 0; i < u.size(); ++i) {
66 double dbl = (u[i] - mean);
67 double d2 = dbl * dbl;
68 var += d2;
69 skew += dbl * d2;
70 kurtosis += d2 * d2;
71 }
72 var /= u.size();
73 double dev = std::sqrt(x: var);
74 skew /= u.size() * dev * var;
75 kurtosis /= u.size() * var * var;
76
77 double expected_mean = double(a) + double(b)/2 - double(a)/2;
78 double expected_var = (sqr(double(b) - double(a) + 1) - 1) / 12;
79
80 double range = double(b) - double(a) + 1.0;
81 assert(range > range / 10); // i.e., it's not infinity
82
83 assert(std::abs(mean - expected_mean) < range / 100);
84 assert(std::abs(var - expected_var) < expected_var / 50);
85 assert(-0.1 < skew && skew < 0.1);
86 assert(1.6 < kurtosis && kurtosis < 2.0);
87}
88
89template <class ResultType, class EngineType>
90void test_statistics() {
91 test_statistics<ResultType, EngineType>(0, std::numeric_limits<ResultType>::max());
92}
93
94int main(int, char**)
95{
96 test_statistics<int, std::minstd_rand0>();
97 test_statistics<int, std::minstd_rand>();
98 test_statistics<int, std::mt19937>();
99 test_statistics<int, std::mt19937_64>();
100 test_statistics<int, std::ranlux24_base>();
101 test_statistics<int, std::ranlux48_base>();
102 test_statistics<int, std::ranlux24>();
103 test_statistics<int, std::ranlux48>();
104 test_statistics<int, std::knuth_b>();
105 test_statistics<int, std::minstd_rand0>(a: -6, b: 106);
106 test_statistics<int, std::minstd_rand>(a: 5, b: 100);
107
108 test_statistics<short, std::minstd_rand0>();
109 test_statistics<int, std::minstd_rand0>();
110 test_statistics<long, std::minstd_rand0>();
111 test_statistics<long long, std::minstd_rand0>();
112
113 test_statistics<unsigned short, std::minstd_rand0>();
114 test_statistics<unsigned int, std::minstd_rand0>();
115 test_statistics<unsigned long, std::minstd_rand0>();
116 test_statistics<unsigned long long, std::minstd_rand0>();
117
118 test_statistics<short, std::minstd_rand0>(SHRT_MIN, SHRT_MAX);
119
120#if defined(_LIBCPP_VERSION) // extension
121 test_statistics<std::int8_t, std::minstd_rand0>();
122 test_statistics<std::uint8_t, std::minstd_rand0>();
123
124#if !defined(TEST_HAS_NO_INT128)
125 test_statistics<__int128_t, std::minstd_rand0>();
126 test_statistics<__uint128_t, std::minstd_rand0>();
127
128 test_statistics<__int128_t, std::minstd_rand0>(-100, 900);
129 test_statistics<__int128_t, std::minstd_rand0>(0, UINT64_MAX);
130 test_statistics<__int128_t, std::minstd_rand0>(std::numeric_limits<__int128_t>::min(), std::numeric_limits<__int128_t>::max());
131 test_statistics<__uint128_t, std::minstd_rand0>(0, UINT64_MAX);
132#endif
133#endif
134
135 return 0;
136}
137

source code of libcxx/test/std/numerics/rand/rand.dist/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp