Home | History | Annotate | Download | only in rand.dist.samp.plinear
      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_linear_distribution
     16 
     17 // template<class _URNG> result_type operator()(_URNG& g);
     18 
     19 #include <iostream>
     20 
     21 #include <random>
     22 #include <algorithm>
     23 #include <vector>
     24 #include <iterator>
     25 #include <numeric>
     26 #include <cassert>
     27 #include <limits>
     28 
     29 template <class T>
     30 inline
     31 T
     32 sqr(T x)
     33 {
     34     return x*x;
     35 }
     36 
     37 double
     38 f(double x, double a, double m, double b, double c)
     39 {
     40     return a + m*(sqr(x) - sqr(b))/2 + c*(x-b);
     41 }
     42 
     43 void
     44 test1()
     45 {
     46     typedef std::piecewise_linear_distribution<> D;
     47     typedef std::mt19937_64 G;
     48     G g;
     49     double b[] = {10, 14, 16, 17};
     50     double p[] = {0, 1, 1, 0};
     51     const size_t Np = sizeof(p) / sizeof(p[0]) - 1;
     52     D d(b, b+Np+1, p);
     53     const int N = 1000000;
     54     std::vector<D::result_type> u;
     55     for (size_t i = 0; i < N; ++i)
     56     {
     57         D::result_type v = d(g);
     58         assert(d.min() <= v && v < d.max());
     59         u.push_back(v);
     60     }
     61     std::sort(u.begin(), u.end());
     62     int kp = -1;
     63     double a = std::numeric_limits<double>::quiet_NaN();
     64     double m = std::numeric_limits<double>::quiet_NaN();
     65     double bk = std::numeric_limits<double>::quiet_NaN();
     66     double c = std::numeric_limits<double>::quiet_NaN();
     67     std::vector<double> areas(Np);
     68     double S = 0;
     69     for (size_t i = 0; i < areas.size(); ++i)
     70     {
     71         areas[i] = (p[i]+p[i+1])*(b[i+1]-b[i])/2;
     72         S += areas[i];
     73     }
     74     for (size_t i = 0; i < areas.size(); ++i)
     75         areas[i] /= S;
     76     for (size_t i = 0; i < Np+1; ++i)
     77         p[i] /= S;
     78     for (size_t i = 0; i < N; ++i)
     79     {
     80         int k = std::lower_bound(b, b+Np+1, u[i]) - b - 1;
     81         if (k != kp)
     82         {
     83             a = 0;
     84             for (int j = 0; j < k; ++j)
     85                 a += areas[j];
     86             m = (p[k+1] - p[k]) / (b[k+1] - b[k]);
     87             bk = b[k];
     88             c = (b[k+1]*p[k] - b[k]*p[k+1]) / (b[k+1] - b[k]);
     89             kp = k;
     90         }
     91         assert(std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001);
     92     }
     93 }
     94 
     95 void
     96 test2()
     97 {
     98     typedef std::piecewise_linear_distribution<> D;
     99     typedef std::mt19937_64 G;
    100     G g;
    101     double b[] = {10, 14, 16, 17};
    102     double p[] = {0, 0, 1, 0};
    103     const size_t Np = sizeof(p) / sizeof(p[0]) - 1;
    104     D d(b, b+Np+1, p);
    105     const int N = 1000000;
    106     std::vector<D::result_type> u;
    107     for (size_t i = 0; i < N; ++i)
    108     {
    109         D::result_type v = d(g);
    110         assert(d.min() <= v && v < d.max());
    111         u.push_back(v);
    112     }
    113     std::sort(u.begin(), u.end());
    114     int kp = -1;
    115     double a = std::numeric_limits<double>::quiet_NaN();
    116     double m = std::numeric_limits<double>::quiet_NaN();
    117     double bk = std::numeric_limits<double>::quiet_NaN();
    118     double c = std::numeric_limits<double>::quiet_NaN();
    119     std::vector<double> areas(Np);
    120     double S = 0;
    121     for (size_t i = 0; i < areas.size(); ++i)
    122     {
    123         areas[i] = (p[i]+p[i+1])*(b[i+1]-b[i])/2;
    124         S += areas[i];
    125     }
    126     for (size_t i = 0; i < areas.size(); ++i)
    127         areas[i] /= S;
    128     for (size_t i = 0; i < Np+1; ++i)
    129         p[i] /= S;
    130     for (size_t i = 0; i < N; ++i)
    131     {
    132         int k = std::lower_bound(b, b+Np+1, u[i]) - b - 1;
    133         if (k != kp)
    134         {
    135             a = 0;
    136             for (int j = 0; j < k; ++j)
    137                 a += areas[j];
    138             m = (p[k+1] - p[k]) / (b[k+1] - b[k]);
    139             bk = b[k];
    140             c = (b[k+1]*p[k] - b[k]*p[k+1]) / (b[k+1] - b[k]);
    141             kp = k;
    142         }
    143         assert(std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001);
    144     }
    145 }
    146 
    147 void
    148 test3()
    149 {
    150     typedef std::piecewise_linear_distribution<> D;
    151     typedef std::mt19937_64 G;
    152     G g;
    153     double b[] = {10, 14, 16, 17};
    154     double p[] = {1, 0, 0, 0};
    155     const size_t Np = sizeof(p) / sizeof(p[0]) - 1;
    156     D d(b, b+Np+1, p);
    157     const size_t N = 1000000;
    158     std::vector<D::result_type> u;
    159     for (size_t 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     std::sort(u.begin(), u.end());
    166     int kp = -1;
    167     double a = std::numeric_limits<double>::quiet_NaN();
    168     double m = std::numeric_limits<double>::quiet_NaN();
    169     double bk = std::numeric_limits<double>::quiet_NaN();
    170     double c = std::numeric_limits<double>::quiet_NaN();
    171     std::vector<double> areas(Np);
    172     double S = 0;
    173     for (size_t i = 0; i < areas.size(); ++i)
    174     {
    175         areas[i] = (p[i]+p[i+1])*(b[i+1]-b[i])/2;
    176         S += areas[i];
    177     }
    178     for (size_t i = 0; i < areas.size(); ++i)
    179         areas[i] /= S;
    180     for (size_t i = 0; i < Np+1; ++i)
    181         p[i] /= S;
    182     for (size_t i = 0; i < N; ++i)
    183     {
    184         int k = std::lower_bound(b, b+Np+1, u[i]) - b - 1;
    185         if (k != kp)
    186         {
    187             a = 0;
    188             for (int j = 0; j < k; ++j)
    189                 a += areas[j];
    190             m = (p[k+1] - p[k]) / (b[k+1] - b[k]);
    191             bk = b[k];
    192             c = (b[k+1]*p[k] - b[k]*p[k+1]) / (b[k+1] - b[k]);
    193             kp = k;
    194         }
    195         assert(std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001);
    196     }
    197 }
    198 
    199 void
    200 test4()
    201 {
    202     typedef std::piecewise_linear_distribution<> D;
    203     typedef std::mt19937_64 G;
    204     G g;
    205     double b[] = {10, 14, 16};
    206     double p[] = {0, 1, 0};
    207     const size_t Np = sizeof(p) / sizeof(p[0]) - 1;
    208     D d(b, b+Np+1, p);
    209     const int N = 1000000;
    210     std::vector<D::result_type> u;
    211     for (size_t i = 0; i < N; ++i)
    212     {
    213         D::result_type v = d(g);
    214         assert(d.min() <= v && v < d.max());
    215         u.push_back(v);
    216     }
    217     std::sort(u.begin(), u.end());
    218     int kp = -1;
    219     double a = std::numeric_limits<double>::quiet_NaN();
    220     double m = std::numeric_limits<double>::quiet_NaN();
    221     double bk = std::numeric_limits<double>::quiet_NaN();
    222     double c = std::numeric_limits<double>::quiet_NaN();
    223     std::vector<double> areas(Np);
    224     double S = 0;
    225     for (size_t i = 0; i < areas.size(); ++i)
    226     {
    227         areas[i] = (p[i]+p[i+1])*(b[i+1]-b[i])/2;
    228         S += areas[i];
    229     }
    230     for (size_t i = 0; i < areas.size(); ++i)
    231         areas[i] /= S;
    232     for (size_t i = 0; i < Np+1; ++i)
    233         p[i] /= S;
    234     for (size_t i = 0; i < N; ++i)
    235     {
    236         int k = std::lower_bound(b, b+Np+1, u[i]) - b - 1;
    237         if (k != kp)
    238         {
    239             a = 0;
    240             for (int j = 0; j < k; ++j)
    241                 a += areas[j];
    242             assert(k < static_cast<int>(Np));
    243             m = (p[k+1] - p[k]) / (b[k+1] - b[k]);
    244             bk = b[k];
    245             c = (b[k+1]*p[k] - b[k]*p[k+1]) / (b[k+1] - b[k]);
    246             kp = k;
    247         }
    248         assert(std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001);
    249     }
    250 }
    251 
    252 void
    253 test5()
    254 {
    255     typedef std::piecewise_linear_distribution<> D;
    256     typedef std::mt19937_64 G;
    257     G g;
    258     double b[] = {10, 14};
    259     double p[] = {1, 1};
    260     const size_t Np = sizeof(p) / sizeof(p[0]) - 1;
    261     D d(b, b+Np+1, p);
    262     const int N = 1000000;
    263     std::vector<D::result_type> u;
    264     for (size_t i = 0; i < N; ++i)
    265     {
    266         D::result_type v = d(g);
    267         assert(d.min() <= v && v < d.max());
    268         u.push_back(v);
    269     }
    270     std::sort(u.begin(), u.end());
    271     int kp = -1;
    272     double a = std::numeric_limits<double>::quiet_NaN();
    273     double m = std::numeric_limits<double>::quiet_NaN();
    274     double bk = std::numeric_limits<double>::quiet_NaN();
    275     double c = std::numeric_limits<double>::quiet_NaN();
    276     std::vector<double> areas(Np);
    277     double S = 0;
    278     for (size_t i = 0; i < areas.size(); ++i)
    279     {
    280         assert(i < Np);
    281         areas[i] = (p[i]+p[i+1])*(b[i+1]-b[i])/2;
    282         S += areas[i];
    283     }
    284     for (size_t i = 0; i < areas.size(); ++i)
    285         areas[i] /= S;
    286     for (size_t i = 0; i < Np+1; ++i)
    287         p[i] /= S;
    288     for (size_t i = 0; i < N; ++i)
    289     {
    290         int k = std::lower_bound(b, b+Np+1, u[i]) - b - 1;
    291         if (k != kp)
    292         {
    293             a = 0;
    294             for (int j = 0; j < k; ++j)
    295                 a += areas[j];
    296             assert(k < static_cast<int>(Np));
    297             m = (p[k+1] - p[k]) / (b[k+1] - b[k]);
    298             bk = b[k];
    299             c = (b[k+1]*p[k] - b[k]*p[k+1]) / (b[k+1] - b[k]);
    300             kp = k;
    301         }
    302         assert(std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001);
    303     }
    304 }
    305 
    306 void
    307 test6()
    308 {
    309     typedef std::piecewise_linear_distribution<> D;
    310     typedef std::mt19937_64 G;
    311     G g;
    312     double b[] = {10, 14, 16, 17};
    313     double p[] = {25, 62.5, 12.5, 0};
    314     const size_t Np = sizeof(p) / sizeof(p[0]) - 1;
    315     D d(b, b+Np+1, p);
    316     const int N = 1000000;
    317     std::vector<D::result_type> u;
    318     for (size_t i = 0; i < N; ++i)
    319     {
    320         D::result_type v = d(g);
    321         assert(d.min() <= v && v < d.max());
    322         u.push_back(v);
    323     }
    324     std::sort(u.begin(), u.end());
    325     int kp = -1;
    326     double a = std::numeric_limits<double>::quiet_NaN();
    327     double m = std::numeric_limits<double>::quiet_NaN();
    328     double bk = std::numeric_limits<double>::quiet_NaN();
    329     double c = std::numeric_limits<double>::quiet_NaN();
    330     std::vector<double> areas(Np);
    331     double S = 0;
    332     for (size_t i = 0; i < areas.size(); ++i)
    333     {
    334         areas[i] = (p[i]+p[i+1])*(b[i+1]-b[i])/2;
    335         S += areas[i];
    336     }
    337     for (size_t i = 0; i < areas.size(); ++i)
    338         areas[i] /= S;
    339     for (size_t i = 0; i < Np+1; ++i)
    340         p[i] /= S;
    341     for (size_t i = 0; i < N; ++i)
    342     {
    343         int k = std::lower_bound(b, b+Np+1, u[i]) - b - 1;
    344         if (k != kp)
    345         {
    346             a = 0;
    347             for (int j = 0; j < k; ++j)
    348                 a += areas[j];
    349             m = (p[k+1] - p[k]) / (b[k+1] - b[k]);
    350             bk = b[k];
    351             c = (b[k+1]*p[k] - b[k]*p[k+1]) / (b[k+1] - b[k]);
    352             kp = k;
    353         }
    354         assert(std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001);
    355     }
    356 }
    357 
    358 int main()
    359 {
    360     test1();
    361     test2();
    362     test3();
    363     test4();
    364     test5();
    365     test6();
    366 }
    367