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