B
     \>                 @   s  d dl mZmZmZ d dlZd dlmZmZ d dlZd dl	Z	d dl
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 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j0ej1ej2ej3ej4ej5ej6ej7ej8ej9ej:iZ;ej<s<ej*e;ej=< ej>ej?ej@ejAejBejCejDejEejFejGejHejIiZJdd ZKejLdd ZMdd ZNdS )    )print_functiondivisionabsolute_importN)defaultdictOrderedDict   )compilerirtypesrewritessixutils)npydecl   )DUFuncc             C   s   t | tjtfS )N)
isinstancenpZufuncr   )func r   9lib/python3.7/site-packages/numba/npyufunc/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                s6   t t| j|f|| | jjj}d|kr2t|d< d S )N	arrayexpr)superr   __init__pipelineZ	targetctxspecial_ops_lower_array_expr)selfr   argskwsr   )	__class__r   r   r      s    
zRewriteArrayExprs.__init__c       	      C   s   t |dkrdS || _|| _t | _i | _|tj}x`|D ]X}|j	j
}|j}t|tjr~t||dtjr~| ||| q<t|tjr<|| j|< q<W 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             C   s   |j }| j}|dkr*|jtjk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binopcallN)opr%   fnr   supported_array_operatorsr   r)   r$   r   r
   ZFunction
typing_keyr   _has_explicit_output)r   r1   r3   r2   Zexpr_opr%   Z	func_typeZfunc_keyr   r   r   r.   C   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    ZvarargZnin)r   r3   r   nargsr   r   r   r<   ^   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 )N)r5   r6   r7   z:Don't know how to find the operator for '{0}' expressions.)r8   r9   r$   r   r)   r;   NotImplementedErrorformat)r   ir_exprir_opr   r   r   _get_array_operatorj   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.
        r6   r5   r7   z:Don't know how to find the operands for '{0}' expressions.N)r8   ZlhsZrhs	list_varsr   r>   r?   )r   r@   rA   r   r   r   _get_operandst   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)   ).0Zop_var)r   r   r   
<listcomp>   s   z5RewriteArrayExprs._translate_expr.<locals>.<listcomp>)r8   r3   rD   rB   )r   r@   rA   Zoperands_or_argsr   )r   r   _translate_expr   s    
z!RewriteArrayExprs._translate_exprc             C   s\  i }t  }tt}x<| j D ],}|j}g }| ||f}tjd|j	|| j
|jj d}t||j|j	}	|	||< |	| j|jj< x| |D ]}
|
j}|| jkr| j| }|j}| }x|D ]}
||
j  d7  < qW || | |jjrJ||jj d||< q|| jkr.|| j|  q||
j  d7  < ||
 qW q W |||fS )ztIterate over the matches, trying to find which instructions should
        be rewritten, deleted, or moved.
        r   )r8   locr3   tyr   N)setr   intr%   valuesr*   rB   r	   r+   rH   r$   r(   r)   r'   rD   rC   appendrG   Zis_tempaddr&   )r   replace_map	dead_vars	used_varsr1   r3   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"   || }x||kr|| }q
W |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_mapr1   replacementr   r   r   _get_final_replacement   s    
z(RewriteArrayExprs._get_final_replacementc             C   sB  |   \}}}| j }|  i }x| jjD ]}t|tjr||kr| ||}|r|	| xX|j
 D ]>}|j}	|	|kr|	||	 ||	 dkrl||	  d8  < qlW n
|	| q.t|tjr|j
}
||
 dkr||
  d8  < |||
< n|
|kr|	| q.|	| q.W |r>x| D ]}|| q*W |S )z}When we've found array expressions in a basic block, rewrite that
        block, returning a new, transformed block.
        r   r   )rR   r#   copyclearbodyr   r	   r'   rT   rM   r*   rC   r)   popZDelrL   Zinsert_before_terminator)r   rO   rP   rQ   resultZ
delete_mapr1   rS   varZvar_nameZinstr_valuer   r   r   apply   s<    



zRewriteArrayExprs.apply)__name__
__module____qualname____doc__r   r4   r.   r<   rB   rD   rG   rR   rT   r[   __classcell__r   r   )r!   r   r      s   !
%
r   c             C   s  t | trR| \}}g }i }x,|D ]$}t|\}}|| || q"W |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jdkr6t	|	|g }
nt	|	|g dd}
|
|fS n^t | tjrt	j| jt	 | jj| jjr| 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   r   r   z__ufunc_or_dufunc_{0}-_)      N)lineno
col_offsetz1Don't know how to translate array expression '%r')$r   tuple_arr_expr_to_astrM   updater   r:   r"   _binopsastZBinOp_cmpopsZCompare	_unaryopsAssertionErrorZUnaryOpr   r?   hexhashreplaceNameZLoadsysversion_infoZCallr	   ZVarr)   rH   linecolr/   ZNumr*   r>   )r3   r8   Zarr_expr_argsast_argsenvargZast_argZ	child_envZfn_nameZfn_ast_nameZast_callr   r   r   rh     sF    


"

rh   c          	   c   s   t  }xD| D ]<}|j}|dddd}||ks6t||f||< ||_qW t|}z
|V  W dx| D ]\}}||_qjW X dS )za
    Legalize names in the variable list for use as a Python function's
    parameter names.
    $rb   .N)r   r)   rq   rn   listrL   )Zvar_listZvar_maprZ   Zold_namenew_nameZparam_namesr   r   r   _legalize_parameter_names6  s    


r~   c          	      s  dt t|dd }|jj}| }tt|dd d}dd |D }t|}t	t
d	rnd
d |D }ndd |D }t
d||d}	t	|	drt|	jdkst|	jd }
||
j_t|j\|
jd _}t
|	 W dQ R X t|	|d}t|| || }j}j |jfdd|D  }g }x6|jD ],}t|tjrX||j n
|| q8W |j j| t!" }|dd |j# ||ddddl$m%} G  fddd|j&}fdd|D }|j'| |||ddS )z:Lower an array expression built by RewriteArrayExprs.
    z__numba_array_expr_%sra   rb   c             S   s   | j S )N)r)   )rZ   r   r   r   <lambda>V  s    z#_lower_array_expr.<locals>.<lambda>)keyc             S   s   g | ]
}|j qS r   )r)   )rE   rZ   r   r   r   rF   Y  s    z%_lower_array_expr.<locals>.<listcomp>ry   c             S   s   g | ]}t |d qS )N)rk   ry   )rE   
param_namer   r   r   rF   a  s   c             S   s   g | ]}t |t  qS r   )rk   rr   ZParam)rE   r   r   r   r   rF   e  s   zdef {0}(): returnexecrW   r   r   Nc             3   s   | ]}  |V  qd S )N)Ztypeof)rE   r)   )lowererr   r   	<genexpr>{  s    z$_lower_array_expr.<locals>.<genexpr>Zerror_modelnumpyF)flagsZcachingr   )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)rE   valZintyZoutty)r   r   r   rF     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_argsrY   )buildercres	inner_sig)r   r   generate  s    

z._lower_array_expr.<locals>.ExprKernel.generateN)r\   r]   r^   r   r   )r   r   r   r   r   
ExprKernel  s   r   c                s   g | ]}  |qS r   )Zloadvar)rE   r)   )r   r   r   rF     s    )Zexplicit_output)(ro   rp   rq   rH   filenamerC   sortedrJ   r~   hasattrrk   parser?   r"   rW   rn   r   rh   r3   r*   Zfix_missing_locationscompiler   Zexec_r   r   rI   r   r
   r-   rM   Zdtyper   r   ZFlagsZcompile_subroutineZtargetsr   Z_KernelZnumpy_ufunc_kernel)r   r3   Z	expr_nameZexpr_filenameZexpr_var_listZexpr_var_uniqueZ	expr_argsZexpr_paramsrw   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   N  sN    




r   )OZ
__future__r   r   r   rk   collectionsr   r   
contextlibrs   r   r   operator r   r	   r
   r   r   r   typingr   Zdufuncr   r   Zregister_rewriteZRewriter   posZUAddnegZUSubinvertZInvertrm   rN   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FloorDivrj   ZIS_PY3ZdiveqZEqneZNotEqltZLtleZLtEgtZGtgeZGtErl   rh   contextmanagerr~   r   r   r   r   r   <module>   sN    
 U+