code: def diff(ctx, f, x, n=1, **options):
      r"""
      Numerically computes the derivative of `f`, `f'(x)`, or generally for
      an integer `n \ge 0`, the `n`-th derivative `f^{(n)}(x)`.
      A few basic examples are::
  
          >>> from mpmath import *
          >>> mp.dps = 15; mp.pretty = True
          >>> diff(lambda x: x**2 + x, 1.0)
          3.0
          >>> diff(lambda x: x**2 + x, 1.0, 2)
          2.0
          >>> diff(lambda x: x**2 + x, 1.0, 3)
          0.0
          >>> nprint([diff(exp, 3, n) for n in range(5)])   # exp'(x) = exp(x)
          [20.0855, 20.0855, 20.0855, 20.0855, 20.0855]
  
      Even more generally, given a tuple of arguments `(x_1, \ldots, x_k)`
      and order `(n_1, \ldots, n_k)`, the partial derivative
      `f^{(n_1,\ldots,n_k)}(x_1,\ldots,x_k)` is evaluated. For example::
  
          >>> diff(lambda x,y: 3*x*y + 2*y - x, (0.25, 0.5), (0,1))
          2.75
          >>> diff(lambda x,y: 3*x*y + 2*y - x, (0.25, 0.5), (1,1))
          3.0
  
      **Options**
  
      The following optional keyword arguments are recognized:
  
      ``method``
          Supported methods are ``'step'`` or ``'quad'``: derivatives may be
          computed using either a finite difference with a small step
          size `h` (default), or numerical quadrature.
      ``direction``
          Direction of finite difference: can be -1 for a left
          difference, 0 for a central difference (default), or +1
          for a right difference; more generally can be any complex number.
      ``addprec``
          Extra precision for `h` used to account for the function's
          sensitivity to perturbations (default = 10).
      ``relative``
          Choose `h` relative to the magnitude of `x`, rather than an
          absolute value; useful for large or tiny `x` (default = False).
      ``h``
          As an alternative to ``addprec`` and ``relative``, manually
          select the step size `h`.
      ``singular``
          If True, evaluation exactly at the point `x` is avoided; this is
          useful for differentiating functions with removable singularities.
          Default = False.
      ``radius``
          Radius of integration contour (with ``method = 'quad'``).
          Default = 0.25. A larger radius typically is faster and more
          accurate, but it must be chosen so that `f` has no
          singularities within the radius from the evaluation point.
  
      A finite difference requires `n+1` function evaluations and must be
      performed at `(n+1)` times the target precision. Accordingly, `f` must
      support fast evaluation at high precision.
  
      With integration, a larger number of function evaluations is
      required, but not much extra precision is required. For high order
      derivatives, this method may thus be faster if f is very expensive to
      evaluate at high precision.
  
      **Further examples**
  
      The direction option is useful for computing left- or right-sided
      derivatives of nonsmooth functions::
  
          >>> diff(abs, 0, direction=0)
          0.0
          >>> diff(abs, 0, direction=1)
          1.0
          >>> diff(abs, 0, direction=-1)
          -1.0
  
      More generally, if the direction is nonzero, a right difference
      is computed where the step size is multiplied by sign(direction).
      For example, with direction=+j, the derivative from the positive
      imaginary direction will be computed::
  
          >>> diff(abs, 0, direction=j)
          (0.0 - 1.0j)
  
      With integration, the result may have a small imaginary part
      even even if the result is purely real::
  
          >>> diff(sqrt, 1, method='quad')    # doctest:+ELLIPSIS
          (0.5 - 4.59...e-26j)
          >>> chop(_)
          0.5
  
      Adding precision to obtain an accurate value::
  
          >>> diff(cos, 1e-30)
          0.0
          >>> diff(cos, 1e-30, h=0.0001)
          -9.99999998328279e-31
          >>> diff(cos, 1e-30, addprec=100)
          -1.0e-30
  
      """
      partial = False
      try:
          orders = list(n)
          x = list(x)
          partial = True
      except TypeError:
          pass
      if partial:
          x = [ctx.convert(_) for _ in x]
          return _partial_diff(ctx, f, x, orders, options)
      method = options.get("method", "step")
      if n == 0 and method != "quad" and not options.get("singular"):
          return f(ctx.convert(x))
      prec = ctx.prec
      try:
          if method == "step":
              values, norm, workprec = hsteps(
                  ctx, f, x, n, prec, **options
              )
              ctx.prec = workprec
              v = ctx.difference(values, n) / norm**n
          elif method == "quad":
              ctx.prec += 10
              radius = ctx.convert(options.get("radius", 0.25))
  
              def g(t):
                  rei = radius * ctx.expj(t)
                  z = x + rei
                  return f(z) / rei**n
  
              d = ctx.quadts(g, [0, 2 * ctx.pi])
              v = d * ctx.factorial(n) / (2 * ctx.pi)
          else:
              raise ValueError("unknown method: %r" % method)
      finally:
          ctx.prec = prec
      return +v
  
file_path: catboost/contrib/python/mpmath/py3/mpmath/calculus/differentiation.py
imports: from ..libmp.backend import xrange
  from .calculus import defun
label_desc: Use image node_id 3 for calling a global function with example usage: diff(ctx, f, x, n) and returns: unknown, _partial_diff, f, unknown