in toutoumomoma.go [329:363]
func entropyVariance(counts *[256]float64, n int) (entropy, variance float64) {
if n == 0 {
return 0, 0
}
// H = -∑i=1..k((p_i)*log(p_i))
// F² = ∑i=1..k((p_i)*log²(p_i)) - H²
//
// Variance in H is F²/N
//
// Calculated using the weighted incremental algorithm for
// mean and variance estimates.
// See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Weighted_incremental_algorithm
var pSum, pSum2 float64
for _, cnt := range counts {
if cnt == 0 {
// Ignore zero counts.
continue
}
p := cnt / float64(n)
l2p := math.Log2(p)
pSum += p
pSum2 += p * p
tmp := entropy
entropy = tmp + (p/pSum)*(l2p-tmp)
variance += p * (l2p - tmp) * (l2p - entropy)
}
variance /= float64(n)
if entropy == 0 {
// Don't negate zero.
return 0, variance
}
return -entropy, variance
}