parameters: (
      func: Callable[..., _TensorOrTensors],  # See Note [VarArg of Tensors]
      inputs: _TensorOrTensors,
      grad_outputs: Optional[_TensorOrTensors] = None,
      *,
      eps: float = 1e-6,
      atol: float = 1e-5,
      rtol: float = 1e-3,
      gen_non_contig_grad_outputs: bool = False,
      raise_exception: bool = True,
      nondet_tol: float = 0.0,
      check_undefined_grad: bool = True,
      check_grad_dtypes: bool = False,
      check_batched_grad: bool = False,
      check_fwd_over_rev: bool = False,
      check_rev_over_rev: bool = True,
      fast_mode: bool = False,
  )
return_statement: return gradcheck(
          new_func, tupled_inputs + tupled_grad_outputs, eps=eps, atol=atol, rtol=rtol, raise_exception=raise_exception,
          nondet_tol=nondet_tol, check_undefined_grad=check_undefined_grad,
          check_grad_dtypes=check_grad_dtypes, check_batched_grad=check_batched_grad, fast_mode=fast_mode,
          check_forward_ad=check_fwd_over_rev, check_backward_ad=check_rev_over_rev)
docstring: r"""Check gradients of gradients computed via small finite differences
      against analytical gradients w.r.t. tensors in :attr:`inputs` and
      :attr:`grad_outputs` that are of floating point or complex type and with
      ``requires_grad=True``.
  
      This function checks that backpropagating through the gradients computed
      to the given :attr:`grad_outputs` are correct.
  
      The check between numerical and analytical gradients uses :func:`~torch.allclose`.
  
      .. note::
          The default values are designed for :attr:`input` and
          :attr:`grad_outputs` of double precision. This check will likely fail if
          they are of less precision, e.g., ``FloatTensor``.
  
      .. warning::
         If any checked tensor in :attr:`input` and :attr:`grad_outputs` has
         overlapping memory, i.e., different indices pointing to the same memory
         address (e.g., from :func:`torch.expand`), this check will likely fail
         because the numerical gradients computed by point perturbation at such
         indices will change values at all other indices that share the same
         memory address.
  
      Args:
          func (function): a Python function that takes Tensor inputs and returns
              a Tensor or a tuple of Tensors
          inputs (tuple of Tensor or Tensor): inputs to the function
          grad_outputs (tuple of Tensor or Tensor, optional): The gradients with
              respect to the function's outputs.
          eps (float, optional): perturbation for finite differences
          atol (float, optional): absolute tolerance
          rtol (float, optional): relative tolerance
          gen_non_contig_grad_outputs (bool, optional): if :attr:`grad_outputs` is
              ``None`` and :attr:`gen_non_contig_grad_outputs` is ``True``, the
              randomly generated gradient outputs are made to be noncontiguous
          raise_exception (bool, optional): indicating whether to raise an exception if
              the check fails. The exception gives more information about the
              exact nature of the failure. This is helpful when debugging gradchecks.
          nondet_tol (float, optional): tolerance for non-determinism. When running
              identical inputs through the differentiation, the results must either match
              exactly (default, 0.0) or be within this tolerance. Note that a small amount
              of nondeterminism in the gradient will lead to larger inaccuracies in
              the second derivative.
          check_undefined_grad (bool, optional): if True, check if undefined output grads
              are supported and treated as zeros
          check_batched_grad (bool, optional): if True, check if we can compute
              batched gradients using prototype vmap support. Defaults to False.
          fast_mode (bool, optional): if True, run a faster implementation of gradgradcheck that
              no longer computes the entire jacobian.
  
      Returns:
          True if all differences satisfy allclose condition
docstring_summary: r"""Check gradients of gradients computed via small finite differences
      against analytical gradients w.r.t. tensors in :attr:`inputs` and
      :attr:`grad_outputs` that are of floating point or complex type and with
      ``requires_grad=True``.
docstring_tokens: r Check gradients of gradients computed via small finite differences against analytical gradients w . r . t . tensors in : attr : inputs and : attr : grad_outputs that are of floating point or complex type and with requires_grad = True .
function: def gradgradcheck(
      func: Callable[..., _TensorOrTensors],  # See Note [VarArg of Tensors]
      inputs: _TensorOrTensors,
      grad_outputs: Optional[_TensorOrTensors] = None,
      *,
      eps: float = 1e-6,
      atol: float = 1e-5,
      rtol: float = 1e-3,
      gen_non_contig_grad_outputs: bool = False,
      raise_exception: bool = True,
      nondet_tol: float = 0.0,
      check_undefined_grad: bool = True,
      check_grad_dtypes: bool = False,
      check_batched_grad: bool = False,
      check_fwd_over_rev: bool = False,
      check_rev_over_rev: bool = True,
      fast_mode: bool = False,
  ) -> bool:
      r"""Check gradients of gradients computed via small finite differences
      against analytical gradients w.r.t. tensors in :attr:`inputs` and
      :attr:`grad_outputs` that are of floating point or complex type and with
      ``requires_grad=True``.
  
      This function checks that backpropagating through the gradients computed
      to the given :attr:`grad_outputs` are correct.
  
      The check between numerical and analytical gradients uses :func:`~torch.allclose`.
  
      .. note::
          The default values are designed for :attr:`input` and
          :attr:`grad_outputs` of double precision. This check will likely fail if
          they are of less precision, e.g., ``FloatTensor``.
  
      .. warning::
         If any checked tensor in :attr:`input` and :attr:`grad_outputs` has
         overlapping memory, i.e., different indices pointing to the same memory
         address (e.g., from :func:`torch.expand`), this check will likely fail
         because the numerical gradients computed by point perturbation at such
         indices will change values at all other indices that share the same
         memory address.
  
      Args:
          func (function): a Python function that takes Tensor inputs and returns
              a Tensor or a tuple of Tensors
          inputs (tuple of Tensor or Tensor): inputs to the function
          grad_outputs (tuple of Tensor or Tensor, optional): The gradients with
              respect to the function's outputs.
          eps (float, optional): perturbation for finite differences
          atol (float, optional): absolute tolerance
          rtol (float, optional): relative tolerance
          gen_non_contig_grad_outputs (bool, optional): if :attr:`grad_outputs` is
              ``None`` and :attr:`gen_non_contig_grad_outputs` is ``True``, the
              randomly generated gradient outputs are made to be noncontiguous
          raise_exception (bool, optional): indicating whether to raise an exception if
              the check fails. The exception gives more information about the
              exact nature of the failure. This is helpful when debugging gradchecks.
          nondet_tol (float, optional): tolerance for non-determinism. When running
              identical inputs through the differentiation, the results must either match
              exactly (default, 0.0) or be within this tolerance. Note that a small amount
              of nondeterminism in the gradient will lead to larger inaccuracies in
              the second derivative.
          check_undefined_grad (bool, optional): if True, check if undefined output grads
              are supported and treated as zeros
          check_batched_grad (bool, optional): if True, check if we can compute
              batched gradients using prototype vmap support. Defaults to False.
          fast_mode (bool, optional): if True, run a faster implementation of gradgradcheck that
              no longer computes the entire jacobian.
  
      Returns:
          True if all differences satisfy allclose condition
      """
      assert check_fwd_over_rev or check_rev_over_rev, \
          "Expected at least one of check_fwd_over_rev or check_rev_over_rev to be True"
      assert not (check_undefined_grad and not check_rev_over_rev), \
          "Setting check_undefined_grad=True requires check_rev_over_rev to be True"
      assert not (check_batched_grad and not check_rev_over_rev), (
          "Setting check_batched_grad=True requires check_rev_over_rev to be True")
      # TODO: do we want to test this too?
      # assert not (check_batched_forward_grad and not check_fwd_over_rev), (
      #     "Setting check_batched_forward_grad=True requires check_fwd_over_rev to be True")
      tupled_inputs = _as_tuple(inputs)
  
      if grad_outputs is None:
          # If grad_outputs is not specified, create random Tensors of the same
          # shape, type, and device as the outputs
          def randn_like(x):
              y = torch.randn_like(
                  x if (x.is_floating_point() or x.is_complex()) else x.double(), memory_format=torch.legacy_contiguous_format)
              if gen_non_contig_grad_outputs:
                  y = torch.testing.make_non_contiguous(y)
              return y.requires_grad_()
          outputs = _as_tuple(func(*tupled_inputs))
          tupled_grad_outputs = tuple(randn_like(x) for x in outputs)
      else:
          tupled_grad_outputs = _as_tuple(grad_outputs)
  
      num_outputs = len(tupled_grad_outputs)
  
      def new_func(*args):
          input_args = args[:-num_outputs]
          grad_outputs = args[-num_outputs:]
          outputs = _differentiable_outputs(func(*input_args))
          input_args = tuple(x for x in input_args
                             if is_tensor_like(x) and x.requires_grad)
          grad_inputs = torch.autograd.grad(outputs, input_args, grad_outputs, create_graph=True,
                                            allow_unused=True)
          grad_inputs = tuple(g for g in grad_inputs if g is not None)
          return grad_inputs
  
      return gradcheck(
          new_func, tupled_inputs + tupled_grad_outputs, eps=eps, atol=atol, rtol=rtol, raise_exception=raise_exception,
          nondet_tol=nondet_tol, check_undefined_grad=check_undefined_grad,
          check_grad_dtypes=check_grad_dtypes, check_batched_grad=check_batched_grad, fast_mode=fast_mode,
          check_forward_ad=check_fwd_over_rev, check_backward_ad=check_rev_over_rev)
function_tokens: def gradgradcheck ( func : Callable [ ... , _TensorOrTensors ] , # See Note [VarArg of Tensors] inputs : _TensorOrTensors , grad_outputs : Optional [ _TensorOrTensors ] = None , * , eps : float = 1e-6 , atol : float = 1e-5 , rtol : float = 1e-3 , gen_non_contig_grad_outputs : bool = False , raise_exception : bool = True , nondet_tol : float = 0.0 , check_undefined_grad : bool = True , check_grad_dtypes : bool = False , check_batched_grad : bool = False , check_fwd_over_rev : bool = False , check_rev_over_rev : bool = True , fast_mode : bool = False , ) -> bool : assert check_fwd_over_rev or check_rev_over_rev , "Expected at least one of check_fwd_over_rev or check_rev_over_rev to be True" assert not ( check_undefined_grad and not check_rev_over_rev ) , "Setting check_undefined_grad=True requires check_rev_over_rev to be True" assert not ( check_batched_grad and not check_rev_over_rev ) , ( "Setting check_batched_grad=True requires check_rev_over_rev to be True" ) # TODO: do we want to test this too? # assert not (check_batched_forward_grad and not check_fwd_over_rev), ( #     "Setting check_batched_forward_grad=True requires check_fwd_over_rev to be True") tupled_inputs = _as_tuple ( inputs ) if grad_outputs is None : # If grad_outputs is not specified, create random Tensors of the same # shape, type, and device as the outputs def randn_like ( x ) : y = torch . randn_like ( x if ( x . is_floating_point ( ) or x . is_complex ( ) ) else x . double ( ) , memory_format = torch . legacy_contiguous_format ) if gen_non_contig_grad_outputs : y = torch . testing . make_non_contiguous ( y ) return y . requires_grad_ ( ) outputs = _as_tuple ( func ( * tupled_inputs ) ) tupled_grad_outputs = tuple ( randn_like ( x ) for x in outputs ) else : tupled_grad_outputs = _as_tuple ( grad_outputs ) num_outputs = len ( tupled_grad_outputs ) def new_func ( * args ) : input_args = args [ : - num_outputs ] grad_outputs = args [ - num_outputs : ] outputs = _differentiable_outputs ( func ( * input_args ) ) input_args = tuple ( x for x in input_args if is_tensor_like ( x ) and x . requires_grad ) grad_inputs = torch . autograd . grad ( outputs , input_args , grad_outputs , create_graph = True , allow_unused = True ) grad_inputs = tuple ( g for g in grad_inputs if g is not None ) return grad_inputs return gradcheck ( new_func , tupled_inputs + tupled_grad_outputs , eps = eps , atol = atol , rtol = rtol , raise_exception = raise_exception , nondet_tol = nondet_tol , check_undefined_grad = check_undefined_grad , check_grad_dtypes = check_grad_dtypes , check_batched_grad = check_batched_grad , fast_mode = fast_mode , check_forward_ad = check_fwd_over_rev , check_backward_ad = check_rev_over_rev )