eval.pass.cpp revision 14fe08bcb729f076d889de4e38955051bc041923
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
29template <class T>
30inline
31T
32sqr(T x)
33{
34    return x*x;
35}
36
37double
38f(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
43void
44test1()
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 (int 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 (int 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 (int i = 0; i < areas.size(); ++i)
76        areas[i] /= S;
77    for (int i = 0; i < Np+1; ++i)
78        p[i] /= S;
79    for (int 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
96void
97test2()
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 (int 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 (int 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 (int i = 0; i < areas.size(); ++i)
129        areas[i] /= S;
130    for (int i = 0; i < Np+1; ++i)
131        p[i] /= S;
132    for (int 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
149void
150test3()
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 int N = 1000000;
161    std::vector<D::result_type> u;
162    for (int 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 (int 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 (int i = 0; i < areas.size(); ++i)
182        areas[i] /= S;
183    for (int i = 0; i < Np+1; ++i)
184        p[i] /= S;
185    for (int 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
202void
203test4()
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 (int 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 (int 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 (int i = 0; i < areas.size(); ++i)
235        areas[i] /= S;
236    for (int i = 0; i < Np+1; ++i)
237        p[i] /= S;
238    for (int 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            m = (p[k+1] - p[k]) / (b[k+1] - b[k]);
247            bk = b[k];
248            c = (b[k+1]*p[k] - b[k]*p[k+1]) / (b[k+1] - b[k]);
249            kp = k;
250        }
251        assert(std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001);
252    }
253}
254
255void
256test5()
257{
258    typedef std::piecewise_linear_distribution<> D;
259    typedef D::param_type P;
260    typedef std::mt19937_64 G;
261    G g;
262    double b[] = {10, 14};
263    double p[] = {1, 1};
264    const size_t Np = sizeof(p) / sizeof(p[0]) - 1;
265    D d(b, b+Np+1, p);
266    const int N = 1000000;
267    std::vector<D::result_type> u;
268    for (int i = 0; i < N; ++i)
269    {
270        D::result_type v = d(g);
271        assert(d.min() <= v && v < d.max());
272        u.push_back(v);
273    }
274    std::sort(u.begin(), u.end());
275    int kp = -1;
276    double a = std::numeric_limits<double>::quiet_NaN();
277    double m = std::numeric_limits<double>::quiet_NaN();
278    double bk = std::numeric_limits<double>::quiet_NaN();
279    double c = std::numeric_limits<double>::quiet_NaN();
280    std::vector<double> areas(Np);
281    double S = 0;
282    for (int i = 0; i < areas.size(); ++i)
283    {
284        areas[i] = (p[i]+p[i+1])*(b[i+1]-b[i])/2;
285        S += areas[i];
286    }
287    for (int i = 0; i < areas.size(); ++i)
288        areas[i] /= S;
289    for (int i = 0; i < Np+1; ++i)
290        p[i] /= S;
291    for (int i = 0; i < N; ++i)
292    {
293        int k = std::lower_bound(b, b+Np+1, u[i]) - b - 1;
294        if (k != kp)
295        {
296            a = 0;
297            for (int j = 0; j < k; ++j)
298                a += areas[j];
299            m = (p[k+1] - p[k]) / (b[k+1] - b[k]);
300            bk = b[k];
301            c = (b[k+1]*p[k] - b[k]*p[k+1]) / (b[k+1] - b[k]);
302            kp = k;
303        }
304        assert(std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001);
305    }
306}
307
308void
309test6()
310{
311    typedef std::piecewise_linear_distribution<> D;
312    typedef D::param_type P;
313    typedef std::mt19937_64 G;
314    G g;
315    double b[] = {10, 14, 16, 17};
316    double p[] = {25, 62.5, 12.5, 0};
317    const size_t Np = sizeof(p) / sizeof(p[0]) - 1;
318    D d(b, b+Np+1, p);
319    const int N = 1000000;
320    std::vector<D::result_type> u;
321    for (int i = 0; i < N; ++i)
322    {
323        D::result_type v = d(g);
324        assert(d.min() <= v && v < d.max());
325        u.push_back(v);
326    }
327    std::sort(u.begin(), u.end());
328    int kp = -1;
329    double a = std::numeric_limits<double>::quiet_NaN();
330    double m = std::numeric_limits<double>::quiet_NaN();
331    double bk = std::numeric_limits<double>::quiet_NaN();
332    double c = std::numeric_limits<double>::quiet_NaN();
333    std::vector<double> areas(Np);
334    double S = 0;
335    for (int i = 0; i < areas.size(); ++i)
336    {
337        areas[i] = (p[i]+p[i+1])*(b[i+1]-b[i])/2;
338        S += areas[i];
339    }
340    for (int i = 0; i < areas.size(); ++i)
341        areas[i] /= S;
342    for (int i = 0; i < Np+1; ++i)
343        p[i] /= S;
344    for (int i = 0; i < N; ++i)
345    {
346        int k = std::lower_bound(b, b+Np+1, u[i]) - b - 1;
347        if (k != kp)
348        {
349            a = 0;
350            for (int j = 0; j < k; ++j)
351                a += areas[j];
352            m = (p[k+1] - p[k]) / (b[k+1] - b[k]);
353            bk = b[k];
354            c = (b[k+1]*p[k] - b[k]*p[k+1]) / (b[k+1] - b[k]);
355            kp = k;
356        }
357        assert(std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001);
358    }
359}
360
361int main()
362{
363    test1();
364    test2();
365    test3();
366    test4();
367    test5();
368    test6();
369}
370