-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathseries.go
97 lines (81 loc) · 2.09 KB
/
series.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package main
import "math"
type fifoSet struct {
numValues int
values []float64
sum float64
}
func newFifoSet(numValues int) *fifoSet {
return &fifoSet{
values: []float64{},
numValues: numValues,
}
}
func (this *fifoSet) AddValue(v float64) {
vals := append(this.values, v)
this.sum += v
if len(vals) > this.numValues {
this.sum -= vals[0]
vals = vals[1:]
}
this.values = vals
}
func (this *fifoSet) Avg() float64 {
return this.sum / float64(len(this.values))
}
type BoundedSeries struct {
values []float64 // array of values
numValues int // how many values have been requested to be stored
maxValues int // how many values we're actually storing (larger to allow smoothing)
highWater int // how many values have been populated
}
func NewBoundedSeries(numValues int) *BoundedSeries {
maxValues := numValues * 2 // double the number of values to support moving averages
values := make([]float64, maxValues)
for i := 0; i < maxValues; i++ {
values[i] = math.NaN()
}
return &BoundedSeries{
values: values,
numValues: numValues,
maxValues: maxValues,
highWater: 0,
}
}
func (this *BoundedSeries) AddValue(v float64) {
if this.highWater < this.maxValues {
this.values[this.highWater] = v
this.highWater++
} else {
newValues := append(this.values, v)
if len(newValues) > this.maxValues {
newValues = newValues[len(newValues)-this.maxValues:]
}
this.values = newValues
}
}
func (this *BoundedSeries) Values() []float64 {
start := max(0, this.highWater-this.numValues)
end := min(this.highWater, start+this.numValues)
return this.values[start:end]
}
func (this *BoundedSeries) SmoothedValues(windowSize int) []float64 {
if windowSize <= 1 {
return this.Values()
}
start := max(0, this.highWater-this.numValues-windowSize)
set := newFifoSet(windowSize)
series := make([]float64, this.numValues)
j := 0
for i := start; i < this.highWater; i++ {
set.AddValue(this.values[i])
if i >= this.highWater-this.numValues {
series[j] = set.Avg()
j++
}
}
for ; j < len(series); j++ {
series[j] = math.NaN()
}
return series
}