package decor
import (
"sort"
"github.com/VividCortex/ewma"
)
// MovingAverage is the interface that computes a moving average over
// a time-series stream of numbers. The average may be over a window
// or exponentially decaying.
type MovingAverage interface {
Add(float64)
Value() float64
Set(float64)
}
type medianWindow [3]float64
func (s *medianWindow) Len() int { return len(s) }
func (s *medianWindow) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s *medianWindow) Less(i, j int) bool { return s[i] < s[j] }
func (s *medianWindow) Add(value float64) {
s[0], s[1] = s[1], s[2]
s[2] = value
}
func (s *medianWindow) Value() float64 {
tmp := *s
sort.Sort(&tmp)
return tmp[1]
}
func (s *medianWindow) Set(value float64) {
for i := 0; i < len(s); i++ {
s[i] = value
}
}
// NewMedian is fixed last 3 samples median MovingAverage.
func NewMedian() MovingAverage {
return new(medianWindow)
}
type medianEwma struct {
count uint
median MovingAverage
MovingAverage
}
func (s *medianEwma) Add(v float64) {
s.median.Add(v)
if s.count >= 2 {
s.MovingAverage.Add(s.median.Value())
}
s.count++
}
// NewMedianEwma is ewma based MovingAverage, which gets its values
// from median MovingAverage.
func NewMedianEwma(age ...float64) MovingAverage {
return &medianEwma{
MovingAverage: ewma.NewMovingAverage(age...),
median: NewMedian(),
}
}