public static RpropBufferData BufferTGa([NoInit] TruncatedGamma use, TruncatedGamma def, TruncatedGamma to_marginal, RpropBufferData bufferTGa)
        {
            var currDist = use * def;

            if (currDist.IsPointMass)
            {
                if (double.IsInfinity(currDist.Point) || double.IsNaN(currDist.Point))
                {
                    throw new ArgumentOutOfRangeException();
                }
                if (VariablePointOp_RpropGamma.UseMean)
                {
                    bufferTGa.nextPoint = Math.Log(currDist.Point);
                }
                else
                {
                    bufferTGa.nextPoint = currDist.Point;
                }
                return(bufferTGa);
            }
            // cannot use buffer.nextPoint as currPoint since Marginal could be initialized by user
            double currPoint;

            if (to_marginal.IsPointMass)
            {
                currPoint = to_marginal.Point;
            }
            else
            {
                currPoint = currDist.GetMean();
            }
            double currDeriv, currDeriv2;

            if (VariablePointOp_RpropGamma.UseMean)
            {
                bufferTGa.lowerBound = Math.Log(currDist.LowerBound);
                bufferTGa.upperBound = Math.Log(currDist.UpperBound);
                currDeriv            = currDist.Gamma.Shape - currDist.Gamma.Rate * currPoint;
                //Trace.WriteLine($"use deriv = {(use.Gamma.Shape-1) - use.Gamma.Rate*currPoint} def deriv = {def.Gamma.Shape - def.Gamma.Rate*currPoint} total deriv = {currDeriv}");
                if (currPoint <= 0)
                {
                    throw new ArgumentException($"currPoint ({currPoint}) <= 0");
                }
                bufferTGa.SetNextPoint(Math.Log(currPoint), currDeriv);
            }
            else
            {
                bufferTGa.lowerBound = currDist.LowerBound;
                bufferTGa.upperBound = currDist.UpperBound;
                currDist.Gamma.GetDerivatives(currPoint, out currDeriv, out currDeriv2);
                bufferTGa.SetNextPoint(currPoint, currDeriv);
            }
            return(bufferTGa);
        }
        public static RpropBufferData BufferBeta([NoInit] Beta use, Beta def, Beta to_marginal, RpropBufferData bufferBeta)
        {
            var currDist = use * def;

            if (currDist.IsPointMass)
            {
                bufferBeta.nextPoint = currDist.Point;
                return(bufferBeta);
            }
            // cannot use buffer.nextPoint as currPoint since Marginal could be initialized by user
            double currPoint;

            if (to_marginal.IsPointMass)
            {
                currPoint = to_marginal.Point;
            }
            else
            {
                currPoint = currDist.GetMean();
            }
            double currDeriv, currDeriv2;

            currDist.GetDerivatives(currPoint, out currDeriv, out currDeriv2);
            bufferBeta.SetNextPoint(currPoint, currDeriv);
            return(bufferBeta);
        }
        public static RpropBufferData BufferTG([NoInit] TruncatedGaussian use, TruncatedGaussian def, TruncatedGaussian to_marginal, RpropBufferData bufferTG)
        {
            var currDist = use * def;

            if (currDist.IsPointMass)
            {
                if (double.IsInfinity(currDist.Point))
                {
                    throw new ArgumentOutOfRangeException(nameof(use), "infinite point mass");
                }
                bufferTG.nextPoint = currDist.Point;
                return(bufferTG);
            }
            // cannot use buffer.nextPoint as currPoint since Marginal could be initialized by user
            double currPoint;

            if (to_marginal.IsPointMass)
            {
                currPoint = to_marginal.Point;
            }
            else
            {
                currPoint = currDist.GetMean();
            }
            // deriv of -0.5*prec*x^2+pm*x
            // is -prec*x + pm
            double currDeriv = currDist.Gaussian.MeanTimesPrecision - currDist.Gaussian.Precision * currPoint;

            bufferTG.lowerBound = currDist.LowerBound;
            bufferTG.upperBound = currDist.UpperBound;
            bufferTG.SetNextPoint(currPoint, currDeriv);
            return(bufferTG);
        }
        public static RpropBufferData Buffer([NoInit] Gaussian use, Gaussian def, Gaussian to_marginal, RpropBufferData buffer)
        {
            var currDist = use * def;

            if (currDist.IsPointMass)
            {
                buffer.nextPoint = currDist.Point;
                return(buffer);
            }
            // cannot use buffer.nextPoint as currPoint since Marginal could be initialized by user
            double currPoint;

            if (to_marginal.IsPointMass)
            {
                currPoint = to_marginal.Point;
            }
            else
            {
                currPoint = currDist.GetMean();
            }
            // deriv of -0.5*prec*x^2+pm*x
            // is -prec*x + pm
            double currDeriv = currDist.MeanTimesPrecision - currDist.Precision * currPoint;

            buffer.SetNextPoint(currPoint, currDeriv);
            return(buffer);
        }
        public static RpropBufferData Buffer0([NoInit] Gamma use, Gamma def, Gamma to_marginal, RpropBufferData buffer0)
        {
            var currDist = use * def;

            if (currDist.IsPointMass)
            {
                if (UseMean)
                {
                    buffer0.nextPoint = Math.Log(currDist.Point);
                }
                else
                {
                    buffer0.nextPoint = currDist.Point;
                }
                return(buffer0);
            }
            // cannot use buffer.nextPoint as currPoint since Marginal could be initialized by user
            double currPoint;

            if (to_marginal.IsPointMass)
            {
                currPoint = to_marginal.Point;
            }
            else
            {
                currPoint = currDist.GetMean();
            }
            double currDeriv, currDeriv2;

            if (UseMean)
            {
                currDeriv = currDist.Shape - currDist.Rate * currPoint;
                if (currPoint <= 0)
                {
                    throw new ArgumentException($"currPoint ({currPoint}) <= 0");
                }
                buffer0.SetNextPoint(Math.Log(currPoint), currDeriv);
            }
            else
            {
                currDist.GetDerivatives(currPoint, out currDeriv, out currDeriv2);
                buffer0.SetNextPoint(currPoint, currDeriv);
            }
            return(buffer0);
        }