a
    .;b>                     @   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   9lib/python3.9/site-packages/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                    s:   t t| j|g|R i | |jj}d|vr6t|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v rD|jtjv rDt fdd| D r|||< nR|dkr|jj j	v 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u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v 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<   ZlhsZ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   rL   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v r| j| }|j}| }|D ]}
||
j  d7  < q|| | |jjrH||jj d||< q|| jv 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)   rO   r"   r&   r'   r%   rL   Zis_tempr@   appendrN   addr$   )r   replace_map	dead_vars	used_varsr/   r1   Zarr_inpsZarr_exprZnew_exprZ	new_instroperandZoperand_nameZchild_assignZ
child_exprZchild_operandsr   r   r   _handle_matches   s@    


z!RewriteArrayExprs._handle_matchesc                 C   s   || }||v 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||v r| ||}|r|	| |j
 D ]>}|j}	|	|v r|	||	 ||	 dkrh||	  d8  < qhn
|	| q,t|tjr|j
}
||
 dkr||
  d8  < |||
< n|
|v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   rQ   )r[   r!   copyclearbodyr   r   r%   r]   rU   r(   r@   r'   popZDelrT   Zinsert_before_terminator)r   rW   rX   rY   resultZ
delete_mapr/   r\   r8   Zvar_nameZinstr_valuer   r   r   apply   s>    



zRewriteArrayExprs.apply)__name__
__module____qualname____doc__r   r2   r,   rB   rK   rL   rN   r[   r]   rc   __classcell__r   r   r   r   r      s   !
%
r   c                 C   s  t | tr.| \}}g }i }|D ]$}t|\}}|| || q |tjv rt|dkr|tv rt	
|d t|  |d |fS |tv rt	|d t|  g|d g|fS n&|tv sJ 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   rQ   z__ufunc_or_dufunc_{0}-_)lineno
col_offsetz1Don't know how to translate array expression '%r'N)!r   tuple_arr_expr_to_astrU   updater
   r>   r    _binopsastZBinOp_cmpopsZCompare	_unaryopsZUnaryOpr   rG   hexhashreplaceNameZLoadZCallr   ZVarr'   rO   linecolr-   ZNumr(   rF   )r1   r<   Zarr_expr_argsast_argsenvargZast_argZ	child_envZfn_nameZfn_ast_nameZast_callr   r   r   ro   
  sX    



ro   c              	   c   s   t  }| D ]Z}|j}|jj||jdj}|dddd}||v rRt|d||f||< ||_q
t|}z"|V  W | D ]\}}||_qn| D ]\}}||_q0 dS )za
    Legalize names in the variable list for use as a Python function's
    parameter names.
    )rO   $rk   .z not uniqueN)	r   r'   ZscopeZredefinerO   rw   AssertionErrorlistrT   )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|}d	d |D }t	
d
||d}	t|	drt|	jdksJ |	jd }
||
j_t|j\|
jd _}t	|	 W d   n1 s0    Y  t|	|d}t|| || }j}j |jfdd|D  }g }|jD ]@}t|tjrF|j}t|tjrb||j n
|| q.|j j| t!" # }|du rt$% n|& }d|_'|j( ||ddddl)m*} G  fddd|j+}t,t|d|d}|j-|j. |_/fdd|D }|0| ||||S )z:Lower an array expression built by RewriteArrayExprs.
    z__numba_array_expr_%srj   rk   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   rM   W  r   z%_lower_array_expr.<locals>.<listcomp>c                 S   s   g | ]}t |d qS r   )rr   r}   )r7   Z
param_namer   r   r   rM   [  s   zdef {0}(): returnexecr`   rQ   r   Nc                 3   s   | ]}  |V  qd S r   )Ztypeofr7   r'   lowererr   r   r:   p  r   z$_lower_array_expr.<locals>.<genexpr>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   rM     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_argsrb   buildercres	inner_sigr9   r   generate  s    


z._lower_array_expr.<locals>.ExprKernel.generateN)rd   re   rf   r   r   r   r   r   
ExprKernel  s   r   )rD   noutrd   c                    s   g | ]}  |qS r   )Zloadvarr   r   r   r   rM     r   )1ru   rv   rw   rO   filenamer@   sortedrR   r   rr   parserG   hasattrr    r`   r   ro   r1   r(   Zfix_missing_locationscompiler   r   r   rP   r   r   Optionaltyper+   rU   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  sZ    

(

r   )Irr   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Invertrt   rV   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FloorDivrq   eqZEqneZNotEqltZLtleZLtEgtZGtgeZGtErs   ro   contextmanagerr   r   r   r   r   r   <module>   sR    X
(
