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
package mcorr

import (
	"math"
)

// MeanVar is for calculate mean and variance in the increment way.
type MeanVar struct {
	n             int     // number of values.
	m1            float64 // first moment.
	dev           float64
	nDev          float64
	m2            float64 // second moment.
	biasCorrected bool
}

// NewMeanVar return a new MeanVar.
func NewMeanVar() *MeanVar {
	return &MeanVar{}
}

// Add adds a value.
func (m *MeanVar) Add(v float64) {
	m.n++
	m.dev = v - m.m1
	m.nDev = m.dev / float64(m.n)
	m.m1 += m.nDev
	m.m2 += float64(m.n-1) * m.dev * m.nDev
}

// Mean returns the mean result.
func (m *MeanVar) Mean() float64 {
	return m.m1
}

// Variance returns the variance.
func (m *MeanVar) Variance() float64 {
	if m.n < 2 {
		return math.NaN()
	}

	if m.biasCorrected {
		return m.m2 / float64(m.n-1)
	}

	return m.m2 / float64(m.n)
}

// N returns the number of values.
func (m *MeanVar) N() int {
    return m.n
}

// IsBiasCorrected return true if the variance will be bias corrected.
func (m *MeanVar) IsBiasCorrected() bool {
    return m.biasCorrected
}

// SetBiasCorrected sets if bias corrected.
func (m *MeanVar) SetBiasCorrected(biasCorrected bool) {
    m.biasCorrected = biasCorrected
}

// Append add another result.
func (m *MeanVar) Append(m2 *MeanVar) {
	if m.n == 0 {
		m.n = m2.n
		m.m1 = m2.m1
		m.dev = m2.dev
		m.nDev = m2.nDev
		m.m2 = m2.m2
	} else {
		if m2.n > 0 {
			total1 := m.m1 * float64(m.n)
			total2 := m2.m1 * float64(m2.n)
			newMean := (total1 + total2) / float64(m.n+m2.n)
			delta1 := m.Mean() - newMean
			delta2 := m2.Mean() - newMean
			sm := (m.m2 + m2.m2) + float64(m.n)*delta1*delta1 + float64(m2.n)*delta2*delta2
			m.m1 = newMean
			m.m2 = sm
			m.n = m.n + m2.n
		}
	}
}