code: def _adesi_whaley_critical_values(
      *,
      sigma,
      x,
      t,
      r,
      d,
      sign,
      is_call_options,
      max_iterations=20,
      tolerance=1e-8,
      dtype,
  ):
      """Computes critical value for the Baron-Adesi Whaley approximation."""
  
      # The naming convention will align variables with the variables named in
      # reference [1], but made lower case, and differentiating between put and
      # call option values with the suffix _put and _call.
      # [1] https://deriscope.com/docs/Barone_Adesi_Whaley_1987.pdf
  
      m = 2 * r / sigma**2
      n = 2 * (r - d) / sigma**2
      k = 1 - tf.exp(-r * t)
      q = _calc_q(n, m, sign, k)
  
      def value_fn(s_crit):
          return (
              vanilla_prices.option_price(
                  volatilities=sigma,
                  strikes=x,
                  expiries=t,
                  spots=s_crit,
                  discount_rates=r,
                  dividend_rates=d,
                  is_call_options=is_call_options,
                  dtype=dtype,
              )
              + sign
              * (
                  1
                  - tf.math.exp(-d * t)
                  * _ncdf(sign * _calc_d1(s_crit, x, sigma, r - d, t))
              )
              * tf.math.divide_no_nan(s_crit, q)
              - sign * (s_crit - x)
          )
  
      def value_and_gradient_func(price):
          return gradient.value_and_gradient(value_fn, price)
  
      # Calculate seed value for critical spot price for fewer iterations needed, as
      # defined in reference [1] part II, section B.
      # [1] https://deriscope.com/docs/Barone_Adesi_Whaley_1987.pdf
      q_inf = _calc_q(n, m, sign)
      s_inf = tf.math.divide_no_nan(
          x,
          1 - tf.math.divide_no_nan(tf.constant(1, dtype=dtype), q_inf),
      )
      h = (
          -(sign * (r - d) * t + 2 * sigma * tf.math.sqrt(t))
          * sign
          * tf.math.divide_no_nan(x, s_inf - x)
      )
      if is_call_options is None:
          s_seed = x + (s_inf - x) * (1 - tf.math.exp(h))
      else:
          s_seed = tf.where(
              is_call_options,
              x + (s_inf - x) * (1 - tf.math.exp(h)),
              s_inf + (x - s_inf) * tf.math.exp(h),
          )
  
      s_crit, converged, failed = root_finder_newton.root_finder(
          value_and_grad_func=value_and_gradient_func,
          initial_values=s_seed,
          max_iterations=max_iterations,
          tolerance=tolerance,
          dtype=dtype,
      )
  
      a = (
          sign
          * tf.math.divide_no_nan(s_crit, q)
          * (
              1
              - tf.math.exp(-d * t)
              * _ncdf(sign * _calc_d1(s_crit, x, sigma, r - d, t))
          )
      )
  
      return q, a, s_crit, converged, failed
  
imports: from typing import Tuple
  import numpy
  import tensorflow.compat.v2
  from tf_quant_finance import types
  from tf_quant_finance.black_scholes import vanilla_prices
  from tf_quant_finance.math import gradient
  from tf_quant_finance.math import integration
  from tf_quant_finance.math.root_search import newton
label_desc: Use image node_id 3 for calling a global function with example usage: _adesi_whaley_critical_values() and returns: q,  a,  s_crit,  converged,  failed, unknown, gradient