code: def truncated_normal_like(x, mu, tau, a=None, b=None):
      R
      x = np.atleast_1d(x)
      if a is None:
          a = -np.inf
      a = np.atleast_1d(a)
      if b is None:
          b = np.inf
      b = np.atleast_1d(b)
      mu = np.atleast_1d(mu)
      sigma = (1. / np.atleast_1d(np.sqrt(tau)))
      if (x < a).any() or (x > b).any():
          return -np.inf
      else:
          n = len(x)
          phi = normal_like(x, mu, tau)
          lPhia = utils.normcdf((a - mu) / sigma, log=True)
          lPhib = utils.normcdf((b - mu) / sigma, log=True)
          try:
              d = utils.log_difference(lPhib, lPhia)
          except ValueError:
              return -np.inf
          # d = np.log(Phib-Phia)
          if len(d) == n:
              Phi = d.sum()
          else:
              Phi = n * d
          if np.isnan(Phi) or np.isinf(Phi):
              return -np.inf
          return phi - Phi
docs: R"""
      Truncated normal log-likelihood.
  
      .. math::
          f(x \mid \mu, \tau, a, b) = \frac{\phi(\frac{x-\mu}{\sigma})} {\Phi(\frac{b-\mu}{\sigma}) - \Phi(\frac{a-\mu}{\sigma})},
  
      where :math:`\sigma^2=1/\tau`, `\phi` is the standard normal PDF and `\Phi` is the standard normal CDF.
  
      :Parameters:
        - `x` : Input data.
        - `mu` : Mean of the distribution.
        - `tau` : Precision of the distribution, which corresponds to 1/sigma**2 (tau > 0).
        - `a` : Left bound of the distribution.
        - `b` : Right bound of the distribution.