/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="GammaPowerProductOp_Laplace"]/message_doc[@name="LogAverageFactor(GammaPower, GammaPower, GammaPower, Gamma)"]/*'/> public static double LogAverageFactor(GammaPower product, GammaPower A, GammaPower B, Gamma q) { if (B.Shape < A.Shape) { return(LogAverageFactor(product, B, A, q)); } if (B.IsPointMass) { return(GammaProductOp.LogAverageFactor(product, A, B.Point)); } if (A.IsPointMass) { return(GammaProductOp.LogAverageFactor(product, A.Point, B)); } double qPoint = q.GetMean(); double logf; if (product.IsPointMass) { // Ga(y/q; s, r)/q if (qPoint == 0) { if (product.Point == 0) { logf = A.GetLogProb(0); } else { logf = double.NegativeInfinity; } } else { logf = A.GetLogProb(product.Point / qPoint) - Math.Log(qPoint); } } else { // int Ga^y_p(a^pa b^pb; y_s, y_r) Ga(a; s, r) da = q^(y_s-y_p) / (r + q y_r)^(y_s + s-pa) Gamma(y_s+s-pa) double shape = product.Shape - product.Power; double shape2 = GammaFromShapeAndRateOp_Slow.AddShapesMinus1(product.Shape, A.Shape) + (1 - A.Power); if (IsProper(product) && product.Shape > A.Shape) { // same as below but product.GetLogNormalizer() is inlined and combined with other terms double AShapeMinusPower = A.Shape - A.Power; logf = shape * Math.Log(qPoint) - Gamma.FromShapeAndRate(A.Shape, A.Rate).GetLogNormalizer() - product.Shape * Math.Log(A.Rate / product.Rate + qPoint) - Math.Log(Math.Abs(product.Power)); if (AShapeMinusPower != 0) { logf += AShapeMinusPower * (MMath.RisingFactorialLnOverN(product.Shape, AShapeMinusPower) - Math.Log(A.Rate + qPoint * product.Rate)); } } else { logf = shape * Math.Log(qPoint) - shape2 * Math.Log(A.Rate + qPoint * product.Rate) + MMath.GammaLn(shape2) - Gamma.FromShapeAndRate(A.Shape, A.Rate).GetLogNormalizer() - product.GetLogNormalizer(); // normalizer is -MMath.GammaLn(Shape) + Shape * Math.Log(Rate) - Math.Log(Math.Abs(Power)) } } double logz = logf + Gamma.FromShapeAndRate(B.Shape, B.Rate).GetLogProb(qPoint) - q.GetLogProb(qPoint); return(logz); }