code: def _directional_numeric_gradients(self, directions, y0_data):
      device = self.device
      func = self.func
      xs = self.xs
      gys = self.gys
      params = self.params
      eps = self.eps
      no_gxs = self.no_gxs
      dtype = self.dtype
      detect_nondifferentiable = self.detect_nondifferentiable
      params_data = [
          p if self.is_immutable_params else p.array for p in params
      ]
  
      xp = device.xp
  
      x_vars = [variable.Variable(x, requires_grad=False) for x in xs]
  
      xs_filtered = [
          x.array
          for x, no_gx in six.moves.zip(x_vars, no_gxs)
          if not no_gx
      ]
  
      if dtype is None:
          casted_data = [x for x in xs_filtered + params_data]
      else:
          if numpy.dtype(dtype).kind != "f":
              raise ValueError("`dtype` is allowed only float type")
  
          # Even skipped variable must have the same dtype.
          for x, no_gx in six.moves.zip(x_vars, no_gxs):
              if no_gx and x.array.dtype.kind == "f":
                  x.array = x.array.astype(dtype, copy=False)
  
          casted_data = [
              None if x is None else x.astype(dtype, copy=False)
              for x in xs_filtered + params_data
          ]
  
      delta = xp.array(0.0, numpy.float64)
  
      def g():
          # This functions is called twice in `numerical_grad`.
          # `delta` is `epsilon` or `-epsilon` in these calls.
          # See the document of `numerical_grad`.
  
          def perturb(data, direction):
              if data is None:
                  assert direction is None
                  return data
  
              data = (
                  data.astype(numpy.float64) + delta * direction
              ).astype(data.dtype)
              if numpy.isscalar(data):
                  data = xp.array(data)
              return data
  
          # Input arrays
          g_x_vars = []
          j = 0
          for x_var, no_gx in six.moves.zip(x_vars, no_gxs):
              if no_gx:
                  g_x_vars.append(x_var)
              else:
                  data = perturb(casted_data[j], directions[j])
                  g_x_vars.append(
                      None if data is None else variable.Variable(data)
                  )
                  j += 1
  
          # Parameters
          for i in range(len(params)):
              data = perturb(casted_data[j + i], directions[j + i])
  
              if self.is_immutable_params:
                  # Update the parameter array since it is converted into
                  # a Parameter just before calling the func.
                  params_data[i] = data
              else:
                  # Update the given Parameter in-place since the object is
                  # held by the caller.
                  params[i].array = data
  
          # Clear gradients to support func that calls backward inside of
          # itself.
          self._clear_grads(g_x_vars)
          if not self.is_immutable_params:
              self._clear_grads(params)
  
          if self.is_immutable_params:
              ps = tuple([chainer.Parameter(p) for p in params_data])
              ys = func(g_x_vars, ps)
          else:
              ys = func(*g_x_vars)
          ys = _as_tuple(ys)
          ys_data = tuple([None if y is None else y.array for y in ys])
          if xp is chainerx:
              ys_data = tuple(
                  [
                      None if y is None else y.as_grad_stopped()
                      for y in ys_data
                  ]
              )
  
          if not self.is_immutable_params:
              for i, param in enumerate(params):
                  param.array = casted_data[j + i]
  
          return ys_data
  
      (gx,) = numerical_grad(
          g,
          (delta,),
          gys,
          eps=eps,
          detect_nondifferentiable=detect_nondifferentiable,
          center_outputs=y0_data,
          diff_atol=0,
          diff_rtol=self.rtol,
      )
  
      return gx
  
imports: from __future__ import absolute_import
  import warnings
  import numpy
  import six
  import chainer
  from chainer import backend
  from chainer.backends import _cpu
  from chainer.backends import cuda
  from chainer import configuration
  from chainer import testing
  from chainer import utils
  from chainer import variable
  import chainerx
label_desc: Use image node_id 11 for calling the _CheckBackward obj's underlying member method code with example usage: obj._directional_numeric_gradients(directions, y0_data) and returns: gx, ys_data, data, data