brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.3 KiB · 6a81dd0 Raw
329 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// REQUIRES: long_tests10 11// <random>12 13// template<class IntType = int>14// class geometric_distribution15 16// template<class _URNG> result_type operator()(_URNG& g);17 18#include <random>19#include <cassert>20#include <cmath>21#include <cstdint>22#include <numeric>23#include <vector>24 25#include "test_macros.h"26 27template <class T>28T sqr(T x) {29    return x * x;30}31 32void test_small_inputs() {33  std::mt19937 engine;34  std::geometric_distribution<std::int16_t> distribution(5.45361e-311);35  typedef std::geometric_distribution<std::int16_t>::result_type result_type;36  for (int i = 0; i < 1000; ++i) {37    volatile result_type res = distribution(engine);38    ((void)res);39  }40}41 42template <class T>43void test1() {44    typedef std::geometric_distribution<T> D;45    typedef std::mt19937 G;46    G g;47    D d(.03125);48    const int N = 1000000;49    std::vector<typename D::result_type> u;50    for (int i = 0; i < N; ++i)51    {52        typename D::result_type v = d(g);53        assert(d.min() <= v && v <= d.max());54        u.push_back(v);55    }56    double mean = std::accumulate(u.begin(), u.end(),57                                          double(0)) / u.size();58    double var = 0;59    double skew = 0;60    double kurtosis = 0;61    for (unsigned i = 0; i < u.size(); ++i)62    {63        double dbl = (u[i] - mean);64        double d2 = sqr(dbl);65        var += d2;66        skew += dbl * d2;67        kurtosis += d2 * d2;68    }69    var /= u.size();70    double dev = std::sqrt(var);71    skew /= u.size() * dev * var;72    kurtosis /= u.size() * var * var;73    kurtosis -= 3;74    double x_mean = (1 - d.p()) / d.p();75    double x_var = x_mean / d.p();76    double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));77    double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());78    assert(std::abs((mean - x_mean) / x_mean) < 0.01);79    assert(std::abs((var - x_var) / x_var) < 0.01);80    assert(std::abs((skew - x_skew) / x_skew) < 0.01);81    assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);82}83 84template <class T>85void test2() {86    typedef std::geometric_distribution<T> D;87    typedef std::mt19937 G;88    G g;89    D d(0.05);90    const int N = 1000000;91    std::vector<typename D::result_type> u;92    for (int i = 0; i < N; ++i)93    {94        typename D::result_type v = d(g);95        assert(d.min() <= v && v <= d.max());96        u.push_back(v);97    }98    double mean = std::accumulate(u.begin(), u.end(),99                                          double(0)) / u.size();100    double var = 0;101    double skew = 0;102    double kurtosis = 0;103    for (unsigned i = 0; i < u.size(); ++i)104    {105        double dbl = (u[i] - mean);106        double d2 = sqr(dbl);107        var += d2;108        skew += dbl * d2;109        kurtosis += d2 * d2;110    }111    var /= u.size();112    double dev = std::sqrt(var);113    skew /= u.size() * dev * var;114    kurtosis /= u.size() * var * var;115    kurtosis -= 3;116    double x_mean = (1 - d.p()) / d.p();117    double x_var = x_mean / d.p();118    double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));119    double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());120    assert(std::abs((mean - x_mean) / x_mean) < 0.01);121    assert(std::abs((var - x_var) / x_var) < 0.01);122    assert(std::abs((skew - x_skew) / x_skew) < 0.01);123    assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);124}125 126template <class T>127void test3() {128    typedef std::geometric_distribution<T> D;129    typedef std::minstd_rand G;130    G g;131    D d(.25);132    const int N = 1000000;133    std::vector<typename D::result_type> u;134    for (int i = 0; i < N; ++i)135    {136        typename D::result_type v = d(g);137        assert(d.min() <= v && v <= d.max());138        u.push_back(v);139    }140    double mean = std::accumulate(u.begin(), u.end(),141                                          double(0)) / u.size();142    double var = 0;143    double skew = 0;144    double kurtosis = 0;145    for (unsigned i = 0; i < u.size(); ++i)146    {147        double dbl = (u[i] - mean);148        double d2 = sqr(dbl);149        var += d2;150        skew += dbl * d2;151        kurtosis += d2 * d2;152    }153    var /= u.size();154    double dev = std::sqrt(var);155    skew /= u.size() * dev * var;156    kurtosis /= u.size() * var * var;157    kurtosis -= 3;158    double x_mean = (1 - d.p()) / d.p();159    double x_var = x_mean / d.p();160    double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));161    double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());162    assert(std::abs((mean - x_mean) / x_mean) < 0.01);163    assert(std::abs((var - x_var) / x_var) < 0.01);164    assert(std::abs((skew - x_skew) / x_skew) < 0.01);165    assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);166}167 168template <class T>169void test4() {170    typedef std::geometric_distribution<T> D;171    typedef std::mt19937 G;172    G g;173    D d(0.5);174    const int N = 1000000;175    std::vector<typename D::result_type> u;176    for (int i = 0; i < N; ++i)177    {178        typename D::result_type v = d(g);179        assert(d.min() <= v && v <= d.max());180        u.push_back(v);181    }182    double mean = std::accumulate(u.begin(), u.end(),183                                          double(0)) / u.size();184    double var = 0;185    double skew = 0;186    double kurtosis = 0;187    for (unsigned i = 0; i < u.size(); ++i)188    {189        double dbl = (u[i] - mean);190        double d2 = sqr(dbl);191        var += d2;192        skew += dbl * d2;193        kurtosis += d2 * d2;194    }195    var /= u.size();196    double dev = std::sqrt(var);197    skew /= u.size() * dev * var;198    kurtosis /= u.size() * var * var;199    kurtosis -= 3;200    double x_mean = (1 - d.p()) / d.p();201    double x_var = x_mean / d.p();202    double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));203    double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());204    assert(std::abs((mean - x_mean) / x_mean) < 0.01);205    assert(std::abs((var - x_var) / x_var) < 0.01);206    assert(std::abs((skew - x_skew) / x_skew) < 0.01);207    assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);208}209 210template <class T>211void test5() {212    typedef std::geometric_distribution<T> D;213    typedef std::mt19937 G;214    G g;215    D d(0.75);216    const int N = 1000000;217    std::vector<typename D::result_type> u;218    for (int i = 0; i < N; ++i)219    {220        typename D::result_type v = d(g);221        assert(d.min() <= v && v <= d.max());222        u.push_back(v);223    }224    double mean = std::accumulate(u.begin(), u.end(),225                                          double(0)) / u.size();226    double var = 0;227    double skew = 0;228    double kurtosis = 0;229    for (unsigned i = 0; i < u.size(); ++i)230    {231        double dbl = (u[i] - mean);232        double d2 = sqr(dbl);233        var += d2;234        skew += dbl * d2;235        kurtosis += d2 * d2;236    }237    var /= u.size();238    double dev = std::sqrt(var);239    skew /= u.size() * dev * var;240    kurtosis /= u.size() * var * var;241    kurtosis -= 3;242    double x_mean = (1 - d.p()) / d.p();243    double x_var = x_mean / d.p();244    double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));245    double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());246    assert(std::abs((mean - x_mean) / x_mean) < 0.01);247    assert(std::abs((var - x_var) / x_var) < 0.01);248    assert(std::abs((skew - x_skew) / x_skew) < 0.01);249    assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);250}251 252template <class T>253void test6() {254    typedef std::geometric_distribution<T> D;255    typedef std::mt19937 G;256    G g;257    D d(0.96875);258    const int N = 1000000;259    std::vector<typename D::result_type> u;260    for (int i = 0; i < N; ++i)261    {262        typename D::result_type v = d(g);263        assert(d.min() <= v && v <= d.max());264        u.push_back(v);265    }266    double mean = std::accumulate(u.begin(), u.end(),267                                          double(0)) / u.size();268    double var = 0;269    double skew = 0;270    double kurtosis = 0;271    for (unsigned i = 0; i < u.size(); ++i)272    {273        double dbl = (u[i] - mean);274        double d2 = sqr(dbl);275        var += d2;276        skew += dbl * d2;277        kurtosis += d2 * d2;278    }279    var /= u.size();280    double dev = std::sqrt(var);281    skew /= u.size() * dev * var;282    kurtosis /= u.size() * var * var;283    kurtosis -= 3;284    double x_mean = (1 - d.p()) / d.p();285    double x_var = x_mean / d.p();286    double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));287    double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());288    assert(std::abs((mean - x_mean) / x_mean) < 0.02);289    assert(std::abs((var - x_var) / x_var) < 0.02);290    assert(std::abs((skew - x_skew) / x_skew) < 0.01);291    assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.02);292}293 294template <class T>295void tests() {296    test1<T>();297    test2<T>();298    test3<T>();299    test4<T>();300    test5<T>();301    test6<T>();302}303 304int main(int, char**) {305    test_small_inputs();306 307    tests<short>();308    tests<int>();309    tests<long>();310    tests<long long>();311 312    tests<unsigned short>();313    tests<unsigned int>();314    tests<unsigned long>();315    tests<unsigned long long>();316 317#if defined(_LIBCPP_VERSION) // extension318    // TODO: std::geometric_distribution currently doesn't work reliably with small types.319    // tests<int8_t>();320    // tests<uint8_t>();321#if !defined(TEST_HAS_NO_INT128)322    tests<__int128_t>();323    tests<__uint128_t>();324#endif325#endif326 327    return 0;328}329