| // Copyright 2017 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package trace | |
| import ( | |
| "math/rand" | |
| "testing" | |
| ) | |
| func TestMUD(t *testing.T) { | |
| // Insert random uniforms and check histogram mass and | |
| // cumulative sum approximations. | |
| rnd := rand.New(rand.NewSource(42)) | |
| mass := 0.0 | |
| var mud mud | |
| for i := 0; i < 100; i++ { | |
| area, l, r := rnd.Float64(), rnd.Float64(), rnd.Float64() | |
| if rnd.Intn(10) == 0 { | |
| r = l | |
| } | |
| t.Log(l, r, area) | |
| mud.add(l, r, area) | |
| mass += area | |
| // Check total histogram weight. | |
| hmass := 0.0 | |
| for _, val := range mud.hist { | |
| hmass += val | |
| } | |
| if !aeq(mass, hmass) { | |
| t.Fatalf("want mass %g, got %g", mass, hmass) | |
| } | |
| // Check inverse cumulative sum approximations. | |
| for j := 0.0; j < mass; j += mass * 0.099 { | |
| mud.setTrackMass(j) | |
| l, u, ok := mud.approxInvCumulativeSum() | |
| inv, ok2 := mud.invCumulativeSum(j) | |
| if !ok || !ok2 { | |
| t.Fatalf("inverse cumulative sum failed: approx %v, exact %v", ok, ok2) | |
| } | |
| if !(l <= inv && inv < u) { | |
| t.Fatalf("inverse(%g) = %g, not ∈ [%g, %g)", j, inv, l, u) | |
| } | |
| } | |
| } | |
| } | |
| func TestMUDTracking(t *testing.T) { | |
| // Test that the tracked mass is tracked correctly across | |
| // updates. | |
| rnd := rand.New(rand.NewSource(42)) | |
| const uniforms = 100 | |
| for trackMass := 0.0; trackMass < uniforms; trackMass += uniforms / 50 { | |
| var mud mud | |
| mass := 0.0 | |
| mud.setTrackMass(trackMass) | |
| for i := 0; i < uniforms; i++ { | |
| area, l, r := rnd.Float64(), rnd.Float64(), rnd.Float64() | |
| mud.add(l, r, area) | |
| mass += area | |
| l, u, ok := mud.approxInvCumulativeSum() | |
| inv, ok2 := mud.invCumulativeSum(trackMass) | |
| if mass < trackMass { | |
| if ok { | |
| t.Errorf("approx(%g) = [%g, %g), but mass = %g", trackMass, l, u, mass) | |
| } | |
| if ok2 { | |
| t.Errorf("exact(%g) = %g, but mass = %g", trackMass, inv, mass) | |
| } | |
| } else { | |
| if !ok { | |
| t.Errorf("approx(%g) failed, but mass = %g", trackMass, mass) | |
| } | |
| if !ok2 { | |
| t.Errorf("exact(%g) failed, but mass = %g", trackMass, mass) | |
| } | |
| if ok && ok2 && !(l <= inv && inv < u) { | |
| t.Errorf("inverse(%g) = %g, not ∈ [%g, %g)", trackMass, inv, l, u) | |
| } | |
| } | |
| } | |
| } | |
| } |