1
2
3
4
5 package trace
6
7 import (
8 "math"
9 "math/rand"
10 "testing"
11 )
12
13 func TestMUD(t *testing.T) {
14
15
16 rnd := rand.New(rand.NewSource(42))
17 mass := 0.0
18 var mud mud
19 for i := 0; i < 100; i++ {
20 area, l, r := rnd.Float64(), rnd.Float64(), rnd.Float64()
21 if rnd.Intn(10) == 0 {
22 r = l
23 }
24 t.Log(l, r, area)
25 mud.add(l, r, area)
26 mass += area
27
28
29 hmass := 0.0
30 for _, val := range mud.hist {
31 hmass += val
32 }
33 if !aeq(mass, hmass) {
34 t.Fatalf("want mass %g, got %g", mass, hmass)
35 }
36
37
38 for j := 0.0; j < mass; j += mass * 0.099 {
39 mud.setTrackMass(j)
40 l, u, ok := mud.approxInvCumulativeSum()
41 inv, ok2 := mud.invCumulativeSum(j)
42 if !ok || !ok2 {
43 t.Fatalf("inverse cumulative sum failed: approx %v, exact %v", ok, ok2)
44 }
45 if !(l <= inv && inv < u) {
46 t.Fatalf("inverse(%g) = %g, not ∈ [%g, %g)", j, inv, l, u)
47 }
48 }
49 }
50 }
51
52 func TestMUDTracking(t *testing.T) {
53
54
55 rnd := rand.New(rand.NewSource(42))
56 const uniforms = 100
57 for trackMass := 0.0; trackMass < uniforms; trackMass += uniforms / 50 {
58 var mud mud
59 mass := 0.0
60 mud.setTrackMass(trackMass)
61 for i := 0; i < uniforms; i++ {
62 area, l, r := rnd.Float64(), rnd.Float64(), rnd.Float64()
63 mud.add(l, r, area)
64 mass += area
65 l, u, ok := mud.approxInvCumulativeSum()
66 inv, ok2 := mud.invCumulativeSum(trackMass)
67
68 if mass < trackMass {
69 if ok {
70 t.Errorf("approx(%g) = [%g, %g), but mass = %g", trackMass, l, u, mass)
71 }
72 if ok2 {
73 t.Errorf("exact(%g) = %g, but mass = %g", trackMass, inv, mass)
74 }
75 } else {
76 if !ok {
77 t.Errorf("approx(%g) failed, but mass = %g", trackMass, mass)
78 }
79 if !ok2 {
80 t.Errorf("exact(%g) failed, but mass = %g", trackMass, mass)
81 }
82 if ok && ok2 && !(l <= inv && inv < u) {
83 t.Errorf("inverse(%g) = %g, not ∈ [%g, %g)", trackMass, inv, l, u)
84 }
85 }
86 }
87 }
88 }
89
90
91
92
93 func aeq(x, y float64) bool {
94 if x < 0 && y < 0 {
95 x, y = -x, -y
96 }
97 const digits = 8
98 factor := 1 - math.Pow(10, -digits+1)
99 return x*factor <= y && y*factor <= x
100 }
101
View as plain text