File: eval.pass.cpp

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (141 lines) | stat: -rw-r--r-- 4,850 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// REQUIRES: long_tests

// <random>

// template<class _IntType = int>
// class uniform_int_distribution

// template<class _URNG> result_type operator()(_URNG& g);

#include <random>
#include <cassert>
#include <climits>
#include <cstddef>
#include <limits>
#include <numeric>
#include <vector>

#include "test_macros.h"

// The __int128 conversions to/from floating point crash on MinGW on x86_64.
// This is fixed in Clang 14 by https://reviews.llvm.org/D110413.
#if defined(__x86_64__) && defined(__MINGW32__) && defined(__clang_major__) && __clang_major__ < 14
 #define TEST_BUGGY_I128_FP
#endif

template <class T>
T sqr(T x) {
    return x * x;
}

template <class ResultType, class EngineType>
void test_statistics(ResultType a, ResultType b) {
    ASSERT_SAME_TYPE(typename std::uniform_int_distribution<ResultType>::result_type, ResultType);

    EngineType g;
    std::uniform_int_distribution<ResultType> dist(a, b);
    assert(dist.a() == a);
    assert(dist.b() == b);
    std::vector<ResultType> u;
    for (int i = 0; i < 10000; ++i) {
        ResultType v = dist(g);
        assert(a <= v && v <= b);
        u.push_back(v);
    }

    // Quick check: The chance of getting *no* hits in any given tenth of the range
    // is (0.9)^10000, or "ultra-astronomically low."
    bool bottom_tenth = false;
    bool top_tenth = false;
    for (std::size_t i = 0; i < u.size(); ++i) {
        bottom_tenth = bottom_tenth || (u[i] <= (a + (b / 10) - (a / 10)));
        top_tenth = top_tenth || (u[i] >= (b - (b / 10) + (a / 10)));
    }
    assert(bottom_tenth);  // ...is populated
    assert(top_tenth);  // ...is populated

    // Now do some more involved statistical math.
    double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
    double var = 0;
    double skew = 0;
    double kurtosis = 0;
    for (std::size_t i = 0; i < u.size(); ++i) {
        double dbl = (u[i] - mean);
        double d2 = dbl * dbl;
        var += d2;
        skew += dbl * d2;
        kurtosis += d2 * d2;
    }
    var /= u.size();
    double dev = std::sqrt(var);
    skew /= u.size() * dev * var;
    kurtosis /= u.size() * var * var;

    double expected_mean = double(a) + double(b)/2 - double(a)/2;
    double expected_var = (sqr(double(b) - double(a) + 1) - 1) / 12;

    double range = double(b) - double(a) + 1.0;
    assert(range > range / 10);  // i.e., it's not infinity

    assert(std::abs(mean - expected_mean) < range / 100);
    assert(std::abs(var - expected_var) < expected_var / 50);
    assert(-0.1 < skew && skew < 0.1);
    assert(1.6 < kurtosis && kurtosis < 2.0);
}

template <class ResultType, class EngineType>
void test_statistics() {
    test_statistics<ResultType, EngineType>(0, std::numeric_limits<ResultType>::max());
}

int main(int, char**)
{
    test_statistics<int, std::minstd_rand0>();
    test_statistics<int, std::minstd_rand>();
    test_statistics<int, std::mt19937>();
    test_statistics<int, std::mt19937_64>();
    test_statistics<int, std::ranlux24_base>();
    test_statistics<int, std::ranlux48_base>();
    test_statistics<int, std::ranlux24>();
    test_statistics<int, std::ranlux48>();
    test_statistics<int, std::knuth_b>();
    test_statistics<int, std::minstd_rand0>(-6, 106);
    test_statistics<int, std::minstd_rand>(5, 100);

    test_statistics<short, std::minstd_rand0>();
    test_statistics<int, std::minstd_rand0>();
    test_statistics<long, std::minstd_rand0>();
    test_statistics<long long, std::minstd_rand0>();

    test_statistics<unsigned short, std::minstd_rand0>();
    test_statistics<unsigned int, std::minstd_rand0>();
    test_statistics<unsigned long, std::minstd_rand0>();
    test_statistics<unsigned long long, std::minstd_rand0>();

    test_statistics<short, std::minstd_rand0>(SHRT_MIN, SHRT_MAX);

#if defined(_LIBCPP_VERSION) // extension
    test_statistics<int8_t, std::minstd_rand0>();
    test_statistics<uint8_t, std::minstd_rand0>();

#if !defined(TEST_HAS_NO_INT128) && !defined(TEST_BUGGY_I128_FP)
    test_statistics<__int128_t, std::minstd_rand0>();
    test_statistics<__uint128_t, std::minstd_rand0>();

    test_statistics<__int128_t, std::minstd_rand0>(-100, 900);
    test_statistics<__int128_t, std::minstd_rand0>(0, UINT64_MAX);
    test_statistics<__int128_t, std::minstd_rand0>(std::numeric_limits<__int128_t>::min(), std::numeric_limits<__int128_t>::max());
    test_statistics<__uint128_t, std::minstd_rand0>(0, UINT64_MAX);
#endif
#endif

    return 0;
}