
    gO                     >   d dl mZ ddlmZ 	 ej        Zn# e$ r
 ej        ZY nw xY wed             Zd Z	edd            Z
d Zedd	            Zd
 Zed             Zi fdZed             Zedd            Zedd            Zed             Zed             ZdS )   )xrange   )defunc                     t          |          }| j        }d|dz  z  }t          |dz             D ]}||||         z  z  }|||z
  z  |dz   z  }|S )z
    Given a sequence `(s_k)` containing at least `n+1` items, returns the
    `n`-th forward difference,

    .. math ::

        \Delta^n = \sum_{k=0}^{\infty} (-1)^{k+n} {n \choose k} s_k.
    r   )intzeror   )ctxsndbks         [/var/www/html/ai-engine/env/lib/python3.11/site-packages/mpmath/calculus/differentiation.py
differencer      sj     	AAA	QAAaC[[ ! !	Q1X!A#YAaC H    c                    |                     d          }|                     dd          }|                     dd          }|d|z  z   |dz   z  }	| j        }
	 |	| _        |                     d          X|                     d	          r#t          |                                         }nd}|                     d| |z
  |z
            n|                               |                     dd          }|r-|                     |          z  t          |dz             }}nt          | |dz   d          }dz  }|rd
z  z  fd|D             }|||	f|
| _        S # |
| _        w xY w)Nsingularaddprec
   	direction    r   r   hrelativeg      ?c                 2    g | ]} |z  z             S  r   ).0r   fr   xs     r   
<listcomp>zhsteps.<locals>.<listcomp>=   s)    ***q!!AacE((***r   )getprecr   magldexpconvertsignr   )r
   r   r   r   r"   optionsr   r   r   workprecorig	hextramagstepsnormvaluesr   s    ``            @r   hstepsr.      s   {{:&&Hkk)R((GK++IQwY1Q3'H8DKK9{{:&& 

OO					!dU7]9455AAAAKKQ//	 	)$$$A1Q3KKEDD A2qsA&&EaCD 	QJA******E***tX%4s   DE+ +	E4c                 \    d}	 t                    }t                    d}n# t          $ r Y nw xY w|r! fdD             t           ||          S |                    dd          }dk    r9|dk    r3|                    d          s                                          S  j        }	 |dk    r9t           |fi |\  }	}
}| _                             |	          |
z  z  }n|dk    r xj        d	z  c_                             |                    d
d                     fd}                     |dd j	        z  g          }| 
                              z  d j	        z  z  }nt          d|z            | _        n# | _        w xY w|
 S )a  
    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

    FTc                 :    g | ]}                     |          S r   )r%   )r   _r
   s     r   r    zdiff.<locals>.<listcomp>   s#    '''S[[^^'''r   methodstepr   quadr   r   radiusg      ?c                 `                         |           z  }|z   } |          |z  z  S N)expj)treizr
   r   r   r5   r   s      r   gzdiff.<locals>.g   s6    SXXa[[(Gqttc1f}$r   r   zunknown method: %r)list	TypeError_partial_diffr!   r%   r"   r.   r   quadtspi	factorial
ValueError)r
   r   r   r   r'   partialordersr2   r"   r-   r,   r(   vr<   r   r5   s   ````           @r   diffrG   C   s   R GaGG    9''''Q'''S!Q888[[6**FAvv&F""7;;z+B+B"qQ   8DV%+CAq$%J%J'%J%J"FD(CHvq))D!G3AAvHHNHH[[Xt!<!<==F% % % % % % % % % 

1q!CF(m,,ACMM!$$$#&1AA1F:;;;42Is    * 
77:CF 	F(c                      |s
             S t          |          s | S dt          t          |                    D ]|         r n|          fd}d|<   t           |||          S )Nr   c                  @      fd} j         |          fi S )Nc                 B     d          | fz   dz   d          z    S Nr   r   )r9   r   f_argsis    r   innerz1_partial_diff.<locals>.fdiff_inner.<locals>.inner   s0    1vbqbzQD(6!A#$$<799r   rG   )rL   rN   r
   r   rM   r'   orders   ` r   fdiff_innerz"_partial_diff.<locals>.fdiff_inner   sI    	: 	: 	: 	: 	: 	: 	:sxvay%;;7;;;r   )sumrangelenr?   )r
   r   xsrE   r'   rQ   rM   rP   s   ``  ` @@r   r?   r?      s     qss
v;; q"v	A3v;;  !9 	E	1IE< < < < < < < < < F1Ik2vw???r   Nc              +     K   || j         }nt          |          }|                    dd          dk    r-d}||dz   k     r  | j        |||fi |V  |dz  }||dz   k      dS |                    d          }|r|                     ||dd          V  n  ||                     |                    V  |dk     rdS || j         k    rd	\  }}nd|dz   }}	 | j        }	t          | ||||	fi |\  }
}}t          ||          D ]H}	 || _        |                     |
|          ||z  z  }|	| _        n# |	| _        w xY w|
 V  ||k    r dS I|t          |d
z  dz             }}t          ||          })ad  
    Returns a generator that yields the sequence of derivatives

    .. math ::

        f(x), f'(x), f''(x), \ldots, f^{(k)}(x), \ldots

    With ``method='step'``, :func:`~mpmath.diffs` uses only `O(k)`
    function evaluations to generate the first `k` derivatives,
    rather than the roughly `O(k^2)` evaluations
    required if one calls :func:`~mpmath.diff` `k` separate times.

    With `n < \infty`, the generator stops as soon as the
    `n`-th derivative has been generated. If the exact number of
    needed derivatives is known in advance, this is further
    slightly more efficient.

    Options are the same as for :func:`~mpmath.diff`.

    **Examples**

        >>> from mpmath import *
        >>> mp.dps = 15
        >>> nprint(list(diffs(cos, 1, 5)))
        [0.540302, -0.841471, -0.540302, 0.841471, 0.540302, -0.841471]
        >>> for i, d in zip(range(6), diffs(cos, 1)):
        ...     print("%s %s" % (i, d))
        ...
        0 0.54030230586814
        1 -0.841470984807897
        2 -0.54030230586814
        3 0.841470984807897
        4 0.54030230586814
        5 -0.841470984807897

    Nr2   r3   r   r   r   T)r   )r   r   gffffff?)
infr   r!   rG   r%   r"   r.   r   r   min)r
   r   r   r   r'   r   r   ABcallprecyr,   r(   r   s                 r   diffsr]      s     L 	yGFF{{8V$$..!a%ii#(1a..g.....FA !a%ii 	{{:&&H  hhq!Qh......aA1uuCG||11!A#18"31aEEWEE41 	 	A$#NN1a((472#8####"HHHAvv #aeAg,,11IIs   #D11	D:c                 8     t                      g  fd}|S )Nc                     t          t                    | dz             D ]$}                    t                               %|          S rK   )r   rT   appendnext)r   rM   datagens     r   r   ziterable_to_function.<locals>.f,  sJ    D		1Q3'' 	# 	#AKKS		""""Awr   )iter)rc   r   rb   s   ` @r   iterable_to_functionre   )  s9    
s))CD      Hr   c              #     K   t          |          }|dk    r|d         D ]}|V  dS t          |                     |d|dz                               }t          |                     ||dz  d                             }d}	  ||           |d          z  }d}t          d|dz             D ]0}	|||	z
  dz   z  |	z  }|| |||	z
            z   ||	          z  z  }1|V  |dz  }g)aV  
    Given a list of `N` iterables or generators yielding
    `f_k(x), f'_k(x), f''_k(x), \ldots` for `k = 1, \ldots, N`,
    generate `g(x), g'(x), g''(x), \ldots` where
    `g(x) = f_1(x) f_2(x) \cdots f_N(x)`.

    At high precision and for large orders, this is typically more efficient
    than numerical differentiation if the derivatives of each `f_k(x)`
    admit direct computation.

    Note: This function does not increase the working precision internally,
    so guard digits may have to be added externally for full accuracy.

    **Examples**

        >>> from mpmath import *
        >>> mp.dps = 15; mp.pretty = True
        >>> f = lambda x: exp(x)*cos(x)*sin(x)
        >>> u = diffs(f, 1)
        >>> v = mp.diffs_prod([diffs(exp,1), diffs(cos,1), diffs(sin,1)])
        >>> next(u); next(v)
        1.23586333600241
        1.23586333600241
        >>> next(u); next(v)
        0.104658952245596
        0.104658952245596
        >>> next(u); next(v)
        -5.96999877552086
        -5.96999877552086
        >>> next(u); next(v)
        -12.4632923122697
        -12.4632923122697

    r   r   Nr   )rT   re   
diffs_prodr   )
r
   factorsNcurF   r   r   ar   s
             r   rg   rg   2  s*     H 	GAAvv 	 	AGGGG	 	 !A!?!?@@ 1!?!?@@	!qqttAAAac]] ' '1QK1$Q1Q3Z!!A$$&&GGGFA	r   c                 V   | |v r||          S |sddi|d<   t          | dz
            }t          d t          |          D                       }i }t          |          D ]6\  }}|d         dz   f|dd         z   }||v r||xx         |z  cc<   1|||<   7t          |          D ]x\  }}t          |          st	          |          D ]S\  }}|rL|d|         |dz
  ||dz            dz   fz   ||dz   d         z   }	|	|v r||	xx         ||z  z  cc<   K||z  ||	<   Ty||| <   ||          S )z
    nth differentiation polynomial for exp (Faa di Bruno's formula).

    TODO: most exponents are zero, so maybe a sparse representation
    would be better.
    r   r   r   c              3   *   K   | ]\  }}|d z   |fV  dS )rn   Nr   )r   rj   rF   s      r   	<genexpr>zdpoly.<locals>.<genexpr>t  s.      22EQqafQZ222222r   Nr   )dpolydict	iteritemsrR   	enumerate)
r   _cacheRRapowerscountpowers1r   ppowers2s
             r   rq   rq   h  s    	F{{ay !Hq	ac

A22Yq\\22222A	B"1    !9Q;.6!"":-b==wKKK5 KKKKBwKK"1 	* 	*6{{ 	V$$ 	* 	*CAa * !*!F1Q3KM'::VAaCDD\Ib==wKKK1U7*KKKK"#E'BwK	* F1I!9r   c           	   #   `  K   t          |          |                      d                    }|V  d}	 |                     d          }t          t	          |                    D ]9\  }}|||                     fdt          |          D                       z  z  }:||z  V  |dz  }x)a  
    Given an iterable or generator yielding `f(x), f'(x), f''(x), \ldots`
    generate `g(x), g'(x), g''(x), \ldots` where `g(x) = \exp(f(x))`.

    At high precision and for large orders, this is typically more efficient
    than numerical differentiation if the derivatives of `f(x)`
    admit direct computation.

    Note: This function does not increase the working precision internally,
    so guard digits may have to be added externally for full accuracy.

    **Examples**

    The derivatives of the gamma function can be computed using
    logarithmic differentiation::

        >>> from mpmath import *
        >>> mp.dps = 15; mp.pretty = True
        >>>
        >>> def diffs_loggamma(x):
        ...     yield loggamma(x)
        ...     i = 0
        ...     while 1:
        ...         yield psi(i,x)
        ...         i += 1
        ...
        >>> u = diffs_exp(diffs_loggamma(3))
        >>> v = diffs(gamma, 3)
        >>> next(u); next(v)
        2.0
        2.0
        >>> next(u); next(v)
        1.84556867019693
        1.84556867019693
        >>> next(u); next(v)
        2.49292999190269
        2.49292999190269
        >>> next(u); next(v)
        3.44996501352367
        3.44996501352367

    r   r   c              3   D   K   | ]\  }}| |d z             |z  V  dS )r   Nr   )r   r   r{   fns      r   rp   zdiffs_exp.<locals>.<genexpr>  s<      LLEQq!LRR!WWaZLLLLLLr   )re   expmpfrs   rq   fprodrt   )r
   fdiffsf0rM   r   rx   rj   r   s          @r   	diffs_expr     s      X 
f	%	%B	AB
HHH	AGGAJJ"588,, 	M 	MIFA399LLLLYv5F5FLLLLLLLAA"f	Qr   r   c           	          t          t                                                    |                              dz   d          }||z
  dz
   fd}                     |||                               ||z
            z  S )a	  
    Calculates the Riemann-Liouville differintegral, or fractional
    derivative, defined by

    .. math ::

        \,_{x_0}{\mathbb{D}}^n_xf(x) = \frac{1}{\Gamma(m-n)} \frac{d^m}{dx^m}
        \int_{x_0}^{x}(x-t)^{m-n-1}f(t)dt

    where `f` is a given (presumably well-behaved) function,
    `x` is the evaluation point, `n` is the order, and `x_0` is
    the reference point of integration (`m` is an arbitrary
    parameter selected automatically).

    With `n = 1`, this is just the standard derivative `f'(x)`; with `n = 2`,
    the second derivative `f''(x)`, etc. With `n = -1`, it gives
    `\int_{x_0}^x f(t) dt`, with `n = -2`
    it gives `\int_{x_0}^x \left( \int_{x_0}^t f(u) du \right) dt`, etc.

    As `n` is permitted to be any number, this operator generalizes
    iterated differentiation and iterated integration to a single
    operator with a continuous order parameter.

    **Examples**

    There is an exact formula for the fractional derivative of a
    monomial `x^p`, which may be used as a reference. For example,
    the following gives a half-derivative (order 0.5)::

        >>> from mpmath import *
        >>> mp.dps = 15; mp.pretty = True
        >>> x = mpf(3); p = 2; n = 0.5
        >>> differint(lambda t: t**p, x, n)
        7.81764019044672
        >>> gamma(p+1)/gamma(p-n+1) * x**(p-n)
        7.81764019044672

    Another useful test function is the exponential function, whose
    integration / differentiation formula easy generalizes
    to arbitrary order. Here we first compute a third derivative,
    and then a triply nested integral. (The reference point `x_0`
    is set to `-\infty` to avoid nonzero endpoint terms.)::

        >>> differint(lambda x: exp(pi*x), -1.5, 3)
        0.278538406900792
        >>> exp(pi*-1.5) * pi**3
        0.278538406900792
        >>> differint(lambda x: exp(pi*x), 3.5, -3, -inf)
        1922.50563031149
        >>> exp(pi*3.5) / pi**3
        1922.50563031149

    However, for noninteger `n`, the differentiation formula for the
    exponential function must be modified to give the same result as the
    Riemann-Liouville differintegral::

        >>> x = mpf(3.5)
        >>> c = pi
        >>> n = 1+2*j
        >>> differint(lambda x: exp(c*x), x, n)
        (-123295.005390743 + 140955.117867654j)
        >>> x**(-n) * exp(c)**x * (x*c)**n * gammainc(-n, 0, x*c) / gamma(-n)
        (-123295.005390743 + 140955.117867654j)


    r   c                 @                           fd g          S )Nc                 ,    | z
  z   |           z  S r7   r   )r9   r   rr   s    r   <lambda>z-differint.<locals>.<lambda>.<locals>.<lambda>  s    acAX!_ r   )r4   )r   r
   r   r   x0s   `r   r   zdifferint.<locals>.<lambda>  s*    #((444444r1g>> r   )maxr   ceilrerG   gamma)r
   r   r   r   r   mr<   r   s   ``  `  @r   	differintr     s    H 	C##$$Q&**A	!AA>>>>>>>A88Aq!syy1~~--r   c                 .     dk    rS  fd}|S )a3  
    Given a function `f`, returns a function `g(x)` that evaluates the nth
    derivative `f^{(n)}(x)`::

        >>> from mpmath import *
        >>> mp.dps = 15; mp.pretty = True
        >>> cos2 = diffun(sin)
        >>> sin2 = diffun(sin, 4)
        >>> cos(1.3), cos2(1.3)
        (0.267498828624587, 0.267498828624587)
        >>> sin(1.3), sin2(1.3)
        (0.963558185417193, 0.963558185417193)

    The function `f` must support arbitrary precision evaluation.
    See :func:`~mpmath.diff` for additional details and supported
    keyword options.
    r   c                 $     j         | fi S r7   rO   )r   r
   r   r   r'   s    r   r<   zdiffun.<locals>.g  s!    sx1a++7+++r   r   )r
   r   r   r'   r<   s   ```` r   diffunr   	  sC    & 	Avv, , , , , , , ,Hr   c                      t            j        |||fi |          }|                    dd          r fd|D             S  fd|D             S )a  
    Produces a degree-`n` Taylor polynomial around the point `x` of the
    given function `f`. The coefficients are returned as a list.

        >>> from mpmath import *
        >>> mp.dps = 15; mp.pretty = True
        >>> nprint(chop(taylor(sin, 0, 5)))
        [0.0, 1.0, 0.0, -0.166667, 0.0, 0.00833333]

    The coefficients are computed using high-order numerical
    differentiation. The function must be possible to evaluate
    to arbitrary precision. See :func:`~mpmath.diff` for additional details
    and supported keyword options.

    Note that to evaluate the Taylor polynomial as an approximation
    of `f`, e.g. with :func:`~mpmath.polyval`, the coefficients must be reversed,
    and the point of the Taylor expansion must be subtracted from
    the argument:

        >>> p = taylor(exp, 2.0, 10)
        >>> polyval(p[::-1], 2.5 - 2.0)
        12.1824939606092
        >>> exp(2.5)
        12.1824939607035

    chopTc                 l    g | ]0\  }}                     |                              |          z  1S r   )r   rB   r   rM   r   r
   s      r   r    ztaylor.<locals>.<listcomp>@  s8    ===ACMM!,,,===r   c                 F    g | ]\  }}|                     |          z  S r   )rB   r   s      r   r    ztaylor.<locals>.<listcomp>B  s.    333tq!#--"""333r   )rt   r]   r!   )r
   r   r   r   r'   rc   s   `     r   taylorr   "  st    8 ICIaA1111
2
2C{{64   4========3333s3333r   c                    t          |          ||z   dz   k     rt          d          |dk    r+|dk    r| j        g| j        gfS |d|dz            | j        gfS |                     |          }t	          |          D ];}t	          t          |||z   dz                       D ]}|||z   |z
           |||f<   <|                     ||dz   ||z   dz                       }|                     ||          }| j        gt          |          z   }	dg|dz   z  }
t	          |dz             D ]J}||         }t	          dt          ||          dz             D ]}||	|         |||z
           z  z  }||
|<   K|
|	fS )a  
    Computes a Pade approximation of degree `(L, M)` to a function.
    Given at least `L+M+1` Taylor coefficients `a` approximating
    a function `A(x)`, :func:`~mpmath.pade` returns coefficients of
    polynomials `P, Q` satisfying

    .. math ::

        P = \sum_{k=0}^L p_k x^k

        Q = \sum_{k=0}^M q_k x^k

        Q_0 = 1

        A(x) Q(x) = P(x) + O(x^{L+M+1})

    `P(x)/Q(x)` can provide a good approximation to an analytic function
    beyond the radius of convergence of its Taylor series (example
    from G.A. Baker 'Essentials of Pade Approximants' Academic Press,
    Ch.1A)::

        >>> from mpmath import *
        >>> mp.dps = 15; mp.pretty = True
        >>> one = mpf(1)
        >>> def f(x):
        ...     return sqrt((one + 2*x)/(one + x))
        ...
        >>> a = taylor(f, 0, 6)
        >>> p, q = pade(a, 3, 3)
        >>> x = 10
        >>> polyval(p[::-1], x)/polyval(q[::-1], x)
        1.38169105566806
        >>> f(x)
        1.38169855941551

    r   z%L+M+1 Coefficients should be providedr   N)rT   rC   onematrixrS   rX   lu_solver=   )r
   rl   LMrY   jrM   rF   r   qr{   r   s               r   pader   D  s   P 1vv!A~~@AAAAvv66G9swi''TacT7SWI%% 	

1A1XX  s1ac!e}}%% 	 	A!AhAadGG		AqsQqSUm$	%	%%AQA		DGGA	
QqS	A1Q3ZZ  aDq#a((Q,'' 	 	A1a!fAA!a4Kr   )r   r7   )r   r   )libmp.backendr   calculusr   rr   rs   AttributeErroritemsr   r.   rG   r?   r]   re   rg   rq   r   r   r   r   r   r   r   r   <module>r      s   " " " " " "      II   
III   "! ! !H H H H HT@ @ @" G G G GR   3 3 3j     B 4 4 4l F. F. F. F.P    0 4 4 4B B B B B Bs    %%