func sendMessageHelper(msgIdx, varIdx int, msgBag, varBag *collection.DistributionBag) float64 {
	mar := varBag.Get(varIdx)
	msg := msgBag.Get(msgIdx)
	varBag.Put(varIdx, mar.Mul(msg))

	// logZ
	return gaussian.LogProdNorm(mar, msg)
}
func gaussianGreaterThanOrWithinUpdateMessage(epsilon float64, msgIdx, varIdx int,
	msgBag, varBag *collection.DistributionBag, vFunc, wFunc func(t, epsilon float64) float64) float64 {
	oldMarginal := varBag.Get(varIdx)
	oldMsg := msgBag.Get(msgIdx)
	msgFromVar := oldMarginal.Div(oldMsg)
	c := msgFromVar.Precision
	d := msgFromVar.PrecisionMean
	sqrtC := math.Sqrt(c)
	dOnSqrtC := d / sqrtC
	epsTimesSqrtC := epsilon * sqrtC
	denom := 1.0 - wFunc(dOnSqrtC, epsTimesSqrtC)
	newPrecision := c / denom
	newPrecisionMean := (d + sqrtC*vFunc(dOnSqrtC, epsTimesSqrtC)) / denom
	newMarginal := gaussian.NewFromPrecision(newPrecisionMean, newPrecision)
	newMsg := oldMsg.Mul(newMarginal).Div(oldMarginal)

	msgBag.Put(msgIdx, newMsg)
	varBag.Put(varIdx, newMarginal)

	return newMarginal.Sub(oldMarginal)
}
// GaussianPrior calculates the prior for the factor graph.
func (gf GaussianFactors) GaussianPrior(mu, sigmaSquared float64, varIdx int,
	varBag *collection.DistributionBag) Factor {
	msgIdx := gf.msgBag.NextIndex()
	newMsg := gaussian.NewFromMeanAndVariance(mu, sigmaSquared)

	updateMessage := func(i int) float64 {
		if i != 0 {
			panic("Index out of range")
		}

		oldMarginal := varBag.Get(varIdx)
		oldMsg := gf.msgBag.Get(msgIdx)
		newMarginal := gaussian.NewFromPrecision(oldMarginal.PrecisionMean+newMsg.PrecisionMean-oldMsg.PrecisionMean,
			oldMarginal.Precision+newMsg.Precision-oldMsg.Precision)
		varBag.Put(varIdx, newMarginal)
		gf.msgBag.Put(msgIdx, newMsg)

		delta := oldMarginal.Sub(newMarginal)
		return delta
	}
	sendMessage := func(i int) float64 {
		if i != 0 {
			panic("Index out of range")
		}

		return sendMessageHelper(msgIdx, varIdx, gf.msgBag, varBag)
	}

	return Factor{
		UpdateMessage:    updateMessage,
		LogNormalization: func() float64 { return 0 },
		NumMessages:      1,
		ResetMarginals:   func() { varBag.PutPriorAt(varIdx) },
		SendMessage:      sendMessage,
	}
}