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