
    \ci                        U d Z ddlZddlZddlZddlZddl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mZ ddl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$m%Z&m'Z(m)Z*m+Z,m-Z. dd
l/m0Z0 ddl1m2Z2 ddl3m4Z4m5Z5m6Z6 ddl7m8Z8 ddl9m:Z; g dZ<eZ=ee>d<   e=ej?        z  Z?ee>d<   de=deddfdZ@	 	 	 d%ddddde?deded         dz  deAdz  dedz  deAdeAde=fdZBddd e=dedz  de=fd!ZCd e=dejD        fd"ZE e
d#          ZFe
e         e>d$<   ededed%         fd&            ZGdd'd(ZHd)d)d)d)d*d+ZId, ZJd)d)d)d)d-dd.d/ZKddd)d)d)d)d-dd0d1ZLd2d)d)d)d)d-dd3d4ZMd)d)d)d)d-d)dd5d6ZNddd8ZOded:ZPd;edeQfd<ZRd e=dedeAfd=ZSdedeQfd>ZTdededz  fd?ZUddd@ddAd e=dBeVeWeV         z  dz  dCeAdDeVeXz  dedz  de=fdEZYddd e=dedz  de=fdFZZdfdGZ[ddHdIZ\dddJdKZ]dfdLe=dedz  de=fdMZ^dN Z_dO Z`dedz  dPee?         de=fdQZadR ZbdgdSZcdT Zd eje        dU           G dV dW                      Zf	 	 	 	 	 dhdYZgdfdZZhddXdXdddddXdXdd)dd[d\Zidd]d^Zjdd]d_Zkdd]d`Zli Zmdae=dedb         fdcZndS )ia6  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)contextmanager)
ContextVar)
ModuleType)AnyLiteral	TypeAlias)Iterable)is_array_api_objis_lazy_arrayis_numpy_arrayis_cupy_arrayis_torch_arrayis_jax_arrayis_dask_arraysizenumpydeviceis_numpy_namespaceis_cupy_namespaceis_torch_namespaceis_jax_namespaceis_dask_namespaceis_array_api_strict_namespace)_compat_module_name)lazy_xp_function)array_namespaceSCIPY_ARRAY_APISCIPY_DEVICE)FunctionDoc)array_api_extra)"_asarrayr   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	np_compatget_native_namespace_namer   r   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_promotemake_xp_test_casemake_xp_pytest_marksmake_xp_pytest_paramArray	ArrayLikearrayxpreturnc                 x    |                     |                    |                     sd}t          |          dS )zCheck for NaNs or Infs.z#array must not contain infs or NaNsN)allisfinite
ValueError)rB   rC   msgs      e/var/www/html/mdtn/previsions/meteo_cartes/venv/lib/python3.11/site-packages/scipy/_lib/_array_api.py_check_finiterK   E   s=    66"++e$$%% 3oo     F)rC   check_finitesubokdtypeorder)KACFcopyrM   rN   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)rP   rO   rN   )rP   rO   )rO   rU      )r   r,   nprB   
asanyarrayasarray	TypeErrorrK   )rB   rO   rP   rU   rC   rM   rN   
coerced_xps           rJ   r"   r"   K   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rC   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)rU   rC   )r   r"   r^   rC   s     rJ   r4   r4   z   s+    , 
zQADR((((rL   c                    t          |           }t          |          r|                                 S t          |          r|                                 S t          |          r&|                                                                 S t          |          r>t          j
        |
                    | |                    d                    d          S t          j
        | d          S )a  Copies a possibly on device array to a NumPy array.

    This function is intended only for converting alternative backend
    arrays to numpy arrays within test code, to make it easier for use
    of the alternative backend to be isolated only to the function being
    tested. `_xp_copy_to_numpy` should NEVER be used except in test code
    for the specific purpose mentioned above. In production code, attempts
    to copy device arrays to NumPy arrays should fail, or else functions
    may appear to be working on the GPU when they actually aren't.

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

    Returns
    -------
    ndarray
    
CPU_DEVICE)r   T)rU   )r   r,   rU   r*   getr-   cpur   r(   rX   rZ   Devicer`   s     rJ   _xp_copy_to_numpyrf      s    & 
		B|| vvxxr{{ uuww|| uuww}}2 
 zJJq<!8!8J99
 
 
 	
 :ad####rL   _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)rh   setreset)rC   tokens     rJ   r%   r%      s^       ""2&&E(  '''''  ''''s	   > Amatchc                    ddl }ddlm} t          |          st	          |          st          |          r|                    | |          S  || |dn|          S )zpytest.warns context manager if arrays of specified namespace are always eager.

    Otherwise, context manager that *ignores* specified warning.
    r   N)ignore_warnsrm    )pytestscipy._lib._utilrp   r,   r(   r*   warns)warning_typern   rC   rr   rp   s        rJ   r&   r&      s}    
 MMM------|| 7*2.. 7'"++ 7||L|666<%-BBUKKKKrL   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: )rh   rc   LookupErrorr   _assert_matching_namespacer,   typeisscalarrZ   rO   is_daskcompute_chunk_sizesshapebroadcast_to)	actualdesiredrC   rw   rx   ry   rz   __tracebackhide___msgs	            rJ   _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   rC   r   desired_arr_spacer   actual_arr_spaces          rJ   r~   r~     s    '001 '8&@1 1 $&;	1 1D
 """D"""&v..&'0& && &D r!!!4!!!!!rL   rq   )rw   rx   ry   rz   err_msgrC   c          	      J   d}t          | ||||||          \  } }}t          |          r|j                            | ||          S t	          |          r+|dk    rd n|}|j                            | |dddd|          S t          j                            | ||          S )NTrv   )r   rq   r   Frtolatol	equal_nanrx   rI   )r   r*   testingassert_array_equalr-   assert_closerX   )	r   r   rw   rx   ry   rz   r   rC   r   s	            rJ   r2   r2     s    '_[  FGR r{{ Gz,,VWg,NNN	" G "R--$$Wz&&vwQQRV38g ' G G 	G :(('(JJJrL   )r   r   rw   rx   ry   rz   r   rC   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 )NTrv   real floatingcomplex floating      ?   gHz>)r   r   r   rq   Fr   )r   isdtyperO   finfoepsr*   r   assert_allcloser-   r   rX   )r   r   r   r   rw   rx   ry   rz   r   rC   r   floatings               rJ   r1   r1   .  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rL      )nulprw   rx   ry   rz   r   rC   c          	          d}	t          | ||||||          \  } }}t          t          | |f          \  } }t          j                            | ||          S )NTrv   )r   )r   maprf   rX   r   assert_array_almost_equal_nulp)
r   r   r   rw   rx   ry   rz   r   rC   r   s
             rJ   xp_assert_close_nulpr   N  sn     ''[(  FGR +fg->??OFG:44VW44PPPrL   )rw   rx   ry   rz   r   verboserC   c          	         d}	t          | ||||||          \  } }}t          |          r|j                            | |||          S t	          |          rH| j        j        dk    r|                                 } |j        j        dk    r|                                }t          j                            | |||          S )NTrv   )r   r   rd   )	r   r*   r   assert_array_lessr-   r   r   rd   rX   )
r   r   rw   rx   ry   rz   r   r   rC   r   s
             rJ   r3   r3   ]  s    '_[  FGR r{{ $z++FG4;W , N N 	N	" $=&&ZZ\\F>%''kkmmG:''07 ( J J JrL      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   rx   ry   r1   r   r   decimalargskwdsr   r   s          rJ   r$   r$   t  W     CgX&$D67 * * * $4UPU* *$(* * *rL      c                 D    ddd| z  z  }}t          | |g|R ||ddd|S r   r   r   s          rJ   r#   r#   }  r   rL   paramc                     d| dS )Nz
Providing z$ is only supported for numpy arrays. )r   s    rJ   r8   r8     s    EEEEErL   c                 8    |                     | j        d          S )Nr   )r   rO   r`   s     rJ   r)   r)     s    ::ag1222rL   c                 X    | j         }|                    t                       d          S )zCReturn name for native namespace (without array_api_compat prefix)..)r   removeprefixr   )rC   names     rJ   r/   r/     s-    ;D 3 5 5888999rL   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-   )rC   r   r   s      rJ   r0   r0     sZ     r{{ {bzz 


y|| 	4rL      )axiskeepdimsordrC   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_normrH   sumconjrX   norm)r^   r   r   r   rC   s        rJ   r9   r9     s    
  "z			rB H2x   	M9((c(RRRaxx !   66"''!**q.th6GGLL y~~aSth~GGGrL   c               T    |t          |           n|}|                    | d          S )N))r   reshaper`   s     rJ   r6   r6     s.      "z			rB::arL   c                     |t          |           n|}t          t          | j                            }||         ||         c||<   ||<   |                    | |          } | S N)r   listrangendimpermute_dims)aaxis1axis2rC   axess        rJ   xp_swapaxesr     sa    !z			rBafD#E{DKDKe
4  AHrL   )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 | ]9}t          |          st          j        |          rt          |d           n|:S T)rN   rC   r   rX   iterabler"   .0argrC   s     rJ   
<listcomp>z"xp_result_type.<locals>.<listcomp>  `     ' ' ' 2@1D1D TWHXHX Xc"----' ' 'rL   c                     g | ]}||S r   r   r   r   s     rJ   r   z"xp_result_type.<locals>.<listcomp>      <<<SCOSOOOrL   g      ?z2.0c                 J    g | ] }t          |d d          dk    r|j        n|!S )r   r   r   )getattrrO   r   s     rJ   r   z"xp_result_type.<locals>.<listcomp>  sD     3 3 3  '.c61&=&=&B&B 3 3 3rL   rO   r   )appendr,   __version__result_typer[   rX   r   rZ   r   r   xp_default_dtype)r   rC   r   args_not_none
float_argsr   	arg_arrayrO   s    `      rJ   r;   r;     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                    |s|S 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 | ]9}t          |          st          j        |          rt          |d           n|:S r   r   r   s     rJ   r   zxp_promote.<locals>.<listcomp>$  r   rL   )r   rC   c                 >    g | ]}|t          |d          n|S )NT)rO   rN   rC   )r"   )r   r   rO   rC   s     rJ   r   zxp_promote.<locals>.<listcomp>)  sE        ?BoXcdr::::SV   rL   r   r   c                     g | ]}||S r   r   r   s     rJ   r   zxp_promote.<locals>.<listcomp>/  r   rL   c                     h | ]	}|j         
S r   )r   r   s     rJ   	<setcomp>zxp_promote.<locals>.<setcomp>2  s    111Cci111rL   z/Array shapes are incompatible for broadcasting.NrN   T)r;   lentuplerX   broadcast_shapesr   rH   r   r,   r   rO   astype)r   r   rC   r   r   shapesr   emessageoutr   kwargsrO   s     `         @rJ   r<   r<     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   6.B% %
C/CCarrc                 
   |t          |           n|}| j        }|                    ||j                  r|                    | |j                  } n1|                    |d          r|                    | |j                  } | S )Nr   )r   rO   r   float32r   	complex64
complex128)r  rC   	arr_dtypes      rJ   xp_float_to_complexr
  P  s    !#			B	I 
zz)RZ(( ,iiR\**	I	/	/ ,iiR]++JrL   c                 V    t          |           r|                                 S | j        S )z@Query the namespace-dependent default floating-point dtype.
    )r-   get_default_dtypefloat64r]   s    rJ   r   r   ^  s.     || ##%%% zrL   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   r5   )r   r   s     rJ   xp_result_devicer  j  sA      " " C   	"S>>!!!	"4rL   arraysc                 J      fd|D             }                      |          S )zbA replacement for `np.r_` as `xp.concat` does not accept python scalars
       or 0-D arrays.
    c                 d    g | ],}t          j                            |          d           -S )r   )r   rC   )xpx
atleast_ndrZ   )r   r   rC   s     rJ   r   zconcat_1d.<locals>.<listcomp>}  s4    IIIQCN2::a==qR888IIIrL   )concat)rC   r  aryss   `  rJ   	concat_1dr  y  s/     JIII&IIID99T??rL   c                     d| j         v S )z=Returns True if `xp` is an MArray namespace; False otherwise.marray)r   r]   s    rJ   r'   r'     s    r{""rL   c                    |t          |           n|}t          |          rVt          j        |          rd}t	          |          |                    |                    | ||          | j                  S |t          |           nOt          t          j
        t          j        | j                  t          j        |                                       S )Nz8`axis` must be an integer or None for use with `MArray`.r   )r   r'   rX   r   NotImplementedErrorr   countrO   r7   intprodrZ   r   )r^   r   r   rC   r  s        rJ   _length_nonmaskedr    s    !z			rB}} M;t 	/PG%g...yy!$BBAGLLL,GAJJJ
17++BJt,<,<=>>??ArL   c                      t                     r8t          j        t          j        d |D                        fd|D             }t          |          dk    r|d         n|S )Nc              3   $   K   | ]}|j         V  d S r   maskr   s     rJ   	<genexpr>z_share_masks.<locals>.<genexpr>  s$      .H.HCsx.H.H.H.H.H.HrL   c                 H    g | ]}                     |j                   S )r"  )rZ   data)r   r   r#  rC   s     rJ   r   z _share_masks.<locals>.<listcomp>  s+    @@@C

38$
//@@@rL   r   r   )r'   	functoolsreduceoperatoror_r   )rC   r   r#  s   ` @rJ   _share_masksr+    sn    }} A.H.H4.H.H.HII@@@@@4@@@$ii1nn477$.rL   )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 )_XPSphinxCapabilityNrd   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   ✅)r1  joinr   )selfvalueress      rJ   _renderz_XPSphinxCapability._render  s_    =5 	5= 	dii666Cs88r>>>#6>>>JurL   c                 |    |                      | j                  }|                      | j                  }|dd|dS )N20z  )r8  rd   r/  )r5  rd   r/  s      rJ   __str__z_XPSphinxCapability.__str__  sB    ll48$$ll48$$$$$C$$$$rL   )r   
__module____qualname__bool__annotations__dataclassesfieldr   r1  strr8  r;  r   rL   rJ   r.  r.    sx         		+++DAAAHd3iAAA	 	 	% % % % %rL   r.  r   c
           
         |rddiS 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 )
Nout_of_scopeT)rd   r/  zno JIT)rd   r/  r1  zcomputes graph)r   array_api_strictcupytorch	jax.numpy
dask.arrayFr   )rj   r.  r   rd   r/  itemsr1  r   )skip_backendsxfail_backendscpu_onlynp_onlyrD  
exceptionsallow_dask_computejax_jitr1  reasoncapabilitiesmodule_backendwarnings                  rJ   _make_sphinx_capabilitiesrX    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&((((rL   c                     d|v rd|  d}t          j        |          S d|  d|d          d|d          d	|d
          d|d          d|d          d|pdz   dz   }t          j        |          S )NrD  z2
        **Array API Standard Support**

        `z` is not in-scope for support of Python Array API Standard compatible
        backends other than NumPy.

        See :ref:`dev-arrayapi` for more information.
        z*
    **Array API Standard Support**

    `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                  rF  z
    PyTorch               rG  z
    JAX                   rH  z
    Dask                  rI  zK
    ====================  ====================  ====================

    rq   z1    See :ref:`dev-arrayapi` for more information.)textwrapdedent)fun_namerS  
extra_notenotes       rJ   _make_capabilities_noter_    s    %%    t$$$   (0  (/  (0  (4   (5!  & '&  S'SD* ?4   rL   )capabilities_tablerK  rL  rM  rN  rR  rD  rO  r1  rP  rQ  r]  c                       t           n  |rd}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
    NT)
rK  rL  rM  rN  rD  rR  rO  rP  rQ  r1  c                 <   | <   t          | j                  }t          |           }|d                             |           t	          |                              dd          d                             d          }	 || _        n# t          $ r Y nw xY w| S )NNotes
r   z 
)	r_  r   r    r   rB  splitlstrip__doc__AttributeError)fr^  docrS  r`  r]  sphinx_capabilitiess      rJ   	decoratorz"xp_capabilities.<locals>.decoratorH  s     !-1&qz3F
SS!nnGD!!!#hhnnT1%%a(//66	AII 	 	 	 D	
 s   B 
BBr   )xp_capabilities_tabledictrX  )r`  rK  rL  rM  rN  rR  rD  rO  r1  rP  rQ  r]  rl  rS  rk  s   `          ` @@rJ   r:   r:     s    H 4F3M//1   #%!-  L 4CClCC         rL   r`  c                 >    | t           n| } 	 t          |d| ifdS )Nr`  c                 2    t          j        d |           S )Nc                      ||           S r   r   )ri  gs     rJ   <lambda>z5make_xp_test_case.<locals>.<lambda>.<locals>.<lambda>  s    aadd rL   )r'  r(  )funcmarkss    rJ   rt  z#make_xp_test_case.<locals>.<lambda>  s    	():):E4HH rL   )rm  r>   )r`  funcsrv  s     @rJ   r=   r=   [  sA    3E3M//1 *V !%O<NOOEHHHHHrL   c                Z    ddl }t          | |          } |j        | g|R || j        dS )a~  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
    make_xp_pytest_marks
    array_api_extra.testing.lazy_xp_function
    r   Nro  )rv  id)rr   r>   r   r   )ru  r`  r   rr   rv  s        rJ   r?   r?     sG    Z MMM :LMMME6<CtCC5T]CCCCrL   c                 r  	 | t           n| } ddl}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             }t          |fi | "|S )a  Variant of ``make_xp_test_case`` that returns a list of pytest marks,
    which can be used with the module-level `pytestmark = ...` variable::

        pytestmark = make_xp_pytest_marks(f1, f2)

        def test(xp):
            ...

    In this example, the whole test module is dedicated to testing `f1` or `f2`,
    and the two functions have the same capabilities, so it's unnecessary to
    cherry-pick which test tests which function.
    The above is equivalent to::

        pytestmark = [
            pytest.mark.skip_xp_backends(...),
            pytest.mark.xfail_xp_backends(...), ...]),
        ]

        def test(xp):
            ...
    
    See Also
    --------
    xp_capabilities
    make_xp_test_case
    make_xp_pytest_param
    array_api_extra.testing.lazy_xp_function
    Nr   rO  rR  rM  T)rM  rO  rR  rN  )rN  rO  rR  rK  )rR  rL  c                 "    i | ]}||         S r   r   )r   krS  s     rJ   
<dictcomp>z(make_xp_pytest_marks.<locals>.<dictcomp>  s5     C C C ,q/ C C CrL   )rP  rQ  )rm  rr   r   markskip_xp_backendsxfail_xp_backendsr   )
r`  rw  rr   rv  ru  rO  rR  mod_namelazy_kwargsrS  s
            @rJ   r>   r>     s   : 4F3M//1 MMM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------LrL   r   )rd   cudaNc                    t          |           rdS t          |           rdS t          |           r| j        j        S t          |           r| j        j        x}dk    rdn|S t          |           rt          | j	                  S d S )Nrd   r  r/  )
r   r   r   r   r   r   platformr   xp_device_type_meta)r   ps     rJ   r  r    s    a uQ va x}A B x00!U::vvAQ 'ag&&&4rL   )r   )r   r   )FN)
r   r   FFFr   FTr   N)org  r)  r@  r'  rZ  collections.abcr   
contextlibr   contextvarsr   typesr   typingr   r   r	   r
   r   rX   numpy.typingnptscipy._lib.array_api_compatr   r   r   r   r   r   r   r   r7   r.   r   r5   r   r,   r   r*   r   r-   r   r+   r   r   r   r(   +scipy._lib.array_api_compat.common._helpersr   "scipy._lib.array_api_extra.testingr   scipy._lib._array_api_overrider   r   r   scipy._lib._docscraper    
scipy._libr!   r  __all__r@   r?  rA   rK   r>  r"   r4   ndarrayrf   rh   r%   r&   r   r~   r2   r1   r   r3   r$   r#   rB  r8   r)   r/   r0   r  r   floatr9   r6   r   r;   r<   r
  r   r  r  r'   r  r+  	dataclassr.  rX  r_  r:   r=   r?   r>   rm  r  r   rL   rJ   <module>r     s               % % % % % % % % % % % % " " " " " "       * * * * * * * * * * $ $ $ $ $ $                                             $ L K K K K K ? ? ? ? ? ?          . - - - - - - - - - - -   y   s},	9 , , , J 4     48 	, !%", , ,,, )*T1, Tk	, , , , 
, , , ,^ 26 ) ) )u )Z$. )% ) ) ) )8&$ &$2: &$ &$ &$ &$R .8Z-F-F Jz* F F F(: (),<"= ( ( ( (  (, 	L 	L 	L 	L 	L #'Dd% % % % %P( ( ($ 9=$ $tRDK K K K K, .24 $$4B B B B B@ 34T%)td!#Q Q Q Q Q 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            */ 2A 2A 2A 2A 2Aj !&e A1 A1 A1 A1 A1H U 
T(9 U        *t# hy.A e    # # #
	A 	A 	A 	A/ / / E"""% % % % % % % #"%0 &(BD&*3 3 3 3l%! %! %! %!X  RE$2 d#H H H H HV 26 /I /I /I /I /Id :> 0D 0D 0D 0D 0Df 59 7 7 7 7 7v  e (; <      rL   