func entropyVariance()

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
}