
    Џkh<                     n    d dl Zd dlmZmZmZmZ d dlmc m	Z
 d dlmZ d dlmZ ddZd Zdddd	d
dZy)    N)array_namespacexp_ravelxp_copy
xp_promote)_RichResult)specialc                     |t        | |      n|}|j                  | |      \  } }|j                  | |fd      }t        j                  |d      S )Nr   axis)r   broadcast_arraysstackr   	logsumexp)xyxpxys       [/var/www/teggl/fontify/venv/lib/python3.12/site-packages/scipy/stats/_continued_fraction.py
_logaddexpr      sS    "$*A	"Bq!$DAq	1a&q	!BRa((    c                    t        |       rt        |      st        d      t        j                  |      s|f} | dg|  |dg| }}t	        ||g| }t        ||g|dd|d^}}}|j                  |j                  }
}	d ||ft        |      z   D        ^}}}|i n|}|j                  dd       }|j                  dd       }d}t        j                  ||nd	||nd	g      }t        j                  |j                  t        j                         xs. t        j                  |j                  t        j                        }|st        j                  |dk        nd
}t        j                  t        j                   |             }|j                  dk7  }|s|s|s|rt        |      t#        |      }||k7  s|dk  rt        d      t%        |t&              st        d      | |||||||||	|
|fS )Nz`a` and `b` must be callable.r   T)force_floating	broadcastr   c              3   2   K   | ]  }t        |        y wN)r   ).0args     r   	<genexpr>z)_continued_fraction_iv.<locals>.<genexpr>'   s     EsXc]Es   epstinyzX`eps` and `tiny` must be (or represent the logarithm of) finite, positive, real scalars.   F)   z)`maxiter` must be a non-negative integer.z`log` must be boolean.)callable
ValueErrornpiterabler   r   shapedtypetuplegetasarray
issubdtypenumbercomplexfloatinganyallisfiniteint
isinstancebool)abargs
tolerancesmaxiterloga0b0r   r&   r'   r   r   messagetolsnot_realnot_positive
not_finite
not_scalarmaxiter_ints                       r   _continued_fraction_ivrC      s    A;hqk899;;tw q[4[!A++B	R	'$	'Br2 & &TT"$&MBT88RXX5EEr2ht.DEMBT!)zJ
..
%C>>&$'D1G::cos1#/tQ8 9DMM$**bii88 A==R-?-?@ ,/266$!)$ULVVBKK-..Jt#J<:!!g,K+1DEEc4 122asD'3BubHHr    d   F)r6   r7   r8   r9   c                    t         |||      }|\   }}}}}	}
d} dfd
 dfd
 fd}j                  |t        j                  j                        }d\  }}|d	n|}|Ksj                        j                  n-t        j                  j                        j                        }Qsj                        j                  d
z  n0d
t        j                  j                        j                        z  rj                   nd}j                  |	|k(  |	      }t        |      }j                  ||      }j                  |j                        }t        d||||||||
      }g d}fd}fd}fd}d }fd}t        j                  |||
|||||||||      S )a!  Evaluate a generalized continued fraction numerically.

    `_continued_fraction` iteratively evaluates convergents of a continued fraction
    given coefficients returned by callables `a` and `b`. Iteration terminates when
    `maxiter` terms have been evaluated or a termination criterion controlled by
    `tolerances` is satisfied, and the final convergent is returned as the ``f``
    attribute of the result object.

    This function works elementwise when `args` contains (broadcastable) arrays.

    Parameters
    ----------
    a, b: callable
        Functions that provide the *numerator* and *denominator* coefficients of
        the continued fraction, respectively.

        The signature of each must be::

            a(n: int, *argsj) -> ndarray

        where ``n`` is the coefficient number and ``argsj`` is a tuple, which may
        contain an arbitrary number of arrays of any shape. `a` and `b` must be
        elementwise functions: each scalar element ``a(n, *argsj)[i]`` must equal
        ``a(n, *[argj[i] for argj in argsj])`` for valid indices ``i``.
        `a` and `b` must not mutate the arrays in ``argsj``.

        The result shape is the broadcasted shape of ``a(0, *args)`` and
        ``b(0, *args)``. The dtype used throughout computation is the result dtype
        of these terms if it is a float, and the default float of the array library
        otherwise. The numerical value of ``a(0, *args)`` is ignored, and
        the value of the leading term ``b(0, *args)`` is the so-called "integer"
        part of the continued fraction (although it need not be integral).

    args : tuple of array_like, optional
        Additional positional *array* arguments to be passed to `a` and `b`. Arrays
        must be broadcastable with one another. If the coefficient callables
        require additional arguments that are not broadcastable with one
        another, wrap them with callables `a` and `b` such that `a` and `b` accept
        only ``n`` and broadcastable array arguments.
    tolerances : dictionary of floats, optional
        Tolerances and numerical thresholds used by the algorithm. Currently,
        valid keys of the dictionary are:

        - ``eps`` - the convergence threshold of Lentz' algorithm
        - ``tiny`` - not strictly a "tolerance", but a very small positive number
          used to avoid division by zero

        The default `eps` is the precision of the appropriate dtype, and the default
        `tiny` is the precision squared. [1]_ advises that ``eps`` is "as small as
        you like", but for most purposes, it should not be set smaller than the default
        because it may prevent convergence of the algorithm. [1]_ also advises that
        ``tiny`` should be less than typical values of ``eps * b(n)``, so the default
        is a good choice unless the :math:`b_n` are very small. See [1]_ for details.
    maxiter : int, default: 100
        The maximum number of iterations of the algorithm to perform.
    log : bool, default: False
        If True, `a` and `b` return the (natural) logarithm of the terms, `tolerances`
        contains the logarithm of the tolerances, and the result object reports the
        logarithm of the convergent.

    Returns
    -------
    res : _RichResult
        An object similar to an instance of `scipy.optimize.OptimizeResult` with the
        following attributes. The descriptions are written as though the values will
        be scalars; however, if `f` returns an array, the outputs will be
        arrays of the same shape.

        success : bool array
            ``True`` where the algorithm terminated successfully (status ``0``);
            ``False`` otherwise.
        status : int array
            An integer representing the exit status of the algorithm.

            - ``0`` : The algorithm converged to the specified tolerances.
            - ``-2`` : The maximum number of iterations was reached.
            - ``-3`` : A non-finite value was encountered.

        f : float array
            The convergent which satisfied a termination criterion.
        nit : int array
            The number of iterations of the algorithm that were performed.
        nfev : int array
            The number of terms that were evaluated.

    Notes
    -----
    A generalized continued fraction is an expression of the form

    .. math::

        b_0 + \frac{a_1}{b_1 + \frac{a_2}{b_2 + \frac{a_3}{b_3 + \cdots}}}

    Successive "convergents" approximate the infinitely recursive continued fraction
    with a finite number of terms :math:`a_n` and :math:`b_n`, which are provided
    by callables `a` and `b`, respectively. This implementation follows the modified
    Lentz algorithm ([1]_, [2]_) to evaluate successive convergents until a
    termination condition is satisfied.

    References
    ----------
    .. [1] Press, William H., and Saul A. Teukolsky. "Evaluating continued fractions
           and computing exponential integrals." Computers in Physics 2.5 (1988): 88-89.
    .. [2] Lentz's algorithm. Wikipedia.
           https://en.wikipedia.org/wiki/Lentz%27s_algorithm
    .. [3] Continued fraction. Wikipedia.
           https://en.wikipedia.org/wiki/Continued_fraction
    .. [4] Generalized continued fraction. Wikipedia.
           https://en.wikipedia.org/wiki/Generalized_continued_fraction

    Examples
    --------
    The "simple continued fraction" of :math:`\pi` is given in [3]_ as

    .. math::

        3 + \frac{1}{7 + \frac{1}{15 + \frac{1}{1 + \cdots}}}

    where the :math:`b_n` terms follow no obvious pattern:

    >>> b = [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1]

    and the :math:`a_n` terms are all :math:`1`.
    In this case, all the terms have been precomputed, so we call `_continued_fraction`
    with simple callables which simply return the precomputed coefficients:

    >>> import numpy as np
    >>> from scipy.special._continued_fraction import _continued_fraction
    >>> res = _continued_fraction(a=lambda n: 1, b=lambda n: b[n], maxiter=len(b) - 1)
    >>> (res.f - np.pi) / np.pi
    np.float64(7.067899292141148e-15)

    A generalized continued fraction for :math:`\pi` is given by:

    .. math::

        3 + \frac{1^2}{6 + \frac{3^2}{6 + \frac{5^2}{6 + \cdots}}}

    We define the coefficient callables as:

    >>> def a(n):
    ...     return (2*n - 1)**2
    >>>
    >>> def b(n):
    ...     if n == 0:
    ...         return 3
    ...     else:
    ...         return 6

    Then the continued fraction can be evaluated as:

    >>> res = _continued_fraction(a, b)
    >>> res
         success: False
          status: -2
               f: 3.1415924109719846
             nit: 100
            nfev: 101

    Note that the requested tolerance was not reached within the (default)
    maximum number of iterations because it converges very slowly.
    An expression that converges more rapidly is expressed as the difference
    between two continued fractions. We will compute both of them in one
    vectorized call to `_continued_fraction`.

    >>> u, v = 5, 239
    >>>
    >>> def a(n, a1, _):
    ...     # The shape of the output must be the shape of the arguments
    ...     shape = a1.shape
    ...     if n == 0:
    ...         return np.zeros(shape)
    ...     elif n == 1:
    ...         return a1
    ...     else:
    ...         return np.full(shape, (n-1)**2)
    >>>
    >>> def b(n, _, uv):
    ...     shape = uv.shape
    ...     if  n == 0:
    ...         return np.zeros(shape)
    ...     return np.full(shape, (2*n - 1)*uv)
    >>>
    >>> res = _continued_fraction(a, b, args=([16, 4], [u, v]))
    >>> res
         success: [ True  True]
          status: [0 0]
               f: [ 3.158e+00  1.674e-02]
             nit: [10  4]
            nfev: [11  5]

    Note that the second term converged in fewer than half the number of iterations
    as the first. The approximation of :math:`\pi` is the difference between the two:

    >>> pi = res.f[0] - res.f[1]
    >>> (pi - np.pi) / np.pi
    np.float64(2.8271597168564594e-16)

    If it is more efficient to compute the :math:`a_n` and :math:`b_n` terms together,
    consider instantiating a class with a method that computes both terms and stores
    the results in an attribute. Separate methods of the class retrieve the
    coefficients, and these methods are passed to `_continued_fraction` as arguments
    `a` and `b`. Similarly,if the coefficients can be computed recursively in terms of
    previous coefficients, use a class to maintain state between callable evaluations.

    N)r4   c                b    t        j                  t        |             d         }  || g| S Nr   r1   realr   )nr4   r6   r   s      r   r4   z_continued_fraction.<locals>.a  -    $Q'({T{r   )r5   c                b    t        j                  t        |             d         }  || g| S rH   rI   )rK   r5   r6   r   s      r   r5   z_continued_fraction.<locals>.b#  rL   r   c                 J    j                   | g|  | g| fd      S )Nr
   )r   )rK   r6   r4   r5   r   s     r   funcz!_continued_fraction.<locals>.func'  s+    xx1takDk2x<<r   r'   )r   r    rE   r!   r   )
rK   fnCnm1Dnm1CnDnr   r   nitnfevstatus))rX   rX   )frR   )rV   rV   )rW   rW   c                     j                  j                  | j                  dz         d      | _        | j                  S )Nr    )rO   )reshaper*   rK   )workr   s    r   pre_func_evalz*_continued_fraction.<locals>.pre_func_evalE  s/    BJJtvvz2E:vvr   c                    |d   |d   }}	sdnj                    }	s|||j                  z  z   nt        |||j                  z         }
|||k(  <   	sd|z  n| }	s|||j                  z  z   nt        |||j                  z
        }
|||k(  <   	s||z  n||z   |_        	s|j
                  |j                  z  n|j
                  |j                  z   |_        ||c|_        |_        y )N).r   ).r    r   r   r    )infrT   r   rS   rU   rR   )rK   abr\   anbnzerodenominatorDnCnr9   r   r   s            r   post_func_evalz+_continued_fraction.<locals>.post_func_evalI  s    FRZBq"&& 14rBtyyL(&r2		>bA 	+/K4'(#&am< 	 *-b2		>!b"tyy.R8 	2: %(R"Wr' 		.1477TYY&$))+ 	  "2	49r   c                    j                  | j                  j                        }r)j                  | j                  j                  dz        nd }sj                  | j                  dz
        n&j                  t        | j                  |            }|| j                  k  }t        j                  | j                  |<   d||<   sj                  | j                         n6j                  | j                        | j                  j                   k(  z   }t        j                  | j                  |<   d||<   |S )NrQ   y              ?r    r_   T)
zeros_likerU   r3   	full_likepiabsrJ   r   r   eim_ECONVERGEDrX   r0   rR   r`   
_EVALUEERR)r\   stoppijresidualir9   r   s        r   check_terminationz._continued_fraction.<locals>.check_terminationc  s    }}TYYbgg}6 47bll499beeBh/D14BFF499q=)DIIsr!BC 	txxAQ +.bkk$''""KK(DGGw,>?@ 	
AQr   c                      y r   rD   )r\   s    r   post_termination_checkz3_continued_fraction.<locals>.post_termination_checkw  s    r   c                 ~    j                  | d         | d<   | d   j                  dk(  r| d   d   n| d   | d<   |S )NrY   rQ   r   rD   )r*   ndim)resr&   r'   r   s     r   customize_resultz-_continued_fraction.<locals>.customize_resultz  sH    ::c#he:4C#&s8==A#53s8B<3s8Cr   r_   )rC   rk   rn   _EINPROGRESSint32finfor   r$   r9   r`   wherer   r   _loop)r4   r5   r6   r7   r8   r9   rz   r   r:   r;   r&   callbackrP   rX   rV   rW   rd   rR   rS   rT   rU   r\   res_work_pairsr]   rh   ru   rw   r{   r'   r   r   s   ``   `                      @@@r   _continued_fractionr   D   s   ` !AtZ#
FCDGAAq$T7CRrH    = \\"c..bhh\?FIC_c'G {),bhhuo!!"&&%9L9L2M |-0rxx""A%arxx?R?R8S6S BFF7qD	"*dB	'B2;D<<D!D<<BFF#Dr4dTT&:D8N&4( 99T8UGT4"N4E+-=~ r   r   )numpyr$   scipy._lib._array_apir   r   r   r   (scipy._lib._elementwise_iterative_method_lib_elementwise_iterative_methodrn   scipy._lib._utilr   scipyr   r   rC   r   rD   r   r   <module>r      s=      7 6 ( ))IX ')T3E r   