U
    hâËdì/  ã                   @   sÆ   d dl Z d dlmZmZ d dlmZmZmZ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 d d	lmZ d d
lmZ dd„ ZG dd„ deƒZG dd„ dejejƒZej e¡ dS )é    N)ÚjitÚtypeof)ÚcgutilsÚtypesÚ	serializeÚsigutils)Ú	is_jitted)Únpydecl)ÚAbstractTemplateÚ	signature)Ú	_internal)Úarray_analysis)Úufuncbuilder)Únumpy_supportc                    s:   ddl m} G ‡ ‡fdd„d|jƒ‰ ˆ  jˆjj7  _ˆ S )Nr   ©Únpyimplc                       s.   e Zd ZdZ”Z‡‡ fdd„Zdd„ Z‡  ZS )z(make_dufunc_kernel.<locals>.DUFuncKernelzÉ
        npyimpl._Kernel subclass responsible for lowering a DUFunc kernel
        (element-wise function) inside a broadcast loop (which is
        generated by npyimpl.numpy_ufunc_kernel()).
        c                    s.   t ˆ | ƒ |||¡ | j |j¡\| _| _d S ©N)ÚsuperÚ__init__ÚdufuncÚfind_ewise_functionÚargsÚ	inner_sigÚcres)ÚselfÚcontextÚbuilderÚ	outer_sig)ÚDUFuncKernelÚ	__class__© úN/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/numba/np/ufunc/dufunc.pyr      s    ÿz1make_dufunc_kernel.<locals>.DUFuncKernel.__init__c           
         sÆ   ˆ j }ˆ j}‡ fdd„t||j|jƒD ƒ}ˆ jjrTˆ jj t	j
t	j
gt|jƒ ¡}nˆ jj |j|j¡}ˆ jjjj}t ||ˆ jjj¡}|j d¡ ˆ jj ˆ j||j|j|¡\}}	ˆ  |	|j|j¡S )Nc                    s    g | ]\}}}ˆ   |||¡‘qS r    )Úcast)Ú.0ÚvalZintyZoutty©r   r    r!   Ú
<listcomp>!   s   ÿzEmake_dufunc_kernel.<locals>.DUFuncKernel.generate.<locals>.<listcomp>Zalwaysinline)r   r   Úzipr   r   Z
objectmoder   Z	call_convZget_function_typer   ZpyobjectÚlenÚreturn_typer   ÚblockÚfunctionÚmoduler   Zget_or_insert_functionZfndescZllvm_func_nameÚ
attributesÚaddZcall_functionr"   )
r   r   ZisigZosigZ	cast_argsZ	func_typer,   Úentry_pointÚ_Úresr    r%   r!   Úgenerate   s:    
þ ÿ ÿ þ   þz1make_dufunc_kernel.<locals>.DUFuncKernel.generate)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r2   Ú__classcell__r    ©r   Ú_dufunc©r   r!   r      s   r   )Únumba.npr   Z_Kernelr3   Úufunc)r9   r   r    r8   r!   Úmake_dufunc_kernel   s    $r=   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚDUFuncLowererzHCallable class responsible for lowering calls to a specific DUFunc.
    c                 C   s   t |ƒ| _g | _d S r   )r=   ÚkernelÚlibs)r   r   r    r    r!   r   <   s    
zDUFuncLowerer.__init__c                 C   s(   ddl m} | ||||| jjj| j¡S )Nr   r   )r;   r   Znumpy_ufunc_kernelr?   r   r<   )r   r   r   Úsigr   r   r    r    r!   Ú__call__@   s
    þzDUFuncLowerer.__call__N)r3   r4   r5   r6   r   rB   r    r    r    r!   r>   9   s   r>   c                       sî   e Zd ZdZedƒZddi fdd„Z‡ fdd„Zd	d
„ Ze	dd„ ƒZ
dd„ Zedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZdd„ Zdd „ Zd!d"„ Zd-d#d$„Zd.d%d&„Zd'd(„ Zd)d*„ Zd/d+d,„Z‡  ZS )0ÚDUFuncz¹
    Dynamic universal function (DUFunc) intended to act like a normal
    Numpy ufunc, but capable of call-time (just-in-time) compilation
    of fast loops specialized to inputs.
    )ÚidentityÚ
_keepaliveÚninÚnoutNFc              	   C   sV   t |ƒr|j}t ¡ � tf d|dœ|—Ž|ƒ}W 5 Q R X |  ||¡ t | |¡ d S )NZnpyufunc)Ú_targetÚcache)r   Úpy_funcr   Z3_suppress_deprecation_warning_nopython_not_suppliedr   Ú_initializeÚ	functoolsÚupdate_wrapper)r   rJ   rD   rI   ÚtargetoptionsÚ
dispatcherr    r    r!   r   Q   s    
ÿþþzDUFunc.__init__c                    sP   t  |¡}tt| ƒj||d� |  ¡  t| ƒ| _|  ¡  |j	j
| _
|j	j| _d S )N)rD   )r   Zparse_identityr   rC   r   Ú_install_typer>   Ú	_lower_meÚ_install_cgrJ   r3   r6   )r   rO   rD   r:   r    r!   rK   [   s    


zDUFunc._initializec                 C   s&   t | jj ¡ ƒ}t| j| j| j|d�S )ú4
        NOTE: part of ReduceMixin protocol
        )rO   rD   ÚfrozenÚsiglist)ÚlistÚ_dispatcherÚ	overloadsÚkeysÚdictrD   Ú_frozen)r   rU   r    r    r!   Ú_reduce_statesf   s    üzDUFunc._reduce_statesc                 C   s<   t j | ¡}| ||¡ |D ]}| |¡ q|r8| ¡  |S )rS   )r   Ú_DUFuncÚ__new__rK   r.   Údisable_compile)ÚclsrO   rD   rT   rU   r   rA   r    r    r!   Ú_rebuildr   s    zDUFunc._rebuildc                 C   s   | S )zK
        For compatibility with the various *UFuncBuilder classes.
        r    r%   r    r    r!   Úbuild_ufunc€   s    zDUFunc.build_ufuncc                 C   s   | j jS r   )rW   rN   r%   r    r    r!   rN   †   s    zDUFunc.targetoptionsc                 C   s   | j jS r   )r<   rF   r%   r    r    r!   rF   Š   s    z
DUFunc.ninc                 C   s   | j jS r   )r<   rG   r%   r    r    r!   rG   Ž   s    zDUFunc.noutc                 C   s   | j jS r   )r<   Únargsr%   r    r    r!   rc   ’   s    zDUFunc.nargsc                 C   s   | j jS r   )r<   Úntypesr%   r    r    r!   rd   –   s    zDUFunc.ntypesc                 C   s   | j jS r   )r<   r   r%   r    r    r!   r   š   s    zDUFunc.typesc                 C   s   | j jS r   )r<   rD   r%   r    r    r!   rD   ž   s    zDUFunc.identityc                 C   s   t | jjƒdkst‚d| _dS )zI
        Disable the compilation of new signatures at call time.
        r   TN)r(   rW   rX   ÚAssertionErrorr[   r%   r    r    r!   r_   ¢   s    zDUFunc.disable_compilec                 C   s   t  |¡\}}|  ||¡S )z=
        Compile the DUFunc for the given signature.
        )r   Znormalize_signatureÚ_compile_for_argtys)r   rA   r   r)   r    r    r!   r.   ª   s    z
DUFunc.addc           	      O   sÌ   | j j}|rLd|kr(| d¡}||f7 }|rLtdd dd„ t|ƒD ƒ¡ ƒ‚t|ƒ}||ksp||| j j kspt‚|rxt‚g }|d |… D ]4}t	|ƒ}t
|tjƒr¨|j}n
t |¡}| |¡ qˆ|  t|ƒ¡S )NÚoutz)unexpected keyword arguments to ufunc: %sz, c                 s   s   | ]}t |ƒV  qd S r   )Úrepr)r#   Úkr    r    r!   Ú	<genexpr>¹   s     z+DUFunc._compile_for_args.<locals>.<genexpr>)r<   rF   ÚpopÚ	TypeErrorÚjoinÚsortedr(   rG   re   r   Ú
isinstancer   ÚArrayZdtyper   Zmap_arrayscalar_typeÚappendrf   Útuple)	r   r   ÚkwsrF   rg   Zargs_lenÚargtysÚargZargtyr    r    r!   Ú_compile_for_args±   s(    

ÿ

zDUFunc._compile_for_argsc           	      C   s¨   | j rtd| f ƒ‚t|tƒs"t‚|dkr0|}n||Ž }t | j| j|¡\}}}t 	|||¡}t 
||¡\}}}|  t|ƒ|¡ | j ||j|f¡ | jj |j¡ |S )a/  
        Given a tuple of argument types (these should be the array
        dtypes, and not the array types themselves), compile the
        element-wise function for those inputs, generate a UFunc loop
        wrapper, and register the loop with the Numpy ufunc object for
        this DUFunc.
        zcompilation disabled for %sN)r[   ÚRuntimeErrorro   rr   re   r   Z_compile_element_wise_functionrW   rN   Z_finalize_ufunc_signatureZ!_build_element_wise_ufunc_wrapperZ	_add_loopÚintrE   rq   ZlibraryrQ   r@   )	r   rt   r)   rA   r   Z
actual_sigZ	dtypenumsZptrÚenvr    r    r!   rf   Ð   s0      ÿ
  ÿ ÿ
zDUFunc._compile_for_argtysc                 C   sB   |dkr| j jj}td| jj tft| | jd�ƒ}| 	| |¡ dS )a*  Constructs and installs a typing class for a DUFunc 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()).
        NZDUFuncTyping_)ÚkeyZgeneric)
rW   ÚtargetdescrZtyping_contextÚtyper<   r3   r
   rZ   Ú_type_meZinsert_user_function)r   Z	typingctxZ_ty_clsr    r    r!   rP   ê   s    
þzDUFunc._install_typec                 C   sj   | j r:t | |¡}|dkrdS t|j|j ƒdt|ƒ… }| jj 	¡ D ]\}}|j
|krF||f  S qFdS )a  
        Given a tuple of element-wise argument types, find a matching
        signature in the dispatcher.

        Return a 2-tuple containing the matching signature, and
        compilation result.  Will return two None's if no matching
        signature was found.
        N)NN)r[   r   Zufunc_find_matching_looprr   ÚinputsÚoutputsr(   rW   rX   Úitemsr   )r   Úewise_typesÚlooprA   r   r    r    r!   r   ø   s    	
zDUFunc.find_ewise_functionc                 C   s  |rt ‚| j}tj |||¡}|\}}}}t|ƒ}	|	dkrRt|dt|ƒ … ƒ}
nt|ƒ}
|  |
¡\}}|dkrª| jr†t	d| |f ƒ‚|  
|
¡ |  |
¡\}}|dk	sªt ‚|	dkr¼t|ƒ}n8|jdkrì|dkrât |j||¡g}qô|jg}ntdƒ‚| |¡ t|Ž S )zì
        Implement AbstractTemplate.generic() for the typing class
        built by DUFunc._install_type().

        Return the call-site signature after either validating the
        element-wise signature or compiling for it.
        r   Nzcannot call %s with types %sé   ztyping gufuncs (nout > 1))re   r<   r	   ZNumpy_rules_ufuncZ_handle_inputsr(   rr   r   r[   rl   rf   rV   rG   r   rp   r)   ÚNotImplementedErrorÚextendr   )r   rt   Zkwtysr<   Z_handle_inputs_resultZ
base_typesZexplicit_outputsZndimsZlayoutZexplicit_output_countr�   rA   r   Zouttysr    r    r!   r}     s<      ÿÿ




zDUFunc._type_mec                    sh   |dkrˆ j jj}tj}tj}|fˆ jj |fˆ jj  }|fˆ jj }| 	‡ fdd„||fD ƒ¡ dS )a-  
        Install an implementation function for a DUFunc object in the
        given target context.  If no target context is given, then
        _install_cg() installs into the target context of the
        dispatcher object (should be same default context used by
        jit() and njit()).
        Nc                    s   g | ]}ˆ j ˆ |f‘qS r    )rQ   )r#   rA   r%   r    r!   r&   D  s     z&DUFunc._install_cg.<locals>.<listcomp>)
rW   r{   Ztarget_contextr   ÚAnyrp   r<   rF   rG   Zinsert_func_defn)r   Z	targetctxZ_anyZ_arrZsig0Zsig1r    r%   r!   rR   4  s    
ÿzDUFunc._install_cg)N)N)N)r3   r4   r5   r6   ÚsetZ_DUFunc__base_kwargsr   rK   r\   Úclassmethodra   rb   ÚpropertyrN   rF   rG   rc   rd   r   rD   r_   r.   rv   rf   rP   r   r}   rR   r7   r    r    r:   r!   rC   G   s<   










(rC   )rL   Znumbar   r   Z
numba.corer   r   r   r   Znumba.core.extendingr   Znumba.core.typingr	   Znumba.core.typing.templatesr
   r   Znumba.np.ufuncr   Znumba.parforsr   r   r;   r   r=   Úobjectr>   ZReduceMixinr]   rC   Z	MAP_TYPESrq   r    r    r    r!   Ú<module>   s   +  