route/vendor/github.com/dgryski/go-onlinestats/dea.go

55 lines
1.4 KiB
Go

package onlinestats
import (
"math"
)
// http://www.drdobbs.com/tools/discontiguous-exponential-averaging/184410671
type DEA struct {
sumOfWeights float64
sumOfData float64
sumOfSquaredData float64
previousTime float64
alpha float64
newDataWeightUpperBound float64
}
func NewDEA(alpha float64, maxDt float64) *DEA {
return &DEA{
alpha: alpha,
newDataWeightUpperBound: 1 - math.Pow(alpha, float64(maxDt)),
}
}
func (ew *DEA) Update(newData float64, t float64) {
weightReductionFactor := math.Pow(ew.alpha, float64(t-ew.previousTime))
newDataWeight := minf(1-weightReductionFactor, ew.newDataWeightUpperBound)
ew.sumOfWeights = weightReductionFactor*ew.sumOfWeights + newDataWeight
ew.sumOfData = weightReductionFactor*ew.sumOfData + newDataWeight*newData
ew.sumOfSquaredData = weightReductionFactor*ew.sumOfSquaredData + (newDataWeight * (newData * newData))
ew.previousTime = t
}
func (ew *DEA) CompletenessFraction(t float64) float64 {
return math.Pow(ew.alpha, float64(t-ew.previousTime)*ew.sumOfWeights)
}
func (ew *DEA) Mean() float64 {
return (ew.sumOfData / ew.sumOfWeights)
}
func (ew *DEA) Var() float64 {
m := ew.Mean()
return (ew.sumOfSquaredData/ew.sumOfWeights - m*m)
}
func (ew *DEA) Stddev() float64 {
return math.Sqrt(ew.Var())
}
func minf(a, b float64) float64 {
if a < b {
return a
}
return b
}