
    Џkh"                        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jd                  jg                  dd      Z4e5e6z  e7d<   ejd                  jg                  dd      Z8e4e8dZ9eZ:ee7d<   e:ejv                  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)       ZBdYd*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ZHdZd6ZId[d7ZJd8ede5fd9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  d?e6d@eNePz  dedz  de:fdAZQdd#d$e:dedz  de:fdBZRdYdCZSddDdEZTdddFdGZUdYdHe:dedz  de:fdIZVdJ ZWdK ZXdL ZY ej                  dM       G dN dO             Z[	 	 	 	 	 d\dQZ\dR Z]ddPdPddddPdPdd+dS
dTZ^ddUdVZ_ddUdWZ`ddUdXZai Zby)]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              #     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        rc|j                  }t        j                  |t        j                        s3t        j                  |t        j                        st        d|d      t        |      r| 	 t        j                  |      }|j                  }t        j                  |t        j                        s5t        j                  |t        j                        sd|d}t        |      |j                   s|  y# t        $ r t        d      w xY ww)	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        Q/var/www/teggl/fontify/venv/lib/python3.12/site-packages/scipy/_lib/_array_api.py_compliance_scipyrO   D   s      *= E?)C S/!eRUU../VWWeRYY'NOOeRZZ"**45KKEMM%3r}}UBHH7U"9% CS !T U U E"K7e, KKEMM%3r}}UBHH7UGy QG H   (( zzU*8  7 !6 7 77s%   DG F(-A1G  G (F==G rK   xpc                 ^    |j                  |j                  |             sd}t        |      y)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o &    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      s?    4 +,'/0J //<<rU   )rP   check_finitesubokrE   order)KACFcopyr[   r\   c                   |t        |       }t        |      rR|du rt        j                  | |||      } nI|rt        j                  | ||      } n.t        j
                  | ||      } n	 |j                  | ||      } |rt        | |       | S # t        $ r1 t        |j                  d            }|j                  | ||      } Y Iw xY w)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.
    T)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#|4<HHU%uEJEMM%uEBEJJuE?E	FJJuEJ=E
 eR L  	F(A7J&&uE&EE	Fs   ,B 7C
	C
rP   xc                8    |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.
    T)rb   rP   )r   r   rh   rP   s     rN   r-   r-      s"    , 
zQADR((rU   _default_xp_default_xp_ctxvar)NNNc              #      K   t         j                  |       }	 d t         j                  |       y# t         j                  |       w xY w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3 AA

Ac                 r    ddl }d}t        |       rt        j                         S |j	                  ||      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     s6     OQ%%''<<E<22rU   Tcheck_namespacecheck_dtypecheck_shapecheck_0dc                @   d}|	 t         j                         }|rt	        | ||       t        |      rg|redt        |        dt        |       }|j                  |       r|j                  |      s)|j                  |       s|j                  |      rJ |       |j                  |       } |j                  |      }|r<d| j                   d|j                   }| j                  |j                  k(  sJ |       |rgt        |      r | j                          |j                          d| j                   d|j                   }| j                  |j                  k(  sJ |       |j                  || j                        }| ||fS # t        $ r t        |      }Y w xY w)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	*#'')B "67B7 |7<.T']O=V$W)=F+BKK4H	QLP	Q J ZZFjj!G/~[X||w}},2d2,2;&&('')/~[X||w}},2d2,oogv||4G7B;  	* )B	*s   F FFc                     d}t        |      }d|j                   d|j                   }||k(  sJ |       t        |       }d|j                   d|j                   }||k(  sJ |       y )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& '8&@&@%A B##%;;-	1D
 "(D("&v.'001 2}&D r!'4'!rU    )rz   r{   r|   r}   err_msgrP   c          	      4   d}t        | ||||||      \  } }}t        |      r|j                  j                  | ||      S t	        |      r+|dk(  rd n|}|j                  j                  | |dddd|      S t        j                  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{zz,,VWg,NN	" "R-$Wzz&&vwQQRV38g ' G 	G ::(('(JJrU   )r   r   rz   r{   r|   r}   r   rP   c          	         d}
t        | ||	||||      \  } }}	|	j                  | j                  d      }|.|r,|	j                  | j                        j                  dz  dz  }n|d}t        |	      r |	j                  j                  | ||||      S t        |	      r+|dk(  rd n|}|	j                  j                  | |||dd	|
      S t        j                  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  s    ''[(FGR zz&,,(MNH| xx%))3.2	r{zz))&'/3W * F 	F	"!R-$Wzz&&vwT155g ' W 	W ::%%fgD+/ & B BrU   )rz   r{   r|   r}   r   verboserP   c          	         d}	t        | ||||||      \  } }}t        |      r|j                  j                  | |||      S t	        |      rR| j
                  j                  dk7  r| j                         } |j
                  j                  dk7  r|j                         }t        j                  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{zz++FG4;W , N 	N	"==&ZZ\F>>%'kkmG::''07 ( J JrU   c                 B    ddd| z  z  }}t        | |g|||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     H     CgX&$D67 * * $4UPU*$(* *rU   c                 B    ddd| z  z  }}t        | |g|||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    y DEErU   c                 :    |j                  | j                  d      S )Nr   )r   rE   rj   s     rN   r"   r"     s    ::agg122rU   c                     t        |       rddl}|j                  S t        |       rddl}|j                  S t        |       r| S y)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)     s;     r{{{bzyy|	rU      )axiskeepdimsordrP   r   r   r   c               :   |t        |       n|}t        rdt        |d      r|j                  j	                  | |||      S |dk7  rt        d      |j                  |j                  |       | z  ||      dz  S t        j                  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2x 99((c(RRax !  66"''!*q.th6GLL yy~~aSth~GGrU   c               D    |t        |       n|}|j                  | d      S )N))r   reshaperj   s     rN   r/   r/     s%      "z	rB::arU   c                     |t        |       n|}t        t        | j                              }||   ||   c||<   ||<   |j	                  | |      } | S N)r   rY   rangerJ   permute_dims)aaxis1axis2rP   axess        rN   xp_swapaxesr     sU    !z	rBaffD#E{DKDKe
4 AHrU   )force_floatingc                    |D cg c]'  }t        j                  |      rt        |d|      n|) }}|D cg c]  }||	 }}| r|j                  d       t	        |      rI|j
                  dk  r:|D cg c]   }t        |dd      dk(  r|j                  n|" }} |j                  | S 	  |j                  | S c c}w c c}w c c}w # t        $ r | s g }|D ][  }t        j                  |      r|j                  |      n|}t        |d|      }|j                  |d	      sK|j                  |       ]  |j                  g |t        |       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`.
    Tr\   rP   g      ?z2.0r   r      rE   r   )r>   iterabler   appendr%   __version__getattrrE   result_typerA   r   re   r   xp_default_dtype)r   rP   r   argargs_not_none
float_args	arg_arrayrE   s           rN   r4   r4     sv   *  24S1AXc"-sJ D $(<SCOS<M<S!|. %23  '.c61&=&BK 3 3r~~}--Ar~~}--<3  A
 
  	'C+-;;s+;

3IIw4Ezz%!FG!!#&		'
 r~~@z@+;B+?@@As.   ,B<CC6%C-C AE&0EE)	broadcastr   c           	      \   |D cg c]'  }t        j                  |      rt        |d|      n|) }}t        |||d}|D cg c]  }|t        ||d|      n| }}| st	        |      dk(  r|d   S t        |      S |D cg c]  }||	 }}|D ch c]  }|j                   }}	 t	        |      dk7  rt        j                  | n|d   j                  }g }|D ]|  }||j                  |       |j                  |k7  r%t        |      rd	dini } |j                  ||fi |}|j                  |k7  r|j                  ||      }|j                  |       ~ t	        |      dk(  r|d   S t        |      S c c}w c c}w c c}w c c}w # t        $ r}	d}
t        |
      |	d}	~	ww xY w)
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
    Tr   )r   rP   N)rE   r\   rP   r   r   z/Array shapes are incompatible for broadcasting.r\   )r>   r   r   r4   lentupler   broadcast_shapesr<   r   r%   r   rE   astype)r   r   rP   r   r   rE   r   shapesr   erM   outkwargss                rN   r5   r5   )  s   &  24S1AXc"-sJ D  DBGE  ?BoXcdr:SVV D  d)Q,tAw7E$K7$(<SCOS<M< $11Ccii1F1)14V1A$$f-#A&,, 	 C ;JJsO
 99(0gt_"F!"//#u77C 99))C'C

3!$ Xq[3q60eCj0S
 = 2  )C!q()s5   ,E;F FFF
+/F 	F+F&&F+arrc                    |t        |       n|}| j                  }|j                  ||j                        r|j	                  | |j
                        } | S |j                  |d      r|j	                  | |j                        } | S )Nr   )r   rE   r   float32r   	complex64
complex128)r   rP   	arr_dtypes      rN   xp_float_to_complexr   g  ss    !#	B		I 
zz)RZZ(iiR\\* J 
I	/iiR]]+JrU   c                 P    t        |       r| j                         S | j                  S )z@Query the namespace-dependent default floating-point dtype.
    )r&   get_default_dtypefloat64rg   s    rN   r   r   u  s&     |##%% zzrU   c                  B    | D ]  }t        |      st        |      c S  y)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     s,      " C S>!	"
 rU   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                   p    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y)_XPSphinxCapabilityNr6   gpu)default_factorywarningsc                     |y|sy| j                   r5ddj                  | j                         z   }t        |      dk  sJ d       |S y)Nzn/au   ⛔u   ⚠️ z;    zWarnings too longu   ✅)r   joinr   )selfvalueress      rN   _renderz_XPSphinxCapability._render  sL    ===dii66Cs8r>6#66>JrU   c                     | j                  | j                        }| j                  | j                        }|dd|dS )N20z  )r  r6   r   )r  r6   r   s      rN   __str__z_XPSphinxCapability.__str__  s;    ll488$ll488$bC8$$rU   )r   
__module____qualname__bool__annotations__dataclassesfieldrY   r   strr  r  r   rU   rN   r   r     s;    		++++DAHd3i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 ]1  \  }
}|	|
   }|j                  d|_        |j                  +d|_        3 |	j                         D ]S  \  }
}|r0|
|dhz  vr(|j                  d|_        |j                  0d|_        8|s;|
|vs@|j                  Md|_        U |D ]%  \  }
}|	|
   }|j                  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_capabilitiesr$    sc    ZJ %48/DdC#$7$48(Tt"R
4 *d+=&'2G
L -(4+??  	v&;;"GK;;"GK  (--/  vZ7)%;;{{&#{{&#&
2w{{7NGK  $ )v&() rU   c                 t    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_namer  notes      rN   _make_capabilities_noter*    s    Z 	 (0D E'/D E'0D E'4D E'5D ED& ??4  rU   )
capabilities_tabler  r  r  r  r  r  r   r  r  c        
         l      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
    )	r  r  r  r  r  r  r  r  r   c                     | <   t        | j                        }t        |       }|d   j                  |       t	        |      j                  dd      d   }	 || _        | S # t        $ r Y | S w xY w)NNotes
r   )r*  r   r   r   r  split__doc__AttributeError)fr)  docr  r+  sphinx_capabilitiess      rN   	decoratorz"xp_capabilities.<locals>.decorator&  s     !-1&qzz3FG!nGD!#hnnT1%a(	AI   	 	s   A$ $	A10A1r   )xp_capabilities_tabledictr$  )r+  r  r  r  r  r  r  r   r  r  r6  r  r5  s   `          @@rN   r3   r3     s\    B 4F3M/1  #%-
L 4ClC  rU   r+  c                 P   | t         n| } dd l}ddlm} g }|D ]  }| |   }|d   }|d   }|d   r-|j	                  |j
                  j                  d||             |d   r-|j	                  |j
                  j                  d||	             |d
   D ]1  \  }	}|j	                  |j
                  j                  |	|             3 |d   D ]1  \  }	}|j	                  |j
                  j                  |	|             3 dD 
ci c]  }
|
||
   
 }}
 ||fi |  |S c c}
w )Nr   )lazy_xp_functionr  r  r  T)r  r  r  r  )r  r  r  r  )r  r  )r  r  )r7  rs   "scipy._lib.array_api_extra.testingr;  r   markskip_xp_backendsxfail_xp_backends)r+  funcsrs   r;  marksfuncr  r  r  mod_nameklazy_kwargss               rN   _make_xp_pytest_marksrF  9  sp   3E3M/1 CE .)$/!,/
h'
#LL55*V 6 E F	"LL55F 6 D E !-_ = 	PHfLL55hv5NO	P ,-= > 	QHfLL66x6OP	Q !BC ,q/) C C--'.* L	Cs   D#c                 :    | t         n| } 	 t        |d| ifdS )Nr+  c                 4    t        j                  d |       S )Nc                      ||       S r   r   )r3  gs     rN   <lambda>z5make_xp_test_case.<locals>.<lambda>.<locals>.<lambda>m  s
    ad rU   )	functoolsreduce)rB  rA  s    rN   rK  z#make_xp_test_case.<locals>.<lambda>m  s    	(():E4H rU   )r7  rF  )r+  r@  rA  s     @rN   make_xp_test_caserN  X  s1    3E3M/1 " "5P=OPEHHrU   c                f    ddl }t        | |      } |j                  | g||| 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   Nr9  )rA  id)rs   rF  r   r   )rB  r+  r   rs   rA  s        rN   make_xp_pytest_paramrQ  p  s6    X !$;MNE6<<CtC5T]]CCrU   r   )   )   )	r   r   FFr   FTr   N)cr1  rt   r  rL  osr&  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   r$  r*  r3   rF  rN  rQ  r7  r   rU   rN   <module>rd     s      	  9 9 % "  * *   '    ( -	 !jjnn->Ft Fzz~~ne4 '  y s}},	9 ,5hy1 5huo 5p J 4 $U $z $R 48 	, !%",,, )*T1, Tk	, , , , 
,^ 26 )u )Z$. )% )8 .8-F Jz* F(: (),<"= ( ( 3 #'Dd%P($ 9=$ $tRDK, .24 $$4B@ 8<#dBQUJ.**FC FC F3% 3Z 3D 3J :+< 0 48$)&'+/	He HuSz)D0H!H eH "D(	H 5:	H4 6:    d!2  e   */ /Ad !&e ;1|U 
T(9 U #
 E"% % #%0 &(.0&*0f!8  RE$2 dAH 6: > 26 I0 :> /Df  rU   