o
    Y۷i1                     @   s   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
 d dlmZ d dlmZmZ d dlmZ d d	lmZmZ d d
lZdd ZG dd de
ZG dd deje	Zdd Zd
S )    )typeof)types)GUFuncBuilder)parse_signature)	UfuncBaseUfuncLowererBase)ufunc_find_matching_loop)	serializeerrors)npydecl)	signatureAbstractTemplateNc                    s6   ddl m} G  fddd|j}| j j7  _|S )Nr   npyimplc                       s<   e Zd ZdZZ fddZ fddZ fddZ  ZS )z(make_gufunc_kernel.<locals>.GUFuncKernelz
        npyimpl._Kernel subclass responsible for lowering a gufunc kernel
        (element-wise function) inside a broadcast loop (which is
        generated by npyimpl.numpy_gufunc_kernel()).
        c                    s6   t  ||| | j|j}| j|\| _| _d S N)super__init__dufunc_get_ewise_dtypesargsfind_ewise_function	inner_sigcres)selfcontextbuilder	outer_sigewise_types	__class__ K/home/ubuntu/vllm_env/lib/python3.10/site-packages/numba/np/ufunc/gufunc.pyr      s
   z1make_gufunc_kernel.<locals>.GUFuncKernel.__init__c                    s:   t |tjrt |tjst ||j|S t |||S r   )
isinstancer   Arrayr   castdtype)r   valfromtytotyr   r    r!   r$      s
   
z-make_gufunc_kernel.<locals>.GUFuncKernel.castc                    s4   | j jrd}t|| j| j jf t j| S )NzCCalling a guvectorize function in object mode is not supported yet.)	r   
objectmoder
   NumbaRuntimeErrorr   add_linking_libslibraryr   generate)r   r   msgr   r    r!   r-   %   s
   
z1make_gufunc_kernel.<locals>.GUFuncKernel.generate)	__name__
__module____qualname____doc__r   r   r$   r-   __classcell__r    _dufuncr   r!   GUFuncKernel   s    r6   )numba.npr   _Kernelr/   )r5   r   r6   r    r4   r!   make_gufunc_kernel   s   r9   c                       s    e Zd ZdZ fddZ  ZS )GUFuncLowererzHCallable class responsible for lowering calls to a specific gufunc.
    c                    s"   ddl m} t |t|j d S )Nr   r   )r7   r   r   r   r9   numpy_gufunc_kernel)r   gufuncr   r   r    r!   r   4   s
   zGUFuncLowerer.__init__)r/   r0   r1   r2   r   r3   r    r    r   r!   r:   1   s    r:   c                   @   s   e Zd ZdZdddi dfddZdd Zd	d
 Zedd Zdd Z	d'ddZ
dd Zdd Zdd Zdd Zd'ddZdd Zedd Zdd  Zd!d" Zd#d$ Zd%d& ZdS )(GUFuncz
    Dynamic generalized universal function (GUFunc)
    intended to act like a normal Numpy gufunc, but capable
    of call-time (just-in-time) compilation of fast loops
    specialized to inputs.
    NFr    c                 C   sj   d | _ d| _|| _|| _t||||||| _| jjj| _| jjj| _| jj	| _
| | j
 t| | d S )NF)ufunc_frozen_is_dynamic	_identityr   gufunc_builderpy_funcr/   r2   nb_func_dispatcher_initialize	functoolsupdate_wrapper)r   rC   r   identitycache
is_dynamictargetoptionswritable_argsr    r    r!   r   C   s   
zGUFunc.__init__c                 C   s&   |    |   t| | _|   d S r   )build_ufunc_install_typer:   	_lower_me_install_cg)r   
dispatcherr    r    r!   rF   V   s   
zGUFunc._initializec                 C   s6   | j }t|j|j| j|j| j|j|j|j	| j
d	}|S )N)	rC   r   rI   rJ   rK   rL   rM   typesigsfrozen)rB   dictrC   r   rA   rJ   r@   rL   rM   _sigsr?   )r   gbdctr    r    r!   _reduce_states\   s   zGUFunc._reduce_statesc
              	   C   s<   | |||||||d}
|D ]}|
 | q|
  |	|
_|
S )N)rC   r   rI   rJ   rK   rL   rM   )addrN   r?   )clsrC   r   rI   rJ   rK   rL   rM   rS   rT   r   sigr    r    r!   _rebuildk   s   zGUFunc._rebuildc                 C   s   d| j  dS )Nz<numba._GUFunc 'z'>)r/   r   r    r    r!   __repr__w   s   zGUFunc.__repr__c                 C   s@   |du r	| j jj}td| j tft| | jd}|| | dS )a*  Constructs and installs a typing class for a gufunc object in the
        input typing context.  If no typing context is given, then
        _install_type() installs into the typing context of the
        dispatcher object (should be same default context used by
        jit() and njit()).
        NGUFuncTyping_)keygeneric)	rE   targetdescrtyping_contexttyper/   r   rU   _type_meinsert_user_function)r   	typingctx_ty_clsr    r    r!   rO   z   s   

zGUFunc._install_typec                 C   s   | j | d S r   )rB   rZ   )r   ftyr    r    r!   rZ      s   z
GUFunc.addc                 C   s   | j  | _| S r   )rB   rN   r>   r^   r    r    r!   rN      s   zGUFunc.build_ufuncc                 C   s0   t | jj}ttt|d ttt|d fS Nr      )r   rB   r   tuplemaplen)r   
parsed_sigr    r    r!   expected_ndims   s   $zGUFunc.expected_ndimsc                 C   s  |rJ | j }| jj}|  \}}|| }t|sJ t|t|D ]F\}}	t|	tjri|	j	|| k ri|t|k r<dnd}
|t|k rF|n|t| }| j
 d|
 d| d|	j	 d| d||  d}t|q#tj|||}|\}}}}| |\}}|d	u r| jrd
|  d| }t|| | | |\}}|dkrd| j
 d| }t||d	usJ ttjg|R  S )z
        Implement AbstractTemplate.generic() for the typing class
        built by gufunc._install_type().

        Return the call-site signature after either validating the
        element-wise signature or compiling for it.
        InputOutputz: z	 operand z& does not have enough dimensions (has z, gufunc core with signature z
 requires )Nzcannot call z with types NNzFail to compile )r>   rB   r   rq   ro   	enumerater"   r   r#   ndimr/   r
   TypingErrorr   Numpy_rules_ufunc_handle_inputsr   r?   _compile_for_argtysnone)r   argtyskwsr>   r\   	inp_ndims	out_ndimsndimsidxargkindir.   _handle_inputs_resultr   _r    r    r!   rf      sH   



zGUFunc._type_mec                 C   s   | j | }| j| d S r   )_get_function_typerB   rZ   )r   r}   return_typefntyr    r    r!   r{      s   
zGUFunc._compile_for_argtysc                 C   s   |  |j}t|t|kS r   )r   r   rm   )r   r   r\   dtypesr    r    r!   match_signature   s   zGUFunc.match_signaturec                 C   s   | j S r   )r@   r^   r    r    r!   rK      s   zGUFunc.is_dynamicc                 C   sD   t dd |}g }|D ]}t|tjr||j q|| q|S )Nc                 S   s   t | tjr| S t| S r   )r"   r   Typer   )r   r    r    r!   <lambda>   s    z*GUFunc._get_ewise_dtypes.<locals>.<lambda>)rn   r"   r   r#   appendr%   )r   r   r}   tysargtyr    r    r!   r      s   zGUFunc._get_ewise_dtypesc                 G   s,   t | jj}t|t|d t|d  kS rk   )r   rB   r   ro   )r   r   rp   r    r    r!   _num_args_match   s    zGUFunc._num_args_matchc                 G   s   t | jj}| |}g }t|d D ] \}}t|}|dkr'|||  q|t|| |d qt|d }t|d D ]\}}|||  }	t|pOd}
|t|	|
d q@tj	| S )Nr   Arl   )
r   rB   r   r   rv   ro   r   r   r#   r|   )r   r   rp   r   lr   sig_dimrw   offsetrettyret_ndimr    r    r!   r      s   

zGUFunc._get_function_typec                 O   s   | j s| js%|rt|d r|d j| dg|R i |S | j|i |S d|v r1||df7 }| j| du rCd| j d}t|| 	|}| jrQt
| j|sf| |dksb| j| }| | |   | j|i |S )Nr   __call__outFz Too few arguments for function 'z'. Note that the pattern `out = gufunc(Arg1, Arg2, ..., ArgN)` is not allowed. Use `gufunc(Arg1, Arg2, ..., ArgN, out) instead.ru   )r?   rK   _is_array_wrapper__array_ufunc__r>   popr   r/   	TypeErrorr   r   r   r   rZ   rN   )r   r   kwargsr.   ewiser\   r    r    r!   r      s.   


zGUFunc.__call__r   )r/   r0   r1   r2   r   rF   rY   classmethodr]   r_   rO   rZ   rN   rq   rf   r{   r   propertyrK   r   r   r   r   r    r    r    r!   r=   ;   s.    



/
r=   c                 C   s    t | t ot| dot| dS )ad  Return True if obj wraps around numpy or another numpy-like library
    and is likely going to apply the ufunc to the wrapped array; False
    otherwise.

    At the moment, this returns True for

    - dask.array.Array
    - dask.dataframe.DataFrame
    - dask.dataframe.Series
    - xarray.DataArray
    - xarray.Dataset
    - xarray.Variable
    - pint.Quantity
    - other potential wrappers around dask array or dask dataframe

    We may need to add other libraries that pickle ufuncs from their
    __array_ufunc__ method in the future.

    Note that the below test is a lot more naive than
    `dask.base.is_dask_collection`
    (https://github.com/dask/dask/blob/5949e54bc04158d215814586a44d51e0eb4a964d/dask/base.py#L209-L249),  # noqa: E501
    because it doesn't need to find out if we're actually dealing with
    a dask collection, only that we're dealing with a wrapper.
    Namely, it will return True for a pint.Quantity wrapping around a plain float, a
    numpy.ndarray, or a dask.array.Array, and it's OK because in all cases
    Quantity.__array_ufunc__ is going to forward the ufunc call inwards.
    __dask_graph__r   )r"   re   hasattr)objr    r    r!   r   #  s
   r   )numbar   
numba.corer   numba.np.ufunc.ufuncbuilderr   numba.np.ufunc.sigparser   numba.np.ufunc.ufunc_baser   r   numba.np.numpy_supportr   r	   r
   numba.core.typingr   numba.core.typing.templatesr   r   rG   r9   r:   ReduceMixinr=   r   r    r    r    r!   <module>   s    $
 i