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