code: def _random_inverse_gaussian_no_gradient(
      shape, loc, concentration, seed
  ):
      """Sample from Inverse Gaussian distribution."""
      # See https://en.wikipedia.org/wiki/Inverse_Gaussian_distribution or
      # https://www.jstor.org/stable/2683801
      dtype = dtype_util.common_dtype([loc, concentration], tf.float32)
      concentration = tf.convert_to_tensor(concentration)
      loc = tf.convert_to_tensor(loc)
      chi2_seed, unif_seed = samplers.split_seed(
          seed, salt="inverse_gaussian"
      )
      sampled_chi2 = tf.square(
          samplers.normal(shape, seed=chi2_seed, dtype=dtype)
      )
      sampled_uniform = samplers.uniform(
          shape, seed=unif_seed, dtype=dtype
      )
      # Wikipedia defines an intermediate x with the formula
      #   x = loc + loc ** 2 * y / (2 * conc)
      #       - loc / (2 * conc) * sqrt(4 * loc * conc * y + loc ** 2 * y ** 2)
      # where y ~ N(0, 1)**2 (sampled_chi2 above) and conc is the concentration.
      # Let us write
      #   w = loc * y / (2 * conc)
      # Then we can extract the common factor in the last two terms to obtain
      #   x = loc + loc * w * (1 - sqrt(2 / w + 1))
      # Now we see that the Wikipedia formula suffers from catastrphic
      # cancellation for large w (e.g., if conc << loc).
      #
      # Fortunately, we can fix this by multiplying both sides
      # by 1 + sqrt(2 / w + 1).  We get
      #   x * (1 + sqrt(2 / w + 1)) =
      #     = loc * (1 + sqrt(2 / w + 1)) + loc * w * (1 - (2 / w + 1))
      #     = loc * (sqrt(2 / w + 1) - 1)
      # The term sqrt(2 / w + 1) + 1 no longer presents numerical
      # difficulties for large w, and sqrt(2 / w + 1) - 1 is just
      # sqrt1pm1(2 / w), which we know how to compute accurately.
      # This just leaves the matter of small w, where 2 / w may
      # overflow.  In the limit a w -> 0, x -> loc, so we just mask
      # that case.
      sqrt1pm1_arg = (
          4 * concentration / (loc * sampled_chi2)
      )  # 2 / w above
      safe_sqrt1pm1_arg = tf.where(
          sqrt1pm1_arg < np.inf, sqrt1pm1_arg, 1.0
      )
      denominator = 1.0 + tf.sqrt(safe_sqrt1pm1_arg + 1.0)
      ratio = generic.sqrt1pm1(safe_sqrt1pm1_arg) / denominator
      sampled = loc * tf.where(
          sqrt1pm1_arg < np.inf, ratio, 1.0
      )  # x above
      return tf.where(
          sampled_uniform <= loc / (loc + sampled),
          sampled,
          tf.square(loc) / sampled,
      )
  
imports: import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import chain
  from tensorflow_probability.python.bijectors import exp
  from tensorflow_probability.python.bijectors import scale
  from tensorflow_probability.python.bijectors import softplus
  from tensorflow_probability.python.distributions import distribution
  from tensorflow_probability.python.distributions import normal
  from tensorflow_probability.python.internal import assert_util
  from tensorflow_probability.python.internal import custom_gradient
  from tensorflow_probability.python.internal import distribution_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import parameter_properties
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import reparameterization
  from tensorflow_probability.python.internal import samplers
  from tensorflow_probability.python.internal import special_math
  from tensorflow_probability.python.internal import tensor_util
  from tensorflow_probability.python.internal import tensorshape_util
  from tensorflow_probability.python.math import generic
label_desc: Use image node_id 1 for calling a global function with example usage: _random_inverse_gaussian_no_gradient(shape, loc, concentration, seed) and returns: tf