
    Ti"                        U d Z ddlZddlZddlZddlZddlZddlmZmZm	Z	 ddlm
Z
 ddlmZ ddlmZ ddlmZmZmZ ddlZddlmZ ddlmZ dd	lmZmZmZmZmZ m!Z"m#Z$m%Z&m'Z(m)Z*m+Z, dd
l-m.Z. ddl/m0Z0 g dZ1ej2        3                    dd          Z4e5e6z  e7d<   ej2        3                    dd          Z8e4e8dZ9eZ:ee7d<   e:ej;        z  Z;ee7d<   dee;         de	e:         fdZ<de:deddfdZ=de:defdZ>	 	 	 d(ddddde;deded         dz  de6dz  dedz  d e6d!e6de:fd"Z?dd#d$e:dedz  de:fd%Z@ ed&          ZAee         e7d'<   e
deded(         fd)            ZBd[d*ZCd+d+d+d+d,d-ZDd. ZEd+d+d+d+d/dd0d1ZFddd+d+d+d+d/dd2d3ZGd+d+d+d+d/d+dd4d5ZHd\d7ZId]d9ZJd:ede5fd;ZKd$e:dede6fd<ZLdededz  fd=ZMddd>dd?d$e:d@eNeOeN         z  dz  dAe6dBeNePz  dedz  de:fdCZQdd#d$e:dedz  de:fdDZRd[dEZSddFdGZTdddHdIZUd[dJe:dedz  de:fdKZVdL ZWdM ZXdN ZY ejZ        dO           G dP dQ                      Z[	 	 	 	 	 d^dSZ\dT Z]ddRdRddddRdRdd+dU
dVZ^ddWdXZ_ddWdYZ`ddWdZZai ZbdS )_a6  Utility functions to use Python Array API compatible libraries.

For the context about the Array API see:
https://data-apis.org/array-api/latest/purpose_and_scope.html

The SciPy use case of the Array API is described on the following page:
https://data-apis.org/array-api/latest/use_cases.html#use-case-scipy
    N)	GeneratorIterableIterator)contextmanager)
ContextVar)
ModuleType)AnyLiteral	TypeAlias)array_api_compat)is_array_api_objis_lazy_arraysizenumpydeviceis_numpy_namespaceis_cupy_namespaceis_torch_namespaceis_jax_namespaceis_dask_namespaceis_array_api_strict_namespace)issparse)FunctionDoc)_asarrayarray_namespaceassert_almost_equalassert_array_almost_equal
default_xpeager_warnsr   	is_marrayis_array_api_strict
is_complexis_cupyis_jaxis_numpyis_torchSCIPY_ARRAY_APISCIPY_DEVICEscipy_namespace_forxp_assert_closexp_assert_equalxp_assert_lessxp_copy	xp_devicexp_ravelxp_sizexp_unsupported_param_msgxp_vector_normxp_capabilitiesxp_result_type
xp_promoter'   Fr(   cpu)r'   r(   Array	ArrayLikearraysreturnc              #   d  K   | D ]}|t          |          rd}t          |          t          |t          j        j                  rt          d          t          |t          j                  rt          d          t          |t          j        t          j	        z            rX|j
        }t          j        |t          j                  s2t          j        |t          j                  st          d|d          t          |          r|V  	 t          j        |          }n# t          $ r t          d          w xY w|j
        }t          j        |t          j                  s4t          j        |t          j                  sd|d}t          |          |j        r|V  dS )	a  Raise exceptions on known-bad subclasses. Discard 0-dimensional ArrayLikes
    and convert 1+-dimensional ArrayLikes to numpy.

    The following subclasses are not supported and raise and error:
    - `numpy.ma.MaskedArray`
    - `numpy.matrix`
    - NumPy arrays which do not have a boolean or numerical dtype
    - Any array-like which is neither array API compatible nor coercible by NumPy
    - Any array-like which is coerced by NumPy to an unsupported dtype
    NzSparse arrays/matrices are not supported by this function. Perhaps one of the `scipy.sparse.linalg` functions would work instead.z8Inputs of type `numpy.ma.MaskedArray` are not supported.z0Inputs of type `numpy.matrix` are not supported.zAn argument has dtype `z3`; only boolean and numerical dtypes are supported.zCAn argument is neither array API compatible nor coercible by NumPy.z1An argument was coerced to an unsupported dtype `)r   
ValueError
isinstancenpmaMaskedArray	TypeErrormatrixndarraygenericdtype
issubdtypenumberbool_r   
asanyarrayndim)r9   arraymsgrE   messages        m/var/www/development/aibuddy-work/election-extract/venv/lib/python3.11/site-packages/scipy/_lib/_array_api.py_compliance_scipyrO   D   s       * *= E?? 	")C S//!eRU.// 	XVWWWeRY'' 	PNOOOeRZ"*455 	UKEM%33 Ur}UBH7U7U U !T% !T !T !T U U U E"" 	KKKK7e,, 7 7 7 !6 7 7 77 KEM%33 )r}UBH7U7U )H H H H   ((( z U* *s   D,,ErK   xpc                 x    |                     |                    |                     sd}t          |          dS )zCheck for NaNs or Infs.z#array must not contain infs or NaNsN)allisfiniter<   )rK   rP   rL   s      rN   _check_finiterT   |   s=    66"++e$$%% 3oo     c                      t           d         st          S t          t          |                     }|rt	          j        | S t          S )a1  Get the array API compatible namespace for the arrays xs.

    Parameters
    ----------
    *arrays : sequence of array_like
        Arrays used to infer the common namespace.

    Returns
    -------
    namespace : module
        Common namespace.

    Notes
    -----
    Thin wrapper around `array_api_compat.array_namespace`.

    1. Check for the global switch: SCIPY_ARRAY_API. This can also be accessed
       dynamically through ``_GLOBAL_CONFIG['SCIPY_ARRAY_API']``.
    2. `_compliance_scipy` raise exceptions on known-bad subclasses. See
       its definition for more details.

    When the global switch is False, it defaults to the `numpy` namespace.
    In that case, there is no compliance check. This is a convenience to
    ease the adoption. Otherwise, arrays must comply with the new rules.
    r'   )_GLOBAL_CONFIG	np_compatlistrO   r   r   )r9   
api_arrayss     rN   r   r      sL    4 +, '//00J  =/<<rU   )rP   check_finitesubokrE   order)KACFcopyr[   r\   c                   |t          |           }t          |          rO|du rt          j        | |||          } n|rt          j        | ||          } n|t          j        | ||          } nd	 |                    | ||          } nJ# t          $ r= t          |                    d                    }|                    | ||          } Y nw xY w|rt          | |           | S )a`  SciPy-specific replacement for `np.asarray` with `order`, `check_finite`, and
    `subok`.

    Memory layout parameter `order` is not exposed in the Array API standard.
    `order` is only enforced if the input array implementation
    is NumPy based, otherwise `order` is just silently ignored.

    `check_finite` is also not a keyword in the array API standard; included
    here for convenience rather than that having to be a separate function
    call inside SciPy functions.

    `subok` is included to allow this function to preserve the behaviour of
    `np.asanyarray` for NumPy based inputs.
    NT)r]   rE   r\   )r]   rE   )rE   rb      )r   r%   r>   rK   rI   asarrayrA   rT   )rK   rE   r]   rb   rP   r[   r\   
coerced_xps           rN   r   r      s   0 
zU##|| F4<<HU%uEJJJEE 	@M%uEBBBEEJuE???EE	FJJuEJ==EE 	F 	F 	F(A77J&&uE&EEEEE	F  !eR   Ls   1B
 
ACCrP   xc                H    |t          |           }t          | d|          S )a3  
    Copies an array.

    Parameters
    ----------
    x : array

    xp : array_namespace

    Returns
    -------
    copy : array
        Copied array

    Notes
    -----
    This copy function does not offer all the semantics of `np.copy`, i.e. the
    `subok` and `order` keywords are not used.
    NT)rb   rP   )r   r   rh   rP   s     rN   r-   r-      s+    , 
zQADR((((rU   _default_xp_default_xp_ctxvar)NNNc              #      K   t                               |           }	 dV  t                               |           dS # t                               |           w xY w)a  In all ``xp_assert_*`` and ``assert_*`` function calls executed within this
    context manager, test by default that the array namespace is
    the provided across all arrays, unless one explicitly passes the ``xp=``
    parameter or ``check_namespace=False``.

    Without this context manager, the default value for `xp` is the namespace
    for the desired array (the second parameter of the tests).
    N)rl   setreset)rP   tokens     rN   r   r      s^       ""2&&E(  '''''  ''''s	   > Ac                     ddl }d}t          |           rt          j                    S |                    ||          S )z@pytest.warns context manager, but only if x is not a lazy array.r   NF)match)pytestr   
contextlibnullcontextwarns)rh   warning_typerr   rs   __thread_safe__s        rN   r   r     sG    MMM OQ (%'''<<E<222rU   Tcheck_namespacecheck_dtypecheck_shapecheck_0dc                   d}|:	 t                                           }n# t          $ r t          |          }Y nw xY w|rt	          | ||           t          |          r|rdt          |            dt          |           }|                    |           r|                    |          s4|                    |           s|                    |          r
J |            |                    |           } |                    |          }|r,d| j	         d|j	         }| j	        |j	        k    s
J |            |rct          |          r(|                                  |                                 d| j         d|j         }| j        |j        k    s
J |            |                    || j                  }| ||fS )NTz$Array-ness does not match:
 Actual: z
 Desired: zdtypes do not match.
Actual: 

Desired: zShapes do not match.
Actual: )rl   getLookupErrorr   _assert_matching_namespacer%   typeisscalarre   rE   is_daskcompute_chunk_sizesshapebroadcast_to)	actualdesiredrP   rz   r{   r|   r}   __tracebackhide___msgs	            rN   _strict_checkr     s    	z	*#''))BB 	* 	* 	* ))BBB	*  8"67B777 || Q Q=<<= =-1']]= =V$$ 	QW)=)= 	QF++	Q46KK4H4H	Q 	QLP	Q 	Q 	Q ZZFjj!!G 3XXXXX|w},,,d,,, 32;; 	*&&((('')))XXXXX|w},,,d,,,oogv|44G7Bs     <<c                     d}t          |          }d|j         d|j         }||k    s
J |            t          |           }d|j         d|j         }||k    s
J |            d S )NTzNamespace of desired array does not match expectations set by the `default_xp` context manager or by the `xp`pytest fixture.
Desired array's space: z
Expected namespace: z=Namespace of actual and desired arrays do not match.
Actual: r   )r   __name__)r   r   rP   r   desired_arr_spacer   actual_arr_spaces          rN   r   r   ;  s    '001 '8&@1 1 $&;	1 1D
 """D"""&v..&'0& && &D r!!!4!!!!!rU    )rz   r{   r|   r}   err_msgrP   c          	      J   d}t          | ||||||          \  } }}t          |          r|j                            | ||          S t	          |          r+|dk    rd n|}|j                            | |dddd|          S t          j                            | ||          S )NTry   )r   r   r   Frtolatol	equal_nanr{   rL   )r   r#   testingassert_array_equalr&   assert_closer>   )	r   r   rz   r{   r|   r}   r   rP   r   s	            rN   r+   r+   M  s    '_[  FGR r{{ Gz,,VWg,NNN	" G "R--$$Wz&&vwQQRV38g ' G G 	G :(('(JJJrU   )r   r   rz   r{   r|   r}   r   rP   c          	         d}
t          | ||	||||          \  } }}	|	                    | j        d          }|(|r&|	                    | j                  j        dz  dz  }n|d}t          |	          r|	j                            | ||||          S t          |	          r+|dk    rd n|}|	j        	                    | |||dd	|
          S t          j                            | ||||          S )NTry   real floatingcomplex floating      ?   gHz>)r   r   r   r   Fr   )r   isdtyperE   finfoepsr#   r   assert_allcloser&   r   r>   )r   r   r   r   rz   r{   r|   r}   r   rP   r   floatings               rN   r*   r*   c  sA    ''[(  FGR zz&,(MNNH|| xx%%)3.2	r{{ Wz))&'/3W * F F 	F	" W!R--$$Wz&&vwT155g ' W W 	W :%%fgD+/ & B B BrU   )rz   r{   r|   r}   r   verboserP   c          	         d}	t          | ||||||          \  } }}t          |          r|j                            | |||          S t	          |          rH| j        j        dk    r|                                 } |j        j        dk    r|                                }t          j                            | |||          S )NTry   )r   r   r6   )	r   r#   r   assert_array_lessr&   r   r   r6   r>   )
r   r   rz   r{   r|   r}   r   r   rP   r   s
             rN   r,   r,     s    '_[  FGR r{{ $z++FG4;W , N N 	N	" $=&&ZZ\\F>%''kkmmG:''07 ( J J JrU      c                 D    ddd| z  z  }}t          | |g|R ||ddd|S zPBackwards compatible replacement. In new code, use xp_assert_close instead.
    r   g      ?
   F)r   r   r{   r|   r*   r   r   decimalargskwdsr   r   s          rN   r   r     W     CgX&$D67 * * * $4UPU* *$(* * *rU      c                 D    ddd| z  z  }}t          | |g|R ||ddd|S r   r   r   s          rN   r   r     r   rU   paramc                     d| dS )Nz
Providing z$ is only supported for numpy arrays. )r   s    rN   r1   r1     s    EEEEErU   c                 8    |                     | j        d          S )Nr   )r   rE   rj   s     rN   r"   r"     s    ::ag1222rU   c                     t          |           rddl}|j        S t          |           rddl}|j        S t          |           r| S dS )a  Return the `scipy`-like namespace of a non-NumPy backend

    That is, return the namespace corresponding with backend `xp` that contains
    `scipy` sub-namespaces like `linalg` and `special`. If no such namespace
    exists, return ``None``. Useful for dispatching.
    r   N)r#   cupyxscipyr$   jaxr&   )rP   r   r   s      rN   r)   r)     sZ     r{{ {bzz 


y|| 	4rU      )axiskeepdimsordrP   r   r   r   c               d   |t          |           n|}t          rtt          |d          r|j                            | |||          S |dk    rt          d          |                    |                    |           | z  ||          dz  S t          j        	                    | |||          S )Nlinalg)r   r   r   r   zonly the Euclidean norm (`ord=2`) is currently supported in `xp_vector_norm` for backends not implementing the `linalg` extension.)r   r   r   )r   r   r   )
r   r'   hasattrr   vector_normr<   sumconjr>   norm)rh   r   r   r   rP   s        rN   r2   r2     s    
  "z			rB H2x   	M9((c(RRRaxx !   66"''!**q.th6GGLL y~~aSth~GGGrU   c               T    |t          |           n|}|                    | d          S )N))r   reshaperj   s     rN   r/   r/     s.      "z			rB::arU   c                     |t          |           n|}t          t          | j                            }||         ||         c||<   ||<   |                    | |          } | S N)r   rY   rangerJ   permute_dims)aaxis1axis2rP   axess        rN   xp_swapaxesr     sa    !z			rBafD#E{DKDKe
4  AHrU   )force_floatingc                    fd|D             }d |D             }| r|                     d           t                    r!j        dk     rd |D             } j        | S 	  j        | S # t          $ r | s g }|D ]i}t          j        |          r                    |          n|}t          |d|          }	                    |d          r|                     |           j j        g |t                    R  cY S w xY w)a  
    Returns the dtype that results from applying type promotion rules
    (see Array API Standard Type Promotion Rules) to the arguments. Augments
    standard `result_type` in a few ways:

    - There is a `force_floating` argument that ensures that the result type
      is floating point, even when all args are integer.
    - When a TypeError is raised (e.g. due to an unsupported promotion)
      and `force_floating=True`, we define a custom rule: use the result type
      of the default float and any other floats passed. See
      https://github.com/scipy/scipy/pull/22695/files#r1997905891
      for rationale.
    - This function accepts array-like iterables, which are immediately converted
      to the namespace's arrays before result type calculation. Consequently, the
      result dtype may be different when an argument is `1.` vs `[1.]`.

    Typically, this function will be called shortly after `array_namespace`
    on a subset of the arguments passed to `array_namespace`.
    c                 `    g | ]*}t          j        |          rt          |d           n|+S T)r\   rP   r>   iterabler   .0argrP   s     rN   
<listcomp>z"xp_result_type.<locals>.<listcomp>  L        24S1A1AJXc"----s   rU   c                     g | ]}||S r   r   r   r   s     rN   r   z"xp_result_type.<locals>.<listcomp>      <<<SCOSOOOrU   g      ?z2.0c                 J    g | ] }t          |d d          dk    r|j        n|!S )r   r      )getattrrE   r   s     rN   r   z"xp_result_type.<locals>.<listcomp>  sD     3 3 3  '.c61&=&=&B&B 3 3 3rU   rE   r   )appendr%   __version__result_typerA   r>   r   re   r   r   xp_default_dtype)r   rP   r   args_not_none
float_argsr   	arg_arrayrE   s    `      rN   r4   r4     s   (     D<<D<<<M "S!!!|| ...3 3$13 3 3r~}--Ar~}-- A A A 	
 
  	' 	'C+-;s+;+;D

3IIw44Ezz%!FGG '!!#&&&r~@z@+;B+?+?@@@@@@As   $	A. .BDD)	broadcastr   c                    fd|D             }t          ||dfd|D             }| s*t          |          dk    r|d         nt          |          S d |D             }d |D             }	 t          |          dk    rt          j        | n|d         j        }n$# t          $ r}d}t          |          |d	}~ww xY wg }	|D ]}
|
|	                    |
           |
j        |k    r$t                    rd
dini } j	        |
|fi |}
|
j
        k    r                    |
          }
|	                    |
           t          |	          dk    r|	d         nt          |	          S )a  
    Promotes elements of *args to result dtype, ignoring `None`s.
    Includes options for forcing promotion to floating point and
    broadcasting the arrays, again ignoring `None`s.
    Type promotion rules follow `xp_result_type` instead of `xp.result_type`.

    Typically, this function will be called shortly after `array_namespace`
    on a subset of the arguments passed to `array_namespace`.

    This function accepts array-like iterables, which are immediately converted
    to the namespace's arrays before result type calculation. Consequently, the
    result dtype may be different when an argument is `1.` vs `[1.]`.

    See Also
    --------
    xp_result_type
    c                 `    g | ]*}t          j        |          rt          |d           n|+S r   r   r   s     rN   r   zxp_promote.<locals>.<listcomp>;  r   rU   )r   rP   c                 >    g | ]}|t          |d          n|S )NT)rE   r\   rP   )r   )r   r   rE   rP   s     rN   r   zxp_promote.<locals>.<listcomp>@  sE        ?BoXcdr::::SV   rU   r   r   c                     g | ]}||S r   r   r   s     rN   r   zxp_promote.<locals>.<listcomp>F  r   rU   c                     h | ]	}|j         
S r   )r   r   s     rN   	<setcomp>zxp_promote.<locals>.<setcomp>I  s    111Cci111rU   z/Array shapes are incompatible for broadcasting.Nr\   T)r4   lentupler>   broadcast_shapesr   r<   r   r%   r   rE   astype)r   r   rP   r   r   shapesr   erM   outr   kwargsrE   s     `         @rN   r5   r5   )  s   $     D DBGGGE      D  8d))Q,,tAwwE$KK7<<D<<<M 21=111F)14V1A1A$f--#A&, 	 ) ) )C!!q() C  ;JJsOOO
 9(0<gt__"F!"/#u7777C 9))C''C

3XXq[[3q66eCjj0s   2.B! !
C+B==Carrc                 
   |t          |           n|}| j        }|                    ||j                  r|                    | |j                  } n1|                    |d          r|                    | |j                  } | S )Nr   )r   rE   r   float32r   	complex64
complex128)r   rP   	arr_dtypes      rN   xp_float_to_complexr  g  s    !#			B	I 
zz)RZ(( ,iiR\**	I	/	/ ,iiR]++JrU   c                 V    t          |           r|                                 S | j        S )z@Query the namespace-dependent default floating-point dtype.
    )r&   get_default_dtypefloat64rg   s    rN   r   r   u  s.     || ##%%% zrU   c                  P    | D ]"}t          |          rt          |          c S #dS )zReturn the device of an array in `args`, for the purpose of
    input-output device propagation.
    If there are multiple devices, return an arbitrary one.
    If there are no arrays, return None (this typically happens only on NumPy).
    N)r   r.   )r   r   s     rN   xp_result_devicer    sA      " " C   	"S>>!!!	"4rU   c                     d| j         v S )z=Returns True if `xp` is an MArray namespace; False otherwise.marray)r   rg   s    rN   r    r      s    r{""rU   )reprc                   t    e Zd ZU edz  ed<   edz  ed<    ej        e          Zee	         ed<   d Z
d ZdS )_XPSphinxCapabilityNr6   gpu)default_factorywarningsc                     |dS |sdS | j         r<dd                    | j                   z   }t          |          dk    s
J d            |S dS )Nzn/au   ⛔u   ⚠️ z;    zWarnings too longu   ✅)r  joinr   )selfvalueress      rN   _renderz_XPSphinxCapability._render  s_    =5 	5= 	dii666Cs88r>>>#6>>>JurU   c                 |    |                      | j                  }|                      | j                  }|dd|dS )N20z  )r  r6   r  )r  r6   r  s      rN   __str__z_XPSphinxCapability.__str__  sB    ll48$$ll48$$$$$C$$$$rU   )r   
__module____qualname__bool__annotations__dataclassesfieldrY   r  strr  r  r   rU   rN   r  r    sx         		+++DAAAHd3iAAA	 	 	% % % % %rU   r  r   c	           
         t          |          }t          dd           t          dd           t          d d          t          dd          t          dd|rg ndg          t          dd |rdgng           d}	t          |           t          |          z   D ])\  }
}|	|
         }|j        d|_        |j        d|_        *|	                                D ]@\  }
}|r%|
|dhz  vr|j        d|_        |j        d|_        ,|r|
|vr|j        d|_        A|D ]'\  }
}|	|
         }|j                            |           (|	S )	NT)r6   r  zno JIT)r6   r  r  zcomputes graph)r   array_api_strictcupytorch	jax.numpy
dask.arrayFr   )rn   r  rY   r6   r  itemsr  r   )skip_backendsxfail_backendscpu_onlynp_only
exceptionsallow_dask_computejax_jitr  reasoncapabilitiesmodule_backendwarnings                 rN   _make_sphinx_capabilitiesr5    s    ZJ %4888/DdCCC#$777$4888(Tt"2RR
4 4 4 *d+=E&''2G G G
 
L -((4+?+??    	v&;"GK;"GK'--//     	 vZ7)%;;;{&#{&# 	 &
22w{7NGK# ) )v&((((rU   c                     d|  d|d          d|d          d|d          d|d	          d
|d          d}t          j        |          S )Nz
    `aG  ` has experimental support for Python Array API Standard compatible
    backends in addition to NumPy. Please consider testing these features
    by setting an environment variable ``SCIPY_ARRAY_API=1`` and providing
    CuPy, PyTorch, JAX, or Dask arrays as array arguments. The following
    combinations of backend and device (or other capability) are supported.

    ====================  ====================  ====================
    Library               CPU                   GPU
    ====================  ====================  ====================
    NumPy                 r   z
    CuPy                  r#  z
    PyTorch               r$  z
    JAX                   r%  z
    Dask                  r&  z}
    ====================  ====================  ====================

    See :ref:`dev-arrayapi` for more information.
    )textwrapdedent)fun_namer0  notes      rN   _make_capabilities_noter;    s      (0  (/  (0  (4  (5  D& ?4   rU   )
capabilities_tabler(  r)  r*  r+  r/  r,  r  r-  r.  c        
         x      t           n  t          ||||||||	|	  	        t          di  fd}
|
S )a  Decorator for a function that states its support among various
    Array API compatible backends.

    This decorator has two effects:
    1. It allows tagging tests with ``@make_xp_test_case`` or
       ``make_xp_pytest_param`` (see below) to automatically generate
       SKIP/XFAIL markers and perform additional backend-specific
       testing, such as extra validation for Dask and JAX;
    2. It automatically adds a note to the function's docstring, containing
       a table matching what has been tested.    

    See Also
    --------
    make_xp_test_case
    make_xp_pytest_param
    array_api_extra.testing.lazy_xp_function
    N)	r(  r)  r*  r+  r/  r,  r-  r.  r  c                    | <   t          | j                  }t          |           }|d                             |           t	          |                              dd          d         }	 || _        n# t          $ r Y nw xY w| S )NNotes
r   )r;  r   r   r   r   split__doc__AttributeError)fr:  docr0  r<  sphinx_capabilitiess      rN   	decoratorz"xp_capabilities.<locals>.decorator&  s     !-1&qz3FGG!nnGD!!!#hhnnT1%%a(	AII 	 	 	 D	
 s   0A8 8
BBr   )xp_capabilities_tabledictr5  )r<  r(  r)  r*  r+  r/  r,  r  r-  r.  rG  r0  rF  s   `          @@rN   r3   r3     s    B 4F3M//1  #%-
 
 
L 4CClCC        rU   r<  c                 v  
 | t           n| } dd l}ddlm} g }|D ]}| |         

d         }
d         }
d         r0|                    |j                            d||                     
d         r0|                    |j                            d||	                     
d
         D ]4\  }}|                    |j                            ||                     5
d         D ]4\  }}|                    |j                            ||                     5
fddD             }	 ||fi |	 |S )Nr   )lazy_xp_functionr,  r/  r*  T)r*  r,  r/  r+  )r+  r,  r/  r(  )r/  r)  c                 "    i | ]}||         S r   r   )r   kr0  s     rN   
<dictcomp>z)_make_xp_pytest_marks.<locals>.<dictcomp>Q  s5     C C C ,q/ C C CrU   )r-  r.  )rH  rs   "scipy._lib.array_api_extra.testingrL  r   markskip_xp_backendsxfail_xp_backends)r<  funcsrs   rL  marksfuncr,  r/  mod_namelazy_kwargsr0  s             @rN   _make_xp_pytest_marksrY  9  s   3E3M//1 MMMCCCCCCE . .)$/!,/
h'
# 	FLL55*V 6 E E F F F	" 	ELL55F 6 D D E E E !-_ = 	P 	PHfLL55hv5NNOOOO ,-= > 	Q 	QHfLL66x6OOPPPPC C C C AC C C------LrU   c                 >    | t           n| } 	 t          |d| ifdS )Nr<  c                 2    t          j        d |           S )Nc                      ||           S r   r   )rD  gs     rN   <lambda>z5make_xp_test_case.<locals>.<lambda>.<locals>.<lambda>m  s    aadd rU   )	functoolsreduce)rV  rU  s    rN   r^  z#make_xp_test_case.<locals>.<lambda>m  s    	():):E4HH rU   )rH  rY  )r<  rT  rU  s     @rN   make_xp_test_casera  X  s@    3E3M//1 " "5P=OPPEHHHHHrU   c                Z    ddl }t          | |          } |j        | g|R || j        dS )ai  Variant of ``make_xp_test_case`` that returns a pytest.param for a function,
    with all necessary skip_xp_backends and xfail_xp_backends marks applied::
    
        @pytest.mark.parametrize(
            "func", [make_xp_pytest_param(f1), make_xp_pytest_param(f2)]
        )
        def test(func, xp):
            ...

    The above is equivalent to::

        @pytest.mark.parametrize(
            "func", [
                pytest.param(f1, marks=[
                    pytest.mark.skip_xp_backends(...),
                    pytest.mark.xfail_xp_backends(...), ...]),
                pytest.param(f2, marks=[
                    pytest.mark.skip_xp_backends(...),
                    pytest.mark.xfail_xp_backends(...), ...]),
        )
        def test(func, xp):
            ...

    Parameters
    ----------
    func : Callable
        Function to be tested. It must be decorated with ``@xp_capabilities``.
    *args : Any, optional
        Extra pytest parameters for the use case, e.g.::

        @pytest.mark.parametrize("func,verb", [
            make_xp_pytest_param(f1, "hello"),
            make_xp_pytest_param(f2, "world")])
        def test(func, verb, xp):
            # iterates on (func=f1, verb="hello")
            # and (func=f2, verb="world")

    See Also
    --------
    xp_capabilities
    make_xp_test_case
    array_api_extra.testing.lazy_xp_function
    r   NrJ  )rU  id)rs   rY  r   r   )rV  r<  r   rs   rU  s        rN   make_xp_pytest_paramrd  p  sG    X MMM!$;MNNNE6<CtCC5T]CCCCrU   r   )r   )r   )	r   r   FFr   FTr   N)crB  rt   r  r_  osr7  collections.abcr   r   r   r   contextvarsr   typesr   typingr	   r
   r   r   r>   numpy.typingnpt
scipy._libr   scipy._lib.array_api_compatr   r   r   r0   rX   r   r.   r   r%   r   r#   r   r&   r   r$   r   r   r   r!   scipy._lib._sparser   scipy._lib._docscraper   __all__environr   r'   r   r  r  r(   rW   r7   r8   rO   rT   r   r   r-   rl   r   r   r   r   r+   r*   r,   r   r   r1   r"   r)   intr   floatr2   r/   r   r4   r5   r  r   r  r    	dataclassr  r5  r;  r3   rY  ra  rd  rH  r   rU   rN   <module>ru     s                 				  9 9 9 9 9 9 9 9 9 9 % % % % % % " " " " " "       * * * * * * * * * *           ' ' ' ' ' '                          ( ' ' ' ' ' - - - - - -	 	 	 !jnn->FFt F F Fz~~ne44 '   y   s},	9 , , ,5hy1 5huo 5 5 5 5p J 4    $U $z $ $ $ $R 48 	, !%", , ,,, )*T1, Tk	, , , , 
, , , ,^ 26 ) ) )u )Z$. )% ) ) ) )8 .8Z-F-F Jz* F F F(: (),<"= ( ( ( ( 3 3 3 3 #'Dd% % % % %P( ( ($ 9=$ $tRDK K K K K, .24 $$4B B B B B@ 8<#dBQUJ J J J J.* * * ** * * *FC FC F F F F3% 3Z 3D 3 3 3 3J :+<    0 48$)&'+/	H H He HuSz)D0H!H eH "D(	H 5:	H H H H4 6:        d!2  e            */ /A /A /A /A /Ad !&e ;1 ;1 ;1 ;1 ;1| U 
T(9 U        # # #
 E"""% % % % % % % #"%0 &(.0&*0 0 0 0f! ! !8  RE$2 dA A A A AH 6:     > 26 I I I I I0 :> /D /D /D /D /Df    rU   