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