-
Notifications
You must be signed in to change notification settings - Fork 7
/
windexp.go
72 lines (52 loc) · 1.54 KB
/
windexp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package onlinestats
import "math"
// WindExp maintains a window of values, followed by a exponentially-weighted
// region for the items that have left the window. This is similar to the
// Average Loss Interval from "Equation-Based Congestion Control for Unicast
// Applications" ( http://www.icir.org/tfrc/tcp-friendly.pdf ), but with lower
// update cost. The advantage is that this maintains more local history, but
// doesn't have the large changes when items leave the window.
type WindExp struct {
n int
w *Windowed
exp *ExpWeight
}
// NewWindExp returns WindExp with the specified window capacity and exponential alpha
func NewWindExp(capacity int, alpha float64) *WindExp {
return &WindExp{
w: NewWindowed(capacity),
exp: NewExpWeight(alpha),
}
}
func (we *WindExp) Push(n float64) {
old := we.w.Push(n)
if we.n >= len(we.w.data) {
we.exp.Push(old)
}
we.n++
}
func (we *WindExp) Len() int {
return we.n
}
func (we *WindExp) Mean() float64 {
// The math says this should be correct
if we.n <= len(we.w.data) {
return we.w.Mean()
}
return (we.w.sum + we.exp.Mean()) / float64(we.w.Len()+1)
}
func (we *WindExp) Var() float64 {
// http://www.emathzone.com/tutorials/basic-statistics/combined-variance.html
cmean := we.Mean()
n1 := float64(we.w.Len())
s1 := we.w.Var()
x1xc := we.w.Mean() - cmean
n2 := float64(we.exp.Len())
s2 := we.exp.Var()
x2xc := we.exp.Mean() - cmean
cvar := (n1*(s1+x1xc*x1xc) + n2*(s2+x2xc*x2xc)) / (n1 + n2)
return cvar
}
func (we *WindExp) Stddev() float64 {
return math.Sqrt(we.Var())
}