Home | History | Annotate | Download | only in rand.dist.samp.pconst
      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 RealType = double>
     15 // class piecewise_constant_distribution
     16 
     17 // template<class _URNG> result_type operator()(_URNG& g);
     18 
     19 #include <random>
     20 #include <vector>
     21 #include <iterator>
     22 #include <numeric>
     23 #include <cassert>
     24 
     25 template <class T>
     26 inline
     27 T
     28 sqr(T x)
     29 {
     30     return x*x;
     31 }
     32 
     33 int main()
     34 {
     35     {
     36         typedef std::piecewise_constant_distribution<> D;
     37         typedef std::mt19937_64 G;
     38         G g;
     39         double b[] = {10, 14, 16, 17};
     40         double p[] = {25, 62.5, 12.5};
     41         const size_t Np = sizeof(p) / sizeof(p[0]);
     42         D d(b, b+Np+1, p);
     43         const int N = 1000000;
     44         std::vector<D::result_type> u;
     45         for (int i = 0; i < N; ++i)
     46         {
     47             D::result_type v = d(g);
     48             assert(d.min() <= v && v < d.max());
     49             u.push_back(v);
     50         }
     51         std::vector<double> prob(std::begin(p), std::end(p));
     52         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
     53         for (int i = 0; i < prob.size(); ++i)
     54             prob[i] /= s;
     55         std::sort(u.begin(), u.end());
     56         for (int i = 0; i < Np; ++i)
     57         {
     58             typedef std::vector<D::result_type>::iterator I;
     59             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
     60             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
     61             const size_t Ni = ub - lb;
     62             if (prob[i] == 0)
     63                 assert(Ni == 0);
     64             else
     65             {
     66                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
     67                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
     68                 double var = 0;
     69                 double skew = 0;
     70                 double kurtosis = 0;
     71                 for (I j = lb; j != ub; ++j)
     72                 {
     73                     double d = (*j - mean);
     74                     double d2 = sqr(d);
     75                     var += d2;
     76                     skew += d * d2;
     77                     kurtosis += d2 * d2;
     78                 }
     79                 var /= Ni;
     80                 double dev = std::sqrt(var);
     81                 skew /= Ni * dev * var;
     82                 kurtosis /= Ni * var * var;
     83                 kurtosis -= 3;
     84                 double x_mean = (b[i+1] + b[i]) / 2;
     85                 double x_var = sqr(b[i+1] - b[i]) / 12;
     86                 double x_skew = 0;
     87                 double x_kurtosis = -6./5;
     88                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
     89                 assert(std::abs((var - x_var) / x_var) < 0.01);
     90                 assert(std::abs(skew - x_skew) < 0.01);
     91                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
     92             }
     93         }
     94     }
     95     {
     96         typedef std::piecewise_constant_distribution<> D;
     97         typedef std::mt19937_64 G;
     98         G g;
     99         double b[] = {10, 14, 16, 17};
    100         double p[] = {0, 62.5, 12.5};
    101         const size_t Np = sizeof(p) / sizeof(p[0]);
    102         D d(b, b+Np+1, p);
    103         const int N = 1000000;
    104         std::vector<D::result_type> u;
    105         for (int i = 0; i < N; ++i)
    106         {
    107             D::result_type v = d(g);
    108             assert(d.min() <= v && v < d.max());
    109             u.push_back(v);
    110         }
    111         std::vector<double> prob(std::begin(p), std::end(p));
    112         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    113         for (int i = 0; i < prob.size(); ++i)
    114             prob[i] /= s;
    115         std::sort(u.begin(), u.end());
    116         for (int i = 0; i < Np; ++i)
    117         {
    118             typedef std::vector<D::result_type>::iterator I;
    119             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    120             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    121             const size_t Ni = ub - lb;
    122             if (prob[i] == 0)
    123                 assert(Ni == 0);
    124             else
    125             {
    126                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    127                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    128                 double var = 0;
    129                 double skew = 0;
    130                 double kurtosis = 0;
    131                 for (I j = lb; j != ub; ++j)
    132                 {
    133                     double d = (*j - mean);
    134                     double d2 = sqr(d);
    135                     var += d2;
    136                     skew += d * d2;
    137                     kurtosis += d2 * d2;
    138                 }
    139                 var /= Ni;
    140                 double dev = std::sqrt(var);
    141                 skew /= Ni * dev * var;
    142                 kurtosis /= Ni * var * var;
    143                 kurtosis -= 3;
    144                 double x_mean = (b[i+1] + b[i]) / 2;
    145                 double x_var = sqr(b[i+1] - b[i]) / 12;
    146                 double x_skew = 0;
    147                 double x_kurtosis = -6./5;
    148                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    149                 assert(std::abs((var - x_var) / x_var) < 0.01);
    150                 assert(std::abs(skew - x_skew) < 0.01);
    151                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    152             }
    153         }
    154     }
    155     {
    156         typedef std::piecewise_constant_distribution<> D;
    157         typedef std::mt19937_64 G;
    158         G g;
    159         double b[] = {10, 14, 16, 17};
    160         double p[] = {25, 0, 12.5};
    161         const size_t Np = sizeof(p) / sizeof(p[0]);
    162         D d(b, b+Np+1, p);
    163         const int N = 1000000;
    164         std::vector<D::result_type> u;
    165         for (int i = 0; i < N; ++i)
    166         {
    167             D::result_type v = d(g);
    168             assert(d.min() <= v && v < d.max());
    169             u.push_back(v);
    170         }
    171         std::vector<double> prob(std::begin(p), std::end(p));
    172         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    173         for (int i = 0; i < prob.size(); ++i)
    174             prob[i] /= s;
    175         std::sort(u.begin(), u.end());
    176         for (int i = 0; i < Np; ++i)
    177         {
    178             typedef std::vector<D::result_type>::iterator I;
    179             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    180             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    181             const size_t Ni = ub - lb;
    182             if (prob[i] == 0)
    183                 assert(Ni == 0);
    184             else
    185             {
    186                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    187                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    188                 double var = 0;
    189                 double skew = 0;
    190                 double kurtosis = 0;
    191                 for (I j = lb; j != ub; ++j)
    192                 {
    193                     double d = (*j - mean);
    194                     double d2 = sqr(d);
    195                     var += d2;
    196                     skew += d * d2;
    197                     kurtosis += d2 * d2;
    198                 }
    199                 var /= Ni;
    200                 double dev = std::sqrt(var);
    201                 skew /= Ni * dev * var;
    202                 kurtosis /= Ni * var * var;
    203                 kurtosis -= 3;
    204                 double x_mean = (b[i+1] + b[i]) / 2;
    205                 double x_var = sqr(b[i+1] - b[i]) / 12;
    206                 double x_skew = 0;
    207                 double x_kurtosis = -6./5;
    208                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    209                 assert(std::abs((var - x_var) / x_var) < 0.01);
    210                 assert(std::abs(skew - x_skew) < 0.01);
    211                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    212             }
    213         }
    214     }
    215     {
    216         typedef std::piecewise_constant_distribution<> D;
    217         typedef std::mt19937_64 G;
    218         G g;
    219         double b[] = {10, 14, 16, 17};
    220         double p[] = {25, 62.5, 0};
    221         const size_t Np = sizeof(p) / sizeof(p[0]);
    222         D d(b, b+Np+1, p);
    223         const int N = 1000000;
    224         std::vector<D::result_type> u;
    225         for (int i = 0; i < N; ++i)
    226         {
    227             D::result_type v = d(g);
    228             assert(d.min() <= v && v < d.max());
    229             u.push_back(v);
    230         }
    231         std::vector<double> prob(std::begin(p), std::end(p));
    232         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    233         for (int i = 0; i < prob.size(); ++i)
    234             prob[i] /= s;
    235         std::sort(u.begin(), u.end());
    236         for (int i = 0; i < Np; ++i)
    237         {
    238             typedef std::vector<D::result_type>::iterator I;
    239             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    240             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    241             const size_t Ni = ub - lb;
    242             if (prob[i] == 0)
    243                 assert(Ni == 0);
    244             else
    245             {
    246                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    247                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    248                 double var = 0;
    249                 double skew = 0;
    250                 double kurtosis = 0;
    251                 for (I j = lb; j != ub; ++j)
    252                 {
    253                     double d = (*j - mean);
    254                     double d2 = sqr(d);
    255                     var += d2;
    256                     skew += d * d2;
    257                     kurtosis += d2 * d2;
    258                 }
    259                 var /= Ni;
    260                 double dev = std::sqrt(var);
    261                 skew /= Ni * dev * var;
    262                 kurtosis /= Ni * var * var;
    263                 kurtosis -= 3;
    264                 double x_mean = (b[i+1] + b[i]) / 2;
    265                 double x_var = sqr(b[i+1] - b[i]) / 12;
    266                 double x_skew = 0;
    267                 double x_kurtosis = -6./5;
    268                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    269                 assert(std::abs((var - x_var) / x_var) < 0.01);
    270                 assert(std::abs(skew - x_skew) < 0.01);
    271                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    272             }
    273         }
    274     }
    275     {
    276         typedef std::piecewise_constant_distribution<> D;
    277         typedef std::mt19937_64 G;
    278         G g;
    279         double b[] = {10, 14, 16, 17};
    280         double p[] = {25, 0, 0};
    281         const size_t Np = sizeof(p) / sizeof(p[0]);
    282         D d(b, b+Np+1, p);
    283         const int N = 100000;
    284         std::vector<D::result_type> u;
    285         for (int i = 0; i < N; ++i)
    286         {
    287             D::result_type v = d(g);
    288             assert(d.min() <= v && v < d.max());
    289             u.push_back(v);
    290         }
    291         std::vector<double> prob(std::begin(p), std::end(p));
    292         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    293         for (int i = 0; i < prob.size(); ++i)
    294             prob[i] /= s;
    295         std::sort(u.begin(), u.end());
    296         for (int i = 0; i < Np; ++i)
    297         {
    298             typedef std::vector<D::result_type>::iterator I;
    299             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    300             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    301             const size_t Ni = ub - lb;
    302             if (prob[i] == 0)
    303                 assert(Ni == 0);
    304             else
    305             {
    306                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    307                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    308                 double var = 0;
    309                 double skew = 0;
    310                 double kurtosis = 0;
    311                 for (I j = lb; j != ub; ++j)
    312                 {
    313                     double d = (*j - mean);
    314                     double d2 = sqr(d);
    315                     var += d2;
    316                     skew += d * d2;
    317                     kurtosis += d2 * d2;
    318                 }
    319                 var /= Ni;
    320                 double dev = std::sqrt(var);
    321                 skew /= Ni * dev * var;
    322                 kurtosis /= Ni * var * var;
    323                 kurtosis -= 3;
    324                 double x_mean = (b[i+1] + b[i]) / 2;
    325                 double x_var = sqr(b[i+1] - b[i]) / 12;
    326                 double x_skew = 0;
    327                 double x_kurtosis = -6./5;
    328                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    329                 assert(std::abs((var - x_var) / x_var) < 0.01);
    330                 assert(std::abs(skew - x_skew) < 0.01);
    331                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    332             }
    333         }
    334     }
    335     {
    336         typedef std::piecewise_constant_distribution<> D;
    337         typedef std::mt19937_64 G;
    338         G g;
    339         double b[] = {10, 14, 16, 17};
    340         double p[] = {0, 25, 0};
    341         const size_t Np = sizeof(p) / sizeof(p[0]);
    342         D d(b, b+Np+1, p);
    343         const int N = 100000;
    344         std::vector<D::result_type> u;
    345         for (int i = 0; i < N; ++i)
    346         {
    347             D::result_type v = d(g);
    348             assert(d.min() <= v && v < d.max());
    349             u.push_back(v);
    350         }
    351         std::vector<double> prob(std::begin(p), std::end(p));
    352         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    353         for (int i = 0; i < prob.size(); ++i)
    354             prob[i] /= s;
    355         std::sort(u.begin(), u.end());
    356         for (int i = 0; i < Np; ++i)
    357         {
    358             typedef std::vector<D::result_type>::iterator I;
    359             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    360             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    361             const size_t Ni = ub - lb;
    362             if (prob[i] == 0)
    363                 assert(Ni == 0);
    364             else
    365             {
    366                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    367                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    368                 double var = 0;
    369                 double skew = 0;
    370                 double kurtosis = 0;
    371                 for (I j = lb; j != ub; ++j)
    372                 {
    373                     double d = (*j - mean);
    374                     double d2 = sqr(d);
    375                     var += d2;
    376                     skew += d * d2;
    377                     kurtosis += d2 * d2;
    378                 }
    379                 var /= Ni;
    380                 double dev = std::sqrt(var);
    381                 skew /= Ni * dev * var;
    382                 kurtosis /= Ni * var * var;
    383                 kurtosis -= 3;
    384                 double x_mean = (b[i+1] + b[i]) / 2;
    385                 double x_var = sqr(b[i+1] - b[i]) / 12;
    386                 double x_skew = 0;
    387                 double x_kurtosis = -6./5;
    388                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    389                 assert(std::abs((var - x_var) / x_var) < 0.01);
    390                 assert(std::abs(skew - x_skew) < 0.01);
    391                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    392             }
    393         }
    394     }
    395     {
    396         typedef std::piecewise_constant_distribution<> D;
    397         typedef std::mt19937_64 G;
    398         G g;
    399         double b[] = {10, 14, 16, 17};
    400         double p[] = {0, 0, 1};
    401         const size_t Np = sizeof(p) / sizeof(p[0]);
    402         D d(b, b+Np+1, p);
    403         const int N = 100000;
    404         std::vector<D::result_type> u;
    405         for (int i = 0; i < N; ++i)
    406         {
    407             D::result_type v = d(g);
    408             assert(d.min() <= v && v < d.max());
    409             u.push_back(v);
    410         }
    411         std::vector<double> prob(std::begin(p), std::end(p));
    412         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    413         for (int i = 0; i < prob.size(); ++i)
    414             prob[i] /= s;
    415         std::sort(u.begin(), u.end());
    416         for (int i = 0; i < Np; ++i)
    417         {
    418             typedef std::vector<D::result_type>::iterator I;
    419             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    420             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    421             const size_t Ni = ub - lb;
    422             if (prob[i] == 0)
    423                 assert(Ni == 0);
    424             else
    425             {
    426                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    427                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    428                 double var = 0;
    429                 double skew = 0;
    430                 double kurtosis = 0;
    431                 for (I j = lb; j != ub; ++j)
    432                 {
    433                     double d = (*j - mean);
    434                     double d2 = sqr(d);
    435                     var += d2;
    436                     skew += d * d2;
    437                     kurtosis += d2 * d2;
    438                 }
    439                 var /= Ni;
    440                 double dev = std::sqrt(var);
    441                 skew /= Ni * dev * var;
    442                 kurtosis /= Ni * var * var;
    443                 kurtosis -= 3;
    444                 double x_mean = (b[i+1] + b[i]) / 2;
    445                 double x_var = sqr(b[i+1] - b[i]) / 12;
    446                 double x_skew = 0;
    447                 double x_kurtosis = -6./5;
    448                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    449                 assert(std::abs((var - x_var) / x_var) < 0.01);
    450                 assert(std::abs(skew - x_skew) < 0.01);
    451                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    452             }
    453         }
    454     }
    455     {
    456         typedef std::piecewise_constant_distribution<> D;
    457         typedef std::mt19937_64 G;
    458         G g;
    459         double b[] = {10, 14, 16};
    460         double p[] = {75, 25};
    461         const size_t Np = sizeof(p) / sizeof(p[0]);
    462         D d(b, b+Np+1, p);
    463         const int N = 100000;
    464         std::vector<D::result_type> u;
    465         for (int i = 0; i < N; ++i)
    466         {
    467             D::result_type v = d(g);
    468             assert(d.min() <= v && v < d.max());
    469             u.push_back(v);
    470         }
    471         std::vector<double> prob(std::begin(p), std::end(p));
    472         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    473         for (int i = 0; i < prob.size(); ++i)
    474             prob[i] /= s;
    475         std::sort(u.begin(), u.end());
    476         for (int i = 0; i < Np; ++i)
    477         {
    478             typedef std::vector<D::result_type>::iterator I;
    479             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    480             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    481             const size_t Ni = ub - lb;
    482             if (prob[i] == 0)
    483                 assert(Ni == 0);
    484             else
    485             {
    486                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    487                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    488                 double var = 0;
    489                 double skew = 0;
    490                 double kurtosis = 0;
    491                 for (I j = lb; j != ub; ++j)
    492                 {
    493                     double d = (*j - mean);
    494                     double d2 = sqr(d);
    495                     var += d2;
    496                     skew += d * d2;
    497                     kurtosis += d2 * d2;
    498                 }
    499                 var /= Ni;
    500                 double dev = std::sqrt(var);
    501                 skew /= Ni * dev * var;
    502                 kurtosis /= Ni * var * var;
    503                 kurtosis -= 3;
    504                 double x_mean = (b[i+1] + b[i]) / 2;
    505                 double x_var = sqr(b[i+1] - b[i]) / 12;
    506                 double x_skew = 0;
    507                 double x_kurtosis = -6./5;
    508                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    509                 assert(std::abs((var - x_var) / x_var) < 0.01);
    510                 assert(std::abs(skew - x_skew) < 0.01);
    511                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    512             }
    513         }
    514     }
    515     {
    516         typedef std::piecewise_constant_distribution<> D;
    517         typedef std::mt19937_64 G;
    518         G g;
    519         double b[] = {10, 14, 16};
    520         double p[] = {0, 25};
    521         const size_t Np = sizeof(p) / sizeof(p[0]);
    522         D d(b, b+Np+1, p);
    523         const int N = 100000;
    524         std::vector<D::result_type> u;
    525         for (int i = 0; i < N; ++i)
    526         {
    527             D::result_type v = d(g);
    528             assert(d.min() <= v && v < d.max());
    529             u.push_back(v);
    530         }
    531         std::vector<double> prob(std::begin(p), std::end(p));
    532         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    533         for (int i = 0; i < prob.size(); ++i)
    534             prob[i] /= s;
    535         std::sort(u.begin(), u.end());
    536         for (int i = 0; i < Np; ++i)
    537         {
    538             typedef std::vector<D::result_type>::iterator I;
    539             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    540             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    541             const size_t Ni = ub - lb;
    542             if (prob[i] == 0)
    543                 assert(Ni == 0);
    544             else
    545             {
    546                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    547                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    548                 double var = 0;
    549                 double skew = 0;
    550                 double kurtosis = 0;
    551                 for (I j = lb; j != ub; ++j)
    552                 {
    553                     double d = (*j - mean);
    554                     double d2 = sqr(d);
    555                     var += d2;
    556                     skew += d * d2;
    557                     kurtosis += d2 * d2;
    558                 }
    559                 var /= Ni;
    560                 double dev = std::sqrt(var);
    561                 skew /= Ni * dev * var;
    562                 kurtosis /= Ni * var * var;
    563                 kurtosis -= 3;
    564                 double x_mean = (b[i+1] + b[i]) / 2;
    565                 double x_var = sqr(b[i+1] - b[i]) / 12;
    566                 double x_skew = 0;
    567                 double x_kurtosis = -6./5;
    568                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    569                 assert(std::abs((var - x_var) / x_var) < 0.01);
    570                 assert(std::abs(skew - x_skew) < 0.01);
    571                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    572             }
    573         }
    574     }
    575     {
    576         typedef std::piecewise_constant_distribution<> D;
    577         typedef std::mt19937_64 G;
    578         G g;
    579         double b[] = {10, 14, 16};
    580         double p[] = {1, 0};
    581         const size_t Np = sizeof(p) / sizeof(p[0]);
    582         D d(b, b+Np+1, p);
    583         const int N = 100000;
    584         std::vector<D::result_type> u;
    585         for (int i = 0; i < N; ++i)
    586         {
    587             D::result_type v = d(g);
    588             assert(d.min() <= v && v < d.max());
    589             u.push_back(v);
    590         }
    591         std::vector<double> prob(std::begin(p), std::end(p));
    592         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    593         for (int i = 0; i < prob.size(); ++i)
    594             prob[i] /= s;
    595         std::sort(u.begin(), u.end());
    596         for (int i = 0; i < Np; ++i)
    597         {
    598             typedef std::vector<D::result_type>::iterator I;
    599             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    600             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    601             const size_t Ni = ub - lb;
    602             if (prob[i] == 0)
    603                 assert(Ni == 0);
    604             else
    605             {
    606                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    607                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    608                 double var = 0;
    609                 double skew = 0;
    610                 double kurtosis = 0;
    611                 for (I j = lb; j != ub; ++j)
    612                 {
    613                     double d = (*j - mean);
    614                     double d2 = sqr(d);
    615                     var += d2;
    616                     skew += d * d2;
    617                     kurtosis += d2 * d2;
    618                 }
    619                 var /= Ni;
    620                 double dev = std::sqrt(var);
    621                 skew /= Ni * dev * var;
    622                 kurtosis /= Ni * var * var;
    623                 kurtosis -= 3;
    624                 double x_mean = (b[i+1] + b[i]) / 2;
    625                 double x_var = sqr(b[i+1] - b[i]) / 12;
    626                 double x_skew = 0;
    627                 double x_kurtosis = -6./5;
    628                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    629                 assert(std::abs((var - x_var) / x_var) < 0.01);
    630                 assert(std::abs(skew - x_skew) < 0.01);
    631                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    632             }
    633         }
    634     }
    635     {
    636         typedef std::piecewise_constant_distribution<> D;
    637         typedef std::mt19937_64 G;
    638         G g;
    639         double b[] = {10, 14};
    640         double p[] = {1};
    641         const size_t Np = sizeof(p) / sizeof(p[0]);
    642         D d(b, b+Np+1, p);
    643         const int N = 100000;
    644         std::vector<D::result_type> u;
    645         for (int i = 0; i < N; ++i)
    646         {
    647             D::result_type v = d(g);
    648             assert(d.min() <= v && v < d.max());
    649             u.push_back(v);
    650         }
    651         std::vector<double> prob(std::begin(p), std::end(p));
    652         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
    653         for (int i = 0; i < prob.size(); ++i)
    654             prob[i] /= s;
    655         std::sort(u.begin(), u.end());
    656         for (int i = 0; i < Np; ++i)
    657         {
    658             typedef std::vector<D::result_type>::iterator I;
    659             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
    660             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
    661             const size_t Ni = ub - lb;
    662             if (prob[i] == 0)
    663                 assert(Ni == 0);
    664             else
    665             {
    666                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
    667                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
    668                 double var = 0;
    669                 double skew = 0;
    670                 double kurtosis = 0;
    671                 for (I j = lb; j != ub; ++j)
    672                 {
    673                     double d = (*j - mean);
    674                     double d2 = sqr(d);
    675                     var += d2;
    676                     skew += d * d2;
    677                     kurtosis += d2 * d2;
    678                 }
    679                 var /= Ni;
    680                 double dev = std::sqrt(var);
    681                 skew /= Ni * dev * var;
    682                 kurtosis /= Ni * var * var;
    683                 kurtosis -= 3;
    684                 double x_mean = (b[i+1] + b[i]) / 2;
    685                 double x_var = sqr(b[i+1] - b[i]) / 12;
    686                 double x_skew = 0;
    687                 double x_kurtosis = -6./5;
    688                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
    689                 assert(std::abs((var - x_var) / x_var) < 0.01);
    690                 assert(std::abs(skew - x_skew) < 0.01);
    691                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
    692             }
    693         }
    694     }
    695 }
    696