Home | History | Annotate | Download | only in rand.dist.bern.bin
      1 //===----------------------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // REQUIRES: long_tests
     11 
     12 // <random>
     13 
     14 // template<class IntType = int>
     15 // class binomial_distribution
     16 
     17 // template<class _URNG> result_type operator()(_URNG& g);
     18 
     19 #include <random>
     20 #include <numeric>
     21 #include <vector>
     22 #include <cassert>
     23 
     24 template <class T>
     25 inline
     26 T
     27 sqr(T x)
     28 {
     29     return x * x;
     30 }
     31 
     32 void
     33 test1()
     34 {
     35     typedef std::binomial_distribution<> D;
     36     typedef std::mt19937_64 G;
     37     G g;
     38     D d(5, .75);
     39     const int N = 1000000;
     40     std::vector<D::result_type> u;
     41     for (int i = 0; i < N; ++i)
     42     {
     43         D::result_type v = d(g);
     44         assert(d.min() <= v && v <= d.max());
     45         u.push_back(v);
     46     }
     47     double mean = std::accumulate(u.begin(), u.end(),
     48                                           double(0)) / u.size();
     49     double var = 0;
     50     double skew = 0;
     51     double kurtosis = 0;
     52     for (unsigned i = 0; i < u.size(); ++i)
     53     {
     54         double dbl = (u[i] - mean);
     55         double d2 = sqr(dbl);
     56         var += d2;
     57         skew += dbl * d2;
     58         kurtosis += d2 * d2;
     59     }
     60     var /= u.size();
     61     double dev = std::sqrt(var);
     62     skew /= u.size() * dev * var;
     63     kurtosis /= u.size() * var * var;
     64     kurtosis -= 3;
     65     double x_mean = d.t() * d.p();
     66     double x_var = x_mean*(1-d.p());
     67     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
     68     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
     69     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
     70     assert(std::abs((var - x_var) / x_var) < 0.01);
     71     assert(std::abs((skew - x_skew) / x_skew) < 0.01);
     72     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.04);
     73 }
     74 
     75 void
     76 test2()
     77 {
     78     typedef std::binomial_distribution<> D;
     79     typedef std::mt19937 G;
     80     G g;
     81     D d(30, .03125);
     82     const int N = 100000;
     83     std::vector<D::result_type> u;
     84     for (int i = 0; i < N; ++i)
     85     {
     86         D::result_type v = d(g);
     87         assert(d.min() <= v && v <= d.max());
     88         u.push_back(v);
     89     }
     90     double mean = std::accumulate(u.begin(), u.end(),
     91                                           double(0)) / u.size();
     92     double var = 0;
     93     double skew = 0;
     94     double kurtosis = 0;
     95     for (unsigned i = 0; i < u.size(); ++i)
     96     {
     97         double dbl = (u[i] - mean);
     98         double d2 = sqr(dbl);
     99         var += d2;
    100         skew += dbl * d2;
    101         kurtosis += d2 * d2;
    102     }
    103     var /= u.size();
    104     double dev = std::sqrt(var);
    105     skew /= u.size() * dev * var;
    106     kurtosis /= u.size() * var * var;
    107     kurtosis -= 3;
    108     double x_mean = d.t() * d.p();
    109     double x_var = x_mean*(1-d.p());
    110     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
    111     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
    112     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    113     assert(std::abs((var - x_var) / x_var) < 0.01);
    114     assert(std::abs((skew - x_skew) / x_skew) < 0.01);
    115     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    116 }
    117 
    118 void
    119 test3()
    120 {
    121     typedef std::binomial_distribution<> D;
    122     typedef std::mt19937 G;
    123     G g;
    124     D d(40, .25);
    125     const int N = 100000;
    126     std::vector<D::result_type> u;
    127     for (int i = 0; i < N; ++i)
    128     {
    129         D::result_type v = d(g);
    130         assert(d.min() <= v && v <= d.max());
    131         u.push_back(v);
    132     }
    133     double mean = std::accumulate(u.begin(), u.end(),
    134                                           double(0)) / u.size();
    135     double var = 0;
    136     double skew = 0;
    137     double kurtosis = 0;
    138     for (unsigned i = 0; i < u.size(); ++i)
    139     {
    140         double dbl = (u[i] - mean);
    141         double d2 = sqr(dbl);
    142         var += d2;
    143         skew += dbl * d2;
    144         kurtosis += d2 * d2;
    145     }
    146     var /= u.size();
    147     double dev = std::sqrt(var);
    148     skew /= u.size() * dev * var;
    149     kurtosis /= u.size() * var * var;
    150     kurtosis -= 3;
    151     double x_mean = d.t() * d.p();
    152     double x_var = x_mean*(1-d.p());
    153     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
    154     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
    155     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    156     assert(std::abs((var - x_var) / x_var) < 0.01);
    157     assert(std::abs((skew - x_skew) / x_skew) < 0.03);
    158     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.3);
    159 }
    160 
    161 void
    162 test4()
    163 {
    164     typedef std::binomial_distribution<> D;
    165     typedef std::mt19937 G;
    166     G g;
    167     D d(40, 0);
    168     const int N = 100000;
    169     std::vector<D::result_type> u;
    170     for (int i = 0; i < N; ++i)
    171     {
    172         D::result_type v = d(g);
    173         assert(d.min() <= v && v <= d.max());
    174         u.push_back(v);
    175     }
    176     double mean = std::accumulate(u.begin(), u.end(),
    177                                           double(0)) / u.size();
    178     double var = 0;
    179     double skew = 0;
    180     double kurtosis = 0;
    181     for (unsigned i = 0; i < u.size(); ++i)
    182     {
    183         double dbl = (u[i] - mean);
    184         double d2 = sqr(dbl);
    185         var += d2;
    186         skew += dbl * d2;
    187         kurtosis += d2 * d2;
    188     }
    189     var /= u.size();
    190     //double dev = std::sqrt(var);
    191     // In this case:
    192     //   skew     computes to 0./0. == nan
    193     //   kurtosis computes to 0./0. == nan
    194     //   x_skew     == inf
    195     //   x_kurtosis == inf
    196     //   These tests are commented out because UBSan warns about division by 0
    197 //    skew /= u.size() * dev * var;
    198 //    kurtosis /= u.size() * var * var;
    199 //    kurtosis -= 3;
    200     double x_mean = d.t() * d.p();
    201     double x_var = x_mean*(1-d.p());
    202 //    double x_skew = (1-2*d.p()) / std::sqrt(x_var);
    203 //    double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
    204     assert(mean == x_mean);
    205     assert(var == x_var);
    206 //    assert(skew == x_skew);
    207 //    assert(kurtosis == x_kurtosis);
    208 }
    209 
    210 void
    211 test5()
    212 {
    213     typedef std::binomial_distribution<> D;
    214     typedef std::mt19937 G;
    215     G g;
    216     D d(40, 1);
    217     const int N = 100000;
    218     std::vector<D::result_type> u;
    219     for (int i = 0; i < N; ++i)
    220     {
    221         D::result_type v = d(g);
    222         assert(d.min() <= v && v <= d.max());
    223         u.push_back(v);
    224     }
    225     double mean = std::accumulate(u.begin(), u.end(),
    226                                           double(0)) / u.size();
    227     double var = 0;
    228     double skew = 0;
    229     double kurtosis = 0;
    230     for (unsigned i = 0; i < u.size(); ++i)
    231     {
    232         double dbl = (u[i] - mean);
    233         double d2 = sqr(dbl);
    234         var += d2;
    235         skew += dbl * d2;
    236         kurtosis += d2 * d2;
    237     }
    238     var /= u.size();
    239 //    double dev = std::sqrt(var);
    240     // In this case:
    241     //   skew     computes to 0./0. == nan
    242     //   kurtosis computes to 0./0. == nan
    243     //   x_skew     == -inf
    244     //   x_kurtosis == inf
    245     //   These tests are commented out because UBSan warns about division by 0
    246 //    skew /= u.size() * dev * var;
    247 //    kurtosis /= u.size() * var * var;
    248 //    kurtosis -= 3;
    249     double x_mean = d.t() * d.p();
    250     double x_var = x_mean*(1-d.p());
    251 //    double x_skew = (1-2*d.p()) / std::sqrt(x_var);
    252 //    double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
    253     assert(mean == x_mean);
    254     assert(var == x_var);
    255 //    assert(skew == x_skew);
    256 //    assert(kurtosis == x_kurtosis);
    257 }
    258 
    259 void
    260 test6()
    261 {
    262     typedef std::binomial_distribution<> D;
    263     typedef std::mt19937 G;
    264     G g;
    265     D d(400, 0.5);
    266     const int N = 100000;
    267     std::vector<D::result_type> u;
    268     for (int i = 0; i < N; ++i)
    269     {
    270         D::result_type v = d(g);
    271         assert(d.min() <= v && v <= d.max());
    272         u.push_back(v);
    273     }
    274     double mean = std::accumulate(u.begin(), u.end(),
    275                                           double(0)) / u.size();
    276     double var = 0;
    277     double skew = 0;
    278     double kurtosis = 0;
    279     for (unsigned i = 0; i < u.size(); ++i)
    280     {
    281         double dbl = (u[i] - mean);
    282         double d2 = sqr(dbl);
    283         var += d2;
    284         skew += dbl * d2;
    285         kurtosis += d2 * d2;
    286     }
    287     var /= u.size();
    288     double dev = std::sqrt(var);
    289     skew /= u.size() * dev * var;
    290     kurtosis /= u.size() * var * var;
    291     kurtosis -= 3;
    292     double x_mean = d.t() * d.p();
    293     double x_var = x_mean*(1-d.p());
    294     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
    295     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
    296     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    297     assert(std::abs((var - x_var) / x_var) < 0.01);
    298     assert(std::abs(skew - x_skew) < 0.01);
    299     assert(std::abs(kurtosis - x_kurtosis) < 0.01);
    300 }
    301 
    302 void
    303 test7()
    304 {
    305     typedef std::binomial_distribution<> D;
    306     typedef std::mt19937 G;
    307     G g;
    308     D d(1, 0.5);
    309     const int N = 100000;
    310     std::vector<D::result_type> u;
    311     for (int i = 0; i < N; ++i)
    312     {
    313         D::result_type v = d(g);
    314         assert(d.min() <= v && v <= d.max());
    315         u.push_back(v);
    316     }
    317     double mean = std::accumulate(u.begin(), u.end(),
    318                                           double(0)) / u.size();
    319     double var = 0;
    320     double skew = 0;
    321     double kurtosis = 0;
    322     for (unsigned i = 0; i < u.size(); ++i)
    323     {
    324         double dbl = (u[i] - mean);
    325         double d2 = sqr(dbl);
    326         var += d2;
    327         skew += dbl * d2;
    328         kurtosis += d2 * d2;
    329     }
    330     var /= u.size();
    331     double dev = std::sqrt(var);
    332     skew /= u.size() * dev * var;
    333     kurtosis /= u.size() * var * var;
    334     kurtosis -= 3;
    335     double x_mean = d.t() * d.p();
    336     double x_var = x_mean*(1-d.p());
    337     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
    338     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
    339     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    340     assert(std::abs((var - x_var) / x_var) < 0.01);
    341     assert(std::abs(skew - x_skew) < 0.01);
    342     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    343 }
    344 
    345 void
    346 test8()
    347 {
    348     const int N = 100000;
    349     std::mt19937 gen1;
    350     std::mt19937 gen2;
    351 
    352     std::binomial_distribution<>         dist1(5, 0.1);
    353     std::binomial_distribution<unsigned> dist2(5, 0.1);
    354 
    355     for(int i = 0; i < N; ++i) {
    356         int r1 = dist1(gen1);
    357         unsigned r2 = dist2(gen2);
    358         assert(r1 >= 0);
    359         assert(static_cast<unsigned>(r1) == r2);
    360     }
    361 }
    362 
    363 void
    364 test9()
    365 {
    366     typedef std::binomial_distribution<> D;
    367     typedef std::mt19937 G;
    368     G g;
    369     D d(0, 0.005);
    370     const int N = 100000;
    371     std::vector<D::result_type> u;
    372     for (int i = 0; i < N; ++i)
    373     {
    374         D::result_type v = d(g);
    375         assert(d.min() <= v && v <= d.max());
    376         u.push_back(v);
    377     }
    378     double mean = std::accumulate(u.begin(), u.end(),
    379                                           double(0)) / u.size();
    380     double var = 0;
    381     double skew = 0;
    382     double kurtosis = 0;
    383     for (unsigned i = 0; i < u.size(); ++i)
    384     {
    385         double dbl = (u[i] - mean);
    386         double d2 = sqr(dbl);
    387         var += d2;
    388         skew += dbl * d2;
    389         kurtosis += d2 * d2;
    390     }
    391     var /= u.size();
    392 //    double dev = std::sqrt(var);
    393     // In this case:
    394     //   skew     computes to 0./0. == nan
    395     //   kurtosis computes to 0./0. == nan
    396     //   x_skew     == inf
    397     //   x_kurtosis == inf
    398     //   These tests are commented out because UBSan warns about division by 0
    399 //    skew /= u.size() * dev * var;
    400 //    kurtosis /= u.size() * var * var;
    401 //    kurtosis -= 3;
    402     double x_mean = d.t() * d.p();
    403     double x_var = x_mean*(1-d.p());
    404 //    double x_skew = (1-2*d.p()) / std::sqrt(x_var);
    405 //    double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
    406     assert(mean == x_mean);
    407     assert(var == x_var);
    408 //    assert(skew == x_skew);
    409 //    assert(kurtosis == x_kurtosis);
    410 }
    411 
    412 void
    413 test10()
    414 {
    415     typedef std::binomial_distribution<> D;
    416     typedef std::mt19937 G;
    417     G g;
    418     D d(0, 0);
    419     const int N = 100000;
    420     std::vector<D::result_type> u;
    421     for (int i = 0; i < N; ++i)
    422     {
    423         D::result_type v = d(g);
    424         assert(d.min() <= v && v <= d.max());
    425         u.push_back(v);
    426     }
    427     double mean = std::accumulate(u.begin(), u.end(),
    428                                           double(0)) / u.size();
    429     double var = 0;
    430     double skew = 0;
    431     double kurtosis = 0;
    432     for (unsigned i = 0; i < u.size(); ++i)
    433     {
    434         double dbl = (u[i] - mean);
    435         double d2 = sqr(dbl);
    436         var += d2;
    437         skew += dbl * d2;
    438         kurtosis += d2 * d2;
    439     }
    440     var /= u.size();
    441 //    double dev = std::sqrt(var);
    442     // In this case:
    443     //   skew     computes to 0./0. == nan
    444     //   kurtosis computes to 0./0. == nan
    445     //   x_skew     == inf
    446     //   x_kurtosis == inf
    447     //   These tests are commented out because UBSan warns about division by 0
    448 //    skew /= u.size() * dev * var;
    449 //    kurtosis /= u.size() * var * var;
    450 //    kurtosis -= 3;
    451     double x_mean = d.t() * d.p();
    452     double x_var = x_mean*(1-d.p());
    453 //    double x_skew = (1-2*d.p()) / std::sqrt(x_var);
    454 //    double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
    455     assert(mean == x_mean);
    456     assert(var == x_var);
    457 //    assert(skew == x_skew);
    458 //    assert(kurtosis == x_kurtosis);
    459 }
    460 
    461 void
    462 test11()
    463 {
    464     typedef std::binomial_distribution<> D;
    465     typedef std::mt19937 G;
    466     G g;
    467     D d(0, 1);
    468     const int N = 100000;
    469     std::vector<D::result_type> u;
    470     for (int i = 0; i < N; ++i)
    471     {
    472         D::result_type v = d(g);
    473         assert(d.min() <= v && v <= d.max());
    474         u.push_back(v);
    475     }
    476     double mean = std::accumulate(u.begin(), u.end(),
    477                                           double(0)) / u.size();
    478     double var = 0;
    479     double skew = 0;
    480     double kurtosis = 0;
    481     for (unsigned i = 0; i < u.size(); ++i)
    482     {
    483         double dbl = (u[i] - mean);
    484         double d2 = sqr(dbl);
    485         var += d2;
    486         skew += dbl * d2;
    487         kurtosis += d2 * d2;
    488     }
    489     var /= u.size();
    490 //    double dev = std::sqrt(var);
    491     // In this case:
    492     //   skew     computes to 0./0. == nan
    493     //   kurtosis computes to 0./0. == nan
    494     //   x_skew     == -inf
    495     //   x_kurtosis == inf
    496     //   These tests are commented out because UBSan warns about division by 0
    497 //    skew /= u.size() * dev * var;
    498 //    kurtosis /= u.size() * var * var;
    499 //    kurtosis -= 3;
    500     double x_mean = d.t() * d.p();
    501     double x_var = x_mean*(1-d.p());
    502 //    double x_skew = (1-2*d.p()) / std::sqrt(x_var);
    503 //    double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
    504     assert(mean == x_mean);
    505     assert(var == x_var);
    506 //    assert(skew == x_skew);
    507 //    assert(kurtosis == x_kurtosis);
    508 }
    509 
    510 int main()
    511 {
    512     test1();
    513     test2();
    514     test3();
    515     test4();
    516     test5();
    517     test6();
    518     test7();
    519     test8();
    520     test9();
    521     test10();
    522     test11();
    523 }
    524