B
     \*                 @   s   d dl mZmZmZ d dlZddlmZmZm	Z	m
Z
mZmZ ddlmZ ddlmZmZ ddlmZ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Zeje dS )    )absolute_importprint_functiondivisionN   )jittypeofutilstypesnumpy_supportsigutils)npydecl)AbstractTemplate	signature   )	_internalufuncbuilder)
Dispatcher)array_analysisc                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__ 4lib/python3.7/site-packages/numba/npyufunc/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}|j| jjjd}|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>)nameZalwaysinline)r   r   zipr   r   Z
objectmoder   Z	call_convZget_function_typer	   Zpyobjectlenreturn_typer   blockZfunctionmoduleZget_or_insert_functionZfndescZllvm_func_nameZ
attributesaddZcall_functionr$   )
r   r   ZisigZosigZ	cast_argsZ	func_typer-   Zentry_point_Zresr"   )r   r#   generate   s"    

z1make_dufunc_kernel.<locals>.DUFuncKernel.generate)__name__
__module____qualname____doc__r   r   r0   __classcell__r"   )r    _dufunc)r!   r#   r       s   r    )targetsr   Z_Kernelr1   ufunc)r6   r   r"   )r    r6   r#   make_dufunc_kernel   s    "r9   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 )N)r9   kernellibs)r   r   r"   r"   r#   r   8   s    
zDUFuncLowerer.__init__c             C   s8   ddl m} t|| jjjjk}|j||||| j|dS )Nr   )r   )explicit_output)r7   r   r*   r;   r   r8   ninZnumpy_ufunc_kernel)r   r   r   sigr   r   r=   r"   r"   r#   __call__<   s
    zDUFuncLowerer.__call__N)r1   r2   r3   r4   r   r@   r"   r"   r"   r#   r:   5   s   r:   c                   s   e Zd ZdZedZddi f f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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 )(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
_keepaliver>   noutNFc                s~   t |tr|j}| | _i }t||d< td|d|}tt	| j
|f| |   t| | _|   |j| _|j| _d S )NrB   Znpyufunc)targetcache)
isinstancer   py_funccopytargetoptionsr   Zparse_identityr   r   rA   r   _install_typer:   	_lower_me_install_cgr1   r4   )r   rH   rB   rF   rJ   kws
dispatcher)r!   r"   r#   r   N   s    


zDUFunc.__init__c             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 )N)r8   r>   )r   r"   r"   r#   r>   e   s    z
DUFunc.ninc             C   s   | j jS )N)r8   rD   )r   r"   r"   r#   rD   i   s    zDUFunc.noutc             C   s   | j jS )N)r8   nargs)r   r"   r"   r#   rQ   m   s    zDUFunc.nargsc             C   s   | j jS )N)r8   ntypes)r   r"   r"   r#   rR   q   s    zDUFunc.ntypesc             C   s   | j jS )N)r8   r	   )r   r"   r"   r#   r	   u   s    zDUFunc.typesc             C   s   | j jS )N)r8   rB   )r   r"   r"   r#   rB   y   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*   _dispatcher	overloadsAssertionError_frozen)r   r"   r"   r#   disable_compile}   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   r?   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 }xT|d | D ]D}t	
|r|t	| qt|}t|tjr|j}|| qW | t|S )Noutz)unexpected keyword arguments to ufunc: %sz, c             s   s   | ]}t |V  qd S )N)repr)r%   kr"   r"   r#   	<genexpr>   s    z+DUFunc._compile_for_args.<locals>.<genexpr>)r8   r>   pop	TypeErrorjoinsortedr*   rD   rU   r
   Zis_arrayscalarappendZmap_arrayscalar_typer   rG   r	   ArrayZdtyperX   tuple)	r   r   rN   r>   rY   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)rV   RuntimeErrorrG   rc   rU   r   Z_compile_element_wise_functionrS   rJ   Z_finalize_ufunc_signatureZ!_build_element_wise_ufunc_wrapperZ	_add_loopr   ZlongintrC   ra   ZlibraryrL   r<   )	r   rd   r+   r?   r   Z
actual_sigZ	dtypenumsZptrenvr"   r"   r#   rX      s     
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)
rS   targetdescrZtyping_contexttyper8   r1   r   dict_type_meZinsert_user_function)r   Z	typingctxZ_ty_clsr"   r"   r#   rK      s    
zDUFunc._install_typec             C   sj   | j r:t| |}|dkrdS t|j|j dt| }x*| jj	 D ]\}}|j
|krH||fS qHW d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)rV   r
   Zufunc_find_matching_looprc   ZinputsZoutputsr*   rS   rT   itemsr   )r   ewise_typesZloopr?   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rt	d| |f | 
|
 | |
\}}|dk	st |	dkrt|}n8|jdkr|dkrt|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 %sr   ztyping gufuncs (nout > 1))rU   r8   r   ZNumpy_rules_ufuncZ_handle_inputsr*   rc   r   rV   r^   rX   listrD   r	   rb   r+   NotImplementedErrorextendr   )r   rd   Zkwtysr8   Z_handle_inputs_resultZ
base_typesZexplicit_outputsZndimsZlayoutZexplicit_output_countro   r?   r   Zouttysr"   r"   r#   rm      s4    





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"   )rL   )r%   r?   )r   r"   r#   r'     s    z&DUFunc._install_cg.<locals>.<listcomp>)
rS   rj   Ztarget_contextr	   ZAnyrb   r8   r>   rD   Zinsert_func_defn)r   Z	targetctxZ_anyZ_arrZsig0Zsig1r"   )r   r#   rM     s    
zDUFunc._install_cg)N)N)N)r1   r2   r3   r4   setZ_DUFunc__base_kwargsr   rP   propertyr>   rD   rQ   rR   r	   rB   rW   r.   rf   rX   rK   r   rm   rM   r5   r"   r"   )r!   r#   rA   D   s$   

(rA   )Z
__future__r   r   r   ZnumpyZnp r   r   r   r	   r
   r   typingr   Ztyping.templatesr   r   r   r   rO   r   r   r9   objectr:   Z_DUFuncrA   Z	MAP_TYPESra   r"   r"   r"   r#   <module>   s    ) [