1 module tests.drift;
2 
3 import tests.utils;
4 import vivaldi;
5 
6 @("drift")
7 unittest {
8     import std.algorithm : map, max, min, sum;
9     import std.format;
10     import std.math;
11     import std.random;
12 
13     // Stable seed for random unitvectors.
14     rndGen().seed(1);
15 
16     alias N = Node!(Coordinate!2, 20);
17 
18     immutable double dist = 0.5;
19     immutable size_t n = 4;
20 
21     N[n] nodes = new N[n];
22 
23     nodes[0].coordinate.vector = [ 0.0, 0.0 ];
24     nodes[1].coordinate.vector = [ 0.0, dist ];
25     nodes[2].coordinate.vector = [ dist, dist ];
26     nodes[3].coordinate.vector = [ dist, 0.0 ];
27 
28     auto matrix = matrix!n;
29 
30     // The nodes are laid out like this so the distances are all
31     // equal, except for the diagonal:
32     //
33     // (1)  <- dist ->  (2)
34     //
35     //  | <- dist        |
36     //  |                |
37     //  |        dist -> |
38     //
39     // (0)  <- dist ->  (3)
40     for (size_t i = 0; i < n; i++) {
41         for (size_t j = i + 1; j < n; j++) {
42             double rtt = dist;
43 
44             if (i % 2 == 0 && j % 2 == 0) {
45                 rtt *= SQRT2;
46             }
47 
48             matrix[i][j] = rtt;
49             matrix[j][i] = rtt;
50         }
51     }
52 
53     double centerError() {
54         auto mini = nodes[0].coordinate;
55         auto maxi = nodes[0].coordinate;
56 
57         for (size_t i = 1; i < n; i++) {
58             auto coord = nodes[i].coordinate;
59 
60             foreach (j, v; coord.vector) {
61                 mini.vector[j] = min(mini.vector[j], v);
62                 maxi.vector[j] = max(maxi.vector[j], v);
63             }
64         }
65 
66         auto mid = new double[2];
67 
68         for (size_t i = 0; i < 2; i++) {
69             mid[i] = mini.vector[i] + (maxi.vector[i] - mini.vector[i]) / 2;
70         }
71 
72         return sqrt(sum(mid.map!(a => a * a)));
73     }
74 
75     simulate!(N, 3, n)(nodes, matrix, 1000);
76     double baseline = centerError();
77 
78     simulate!(N, 3, n)(nodes, matrix, 10000);
79 
80     double err = centerError();
81     assert(err <= 0.81 * baseline, format("err=%s baseline=%s", err, baseline));
82 }