U
    ,d>                     @   sr  d dl Z d dlmZmZ d dlZd dlZd dlmZ d dlZ	d dl
Z
d dlmZmZmZmZmZ d dlmZ d dlmZ dd Zed	G d
d dejZe
je je
je je
je jiZe
je j e
j!e j"e
j#e j$e
j%e j&e
j'e j(e
j)e j*e
j+e j,e
j-e j.e
j/e j0e
j1e j2e
j3e j4e
j5e j6iZ7e
j8e j9e
j:e j;e
j<e j=e
j>e j?e
j@e jAe
jBe jCiZDdd ZEejFdd ZGdd ZHdS )    N)defaultdictOrderedDict)SimpleNamespace)typestargetconfigirrewritescompiler)npydecl)DUFuncc                 C   s   t | tjtfS N)
isinstancenpufuncr   )func r   >/tmp/pip-unpacked-wheel-eu7e0c37/numba/np/ufunc/array_exprs.py	_is_ufunc   s    r   zafter-inferencec                       sh   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Z  ZS )RewriteArrayExprszThe RewriteArrayExprs class is responsible for finding array
    expressions in Numba intermediate representation code, and
    rewriting those expressions to a single operation that will expand
    into something similar to a ufunc call.
    c                    s4   t t| j|f|| |jj}d|kr0t|d< d S )N	arrayexpr)superr   __init__Z	targetctxspecial_ops_lower_array_expr)selfstateargskwsr   	__class__r   r   r      s    zRewriteArrayExprs.__init__c           	      C   s   t |dkrdS || _|| _t | _i | _|tj}|D ]X}|j	j
}|j}t|tjr|t||dtjr|| ||| q:t|tjr:|| j|< q:t | jdkS )z
        Using typing and a basic block, search the basic block for array
        expressions.
        Return True when one or more matches were found, False otherwise.
        r   FN)len
crnt_blocktypemapr   array_assignsconst_assignsZ
find_instsr   Assigntargetnamevaluer   Exprgetr   Array_match_array_exprConst)	r   Zfunc_irblockr"   Z	calltypesZassignmentsinstrtarget_nameexprr   r   r   match!   s"    zRewriteArrayExprs.matchc                    s   |j } j}|dkrD|jtjkrDt fdd| D r|||< nR|dkr|jj j	kr j	|jj }t
|tjr|j}t|r ||s|||< dS )z
        Find whether the given assignment (*instr*) of an expression (*expr*)
        to variable *target_name* is an array expression.
        unarybinopc                 3   s   | ]} j |j jV  qd S r   )r"   r'   Zis_internal.0varr   r   r   	<genexpr>Q   s   z6RewriteArrayExprs._match_array_expr.<locals>.<genexpr>callN)opr#   fnr
   supported_array_operatorsall	list_varsr   r'   r"   r   r   ZFunction
typing_keyr   _has_explicit_output)r   r/   r1   r0   Zexpr_opr#   Z	func_typeZfunc_keyr   r9   r   r,   B   s     

z#RewriteArrayExprs._match_array_exprc                 C   s,   t |jt |j }|jdk	r"dS ||jkS )zr
        Return whether the *expr* call to *func* (a ufunc) features an
        explicit output argument.
        NT)r    r   r   varargnin)r   r1   r   nargsr   r   r   rB   `   s    
z&RewriteArrayExprs._has_explicit_outputc                 C   s>   |j }|dkr|jS |dkr,| j|jj jS td|d S )Nr3   r;   z:Don't know how to find the operator for '{0}' expressions.)r<   r=   r"   r   r'   rA   NotImplementedErrorformatr   ir_exprir_opr   r   r   _get_array_operatorl   s    z%RewriteArrayExprs._get_array_operatorc                 C   sJ   |j }|dkr|j|jfS |dkr*| S |dkr8|jS td|dS )z{Given a Numba IR expression, return the operands to the expression
        in order they appear in the expression.
        r5   r4   r;   z:Don't know how to find the operands for '{0}' expressions.N)r<   lhsrhsr@   r   rF   rG   rH   r   r   r   _get_operandsv   s    zRewriteArrayExprs._get_operandsc                    s:   |j }|dkr|jS  fdd |D } ||fS )zZTranslate the given expression from Numba IR to an array expression
        tree.
        r   c                    s   g | ]} j |j|qS r   )r$   r*   r'   )r7   Zop_varr9   r   r   
<listcomp>   s   z5RewriteArrayExprs._translate_expr.<locals>.<listcomp>)r<   r1   rN   rK   )r   rI   rJ   Zoperands_or_argsr   r9   r   _translate_expr   s    
z!RewriteArrayExprs._translate_exprc                 C   sV  i }t  }tt}| j D ],}|j}g }| ||f}tjd|j	|| j
|jj d}t||j|j	}	|	||< |	| j|jj< | |D ]}
|
j}|
jr|| jkr| j| }|j}| }|D ]}
||
j  d7  < q|| | |jjrH||jj d||< q|| jkr,|| j|  q||
j  d7  < ||
 qq|||fS )ztIterate over the matches, trying to find which instructions should
        be rewritten, deleted, or moved.
        r   )r<   locr1   ty   N)setr   intr#   valuesr(   rK   r   r)   rQ   r"   r&   r'   r%   rN   Zis_tempr@   appendrP   addr$   )r   replace_map	dead_vars	used_varsr/   r1   Zarr_inpsZarr_exprZnew_exprZ	new_instrZoperandZoperand_nameZchild_assignZ
child_exprZchild_operandsr   r   r   _handle_matches   s@    


z!RewriteArrayExprs._handle_matchesc                 C   s   || }||kr|| }q|S )zFind the final replacement instruction for a given initial
        instruction by chasing instructions in a map from instructions
        to replacement instructions.
        r   )r   Zreplacement_mapr/   replacementr   r   r   _get_final_replacement   s    
z(RewriteArrayExprs._get_final_replacementc                 C   s6  |   \}}}| j }|  i }| jjD ]}t|tjr||kr| ||}|r|	| |j
 D ]>}|j}	|	|kr|	||	 ||	 dkrh||	  d8  < qhn
|	| q,t|tjr|j
}
||
 dkr||
  d8  < |||
< n|
|kr|	| q,|	| q,|r2| D ]}|| q |S )z}When we've found array expressions in a basic block, rewrite that
        block, returning a new, transformed block.
        r   rS   )r\   r!   copyclearbodyr   r   r%   r^   rW   r(   r@   r'   popZDelrV   Zinsert_before_terminator)r   rY   rZ   r[   resultZ
delete_mapr/   r]   r8   var_nameZinstr_valuer   r   r   apply   s@    
 


zRewriteArrayExprs.apply)__name__
__module____qualname____doc__r   r2   r,   rB   rK   rN   rP   r\   r^   re   __classcell__r   r   r   r   r      s   !
%
r   c                 C   s  t | tr.| \}}g }i }|D ]$}t|\}}|| || q |tjkrt|dkr|tkrt	
|d t|  |d |fS |tkrt	|d t|  g|d g|fS n&|tkstt	t|  |d |fS nRt|rdtt|dd}t	|t	 }	|||< t	|	|g }
|
|fS n^t | tjrnt	j| jt	 | jj| jjrb| jjnddi fS t | tjrt	| j i fS t!d| f d	S )
z[Build a Python expression AST from an array expression built by
    RewriteArrayExprs.
       r   rS   z__ufunc_or_dufunc_{0}-_)lineno
col_offsetz1Don't know how to translate array expression '%r'N)"r   tuple_arr_expr_to_astrW   updater
   r>   r    _binopsastZBinOp_cmpopsZCompare	_unaryopsAssertionErrorZUnaryOpr   rG   hexhashreplaceNameLoadZCallr   ZVarr'   rQ   linecolr-   ZNumr(   rF   )r1   r<   Zarr_expr_argsast_argsenvargZast_argZ	child_envfn_nameZfn_ast_nameZast_callr   r   r   rq   
  s`    

   
 

rq   c              	   c   s   t  }| D ]Z}|j}|jj||jdj}|dddd}||krRt|d||f||< ||_q
t|}z
|V  W 5 | D ]\}}||_qX dS )za
    Legalize names in the variable list for use as a Python function's
    parameter names.
    )rQ   $rm   .z not uniqueN)	r   r'   ZscopeZredefinerQ   rz   rw   listrV   )Zvar_listZvar_mapr8   Zold_namenew_nameZparam_namesr   r   r   _legalize_parameter_names2  s    
r   c              	      s  dt t|dd }|jj}| }tt|dd d}dd |D }t|v}d	d |D }t	
d
||d}	t|	drt|	jdkst|	jd }
||
j_t|j\|
jd _}t	|	 W 5 Q R X t|	|d}t|| || }j}j |jfdd|D  }g }|jD ]@}t|tjr2|j}t|tjrN||j  n
|| q|j!j | t"# $ }|dkrt%& n|' }d|_(|j) ||ddddl*m+} G  fddd|j,}t-t|d|d}|j.|j/ |_0fdd|D }|1| ||||S )z:Lower an array expression built by RewriteArrayExprs.
    z__numba_array_expr_%srl   rm   c                 S   s   | j S r   r'   )r8   r   r   r   <lambda>T      z#_lower_array_expr.<locals>.<lambda>)keyc                 S   s   g | ]
}|j qS r   r   r6   r   r   r   rO   W  s     z%_lower_array_expr.<locals>.<listcomp>c                 S   s   g | ]}t |d qS r   )rt   r   )r7   
param_namer   r   r   rO   [  s   zdef {0}(): returnexecra   rS   r   c                 3   s   | ]}  |V  qd S r   )Ztypeofr7   r'   lowererr   r   r:   p  s     z$_lower_array_expr.<locals>.<genexpr>NnumpyF)flagsZcaching)npyimplc                       s   e Zd Z fddZdS )z%_lower_array_expr.<locals>.ExprKernelc                    sL   t | jjj} fdd|D } jj|} |j jjS )Nc                    s    g | ]\}}}  |||qS r   )cast)r7   valZintyZouttyr9   r   r   rO     s   zB_lower_array_expr.<locals>.ExprKernel.generate.<locals>.<listcomp>)zip	outer_sigr   contextZcall_internalZfndescr   return_type)r   r   Zarg_zipZ	cast_argsrc   buildercres	inner_sigr9   r   generate  s    
   
z._lower_array_expr.<locals>.ExprKernel.generateN)rf   rg   rh   r   r   r   r   r   
ExprKernel  s   r   )rD   noutrf   c                    s   g | ]}  |qS r   )Zloadvarr   r   r   r   rO     s     )2rx   ry   rz   rQ   filenamer@   sortedrT   r   rt   parserG   hasattrr    ra   rw   r   rq   r1   r(   Zfix_missing_locationscompiler   r   r   rR   r   r   Optionaltyper+   rW   Zdtyper   r   ZConfigStackZtop_or_noner	   ZFlagsr_   Zerror_modelZcompile_subroutineZnumba.npr   Z_Kernelr   rD   r   rE   Znumpy_ufunc_kernel)r   r1   Z	expr_nameZexpr_filenameZexpr_var_listZexpr_var_uniqueZ	expr_argsZexpr_paramsr   Z
ast_moduleZast_fn	namespaceZcode_objimplr   r   Zinner_sig_argsZargtyr   r   r   r   r   r   )r   r   r   r   r   r   L  sf    
 


     r   )Irt   collectionsr   r   
contextlibsysr   r   r   r   operatorZ
numba.corer   r   r   r	   Znumba.core.typingr
   Znumba.np.ufunc.dufuncr   r   Zregister_rewriteZRewriter   posZUAddnegZUSubinvertZInvertrv   rX   ZAddsubZSubmulZMulttruedivZDivmodZModor_ZBitOrrshiftZRShiftxorZBitXorlshiftZLShiftand_ZBitAndpowZPowfloordivZFloorDivrs   eqZEqneZNotEqltZLtleZLtEgtZGtgeZGtEru   rq   contextmanagerr   r   r   r   r   r   <module>   s|    X                     
(
