code: def gamma_and_mvn_to_gamma_gaussian(gamma, mvn):
      """
      Convert a pair of Gamma and Gaussian distributions to a GammaGaussian.
  
          p(x | s) ~ Gaussian(s * info_vec, s * precision)
          p(s) ~ Gamma(alpha, beta)
          p(x, s) ~ GammaGaussian(info_vec, precision, alpha, beta)
  
      :param ~pyro.distributions.Gamma gamma: the mixing distribution
      :param ~pyro.distributions.MultivariateNormal mvn: the conditional distribution
          when mixing is 1.
      :return: A GammaGaussian object.
      :rtype: ~pyro.ops.gaussian_gamma.GammaGaussian
      """
      assert isinstance(gamma, torch.distributions.Gamma)
      assert isinstance(mvn, torch.distributions.MultivariateNormal)
      n = mvn.loc.size(-1)
      precision = mvn.precision_matrix
      info_vec = precision.matmul(mvn.loc.unsqueeze(-1)).squeeze(-1)
  
      # reparameterized version of concentration, rate in GaussianGamma
      alpha = gamma.concentration + (0.5 * n - 1)
      beta = gamma.rate + 0.5 * (info_vec * mvn.loc).sum(-1)
      gaussian_logsumexp = 0.5 * n * math.log(
          2 * math.pi
      ) + mvn.scale_tril.diagonal(dim1=-2, dim2=-1).log().sum(-1)
      log_normalizer = -Gamma(
          gaussian_logsumexp, gamma.concentration, gamma.rate
      ).logsumexp()
      return GammaGaussian(
          log_normalizer, info_vec, precision, alpha, beta
      )
  
imports: import math
  import torch
  from torch.distributions.utils import lazy_property
  from torch.nn.functional import pad
  from pyro.distributions.multivariate_studentt import MultivariateStudentT
  from pyro.distributions.torch import MultivariateNormal
  from pyro.distributions.util import broadcast_shape
  from pyro.ops.tensor_utils import precision_to_scale_tril
label_desc: Use image node_id 1 for calling a global function with example usage: gamma_and_mvn_to_gamma_gaussian(gamma, mvn) and returns: GammaGaussian