<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def autodiff(func, wrt=(0,), optimized=True, motion='joint', mode='reverse', preserve_result=False, check_dims=True, input_derivative=INPUT_DERIVATIVE.Required, verbose=0):
 """Build the vector-Jacobian or Jacobian-vector product of a function `func`. For a vector-Jacobian product (reverse-mode autodiff):
 This function proceeds by finding the primals and adjoints of all the functions in the call tree. For a Jacobian-vector product (forward-mode autodiff):
 We first find the primals and tangents of all functions in the call tree. It then wraps the top level function (i.e. the one passed as `func`) in a slightly more user-friendly interface. It then compiles the function and attaches to it the global namespace it needs to run. Args: func: The function to take the gradient of. wrt: A tuple of argument indices to differentiate with respect to. By default the derivative is taken with respect to the first argument. optimized: Whether to optimize the gradient function (`True` by default). motion: Either 'split' (separate functions for forward and backward pass) or 'joint' motion (a single combined function). Joint mode is the default. mode: Either 'forward' or 'reverse' mode. Forward mode is more efficient when the input dimensionality is lower than the output dimensionality, whereas it is the opposite for reverse mode. input_derivative: An enum indicating whether the user must supply an input derivative, and if not, what the default value is. See the possible values of INPUT_DERIVATIVE in this file. preserve_result: A boolean indicating whether or not the generated gradient function should also return the output of the original function. If False, the return signature of the input and output functions will be > val = func(*args) > df = grad(func,preserve_result=False) > gradval = df(*args) If True, > val = func(*args) > df = grad(func,preserve_result=True) > gradval, val = df(*args) Note that if taking gradients with respect to multiple arguments, the primal value will be appended to the return signature. Ex: > val = func(x,y) > df = grad(func,wrt=(0,1),preserve_result=True) > dx,dy,val = df(x,y) verbose: If 1 the source code of the generated functions will be output to stdout at various stages of the process for debugging purposes. If > 1, all intermediate code generation steps will print. Returns: df: A function that calculates a derivative (see file-level documentation above for the kinds of derivatives available) with respect to arguments specified in `wrt`, using forward or reverse mode according to `mode`. If using reverse mode, the gradient is calculated in either split or joint motion according to the value passed in `motion`. If `preserve_result` is True, the function will also return the original result of `func`. """

  # If the function had the with insert_grad_of statements removed, retrieve them
  func = getattr(func, 'tangent', func)

  # Generate the derivative
  node, namespace = autodiff_tree(func, wrt, motion, mode, preserve_result,
                                  check_dims, verbose)

  if mode == 'reverse' and motion == 'joint':
    # Pull the stack definition and initial gradient into the function body
    # TODO: Use first FunctionDef instead of first element
    node.body[0] = _create_joint(node.body[0], func, wrt, input_derivative)
    if verbose >= 2:
      print('INLINED')
      print(quoting.to_source(node))
  if mode == 'forward':
    node = _create_forward(node)
  if optimized:
    # Optimize the resulting functions
    node = optimization.optimize(node)
  node = comments.remove_repeated_comments(node)
  if verbose >= 1:
    print(quoting.to_source(node))

  # Compile and return
  module = compile_.compile_file(node, namespace)
  if mode == 'forward' or motion == 'joint':
    return getattr(module, node.body[0].name)
  else:
    # Compiling the top-level function in split mode makes no sense, but we use
    # it for testing; hence we don't care about the source being readable
    forward = getattr(module, node.body[0].name)
    backward = getattr(module, node.body[1].name)

    # Imported here to avoid circular imports
    import tangent

    def df(*args, **kwargs):
      _stack = tangent.Stack()
      init_grad = kwargs.pop('init_grad', 1.0)
      forward(_stack, *args, **kwargs)
      dx = backward(_stack, init_grad, *args, **kwargs)
      if len(dx) == 1:
        dx, = dx
      return dx

    return df