U
    hâËdu›  ã                   @   sþ   d dl Z d dlZd dlmZ d dlmZmZm	Z	mZm
Z
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 d dlmZ d dlZd dlZd d	lmZ G d
d„ deƒZedd„ ƒZ dd„ Z!G dd„ deƒZ"ddd„Z#dd„ Z$ee#ƒdd„ ƒZ%dS )é    N)Úir)ÚtypesÚtypingÚutilsr   ÚconfigÚir_utilsÚregistry)ÚCallableTemplateÚ	signatureÚinfer_globalÚAbstractTemplate)Úlower_builtin)Úregister_jitable)ÚNumbaValueError)Úliteral_unroll)Únumpy_supportc                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚStencilFuncLowererzMCallable class responsible for lowering calls to a specific StencilFunc.
    c                 C   s
   || _ d S ©N)ÚstencilFunc)ÚselfZsf© r   úO/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/numba/stencils/stencil.pyÚ__init__   s    zStencilFuncLowerer.__init__c                 C   s:   | j  |ji |jd ¡}| ||j||¡}| |jg¡ |S r   )r   Úcompile_for_argtysÚargsÚreturn_typeZcall_internalZfndescZadd_linking_libsZlibrary)r   ÚcontextÚbuilderÚsigr   ZcresÚresr   r   r   Ú__call__   s     ÿzStencilFuncLowerer.__call__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r    r   r   r   r   r      s   r   c                 G   s\   | j }t|ƒD ]H}| j|jkr&tdƒ‚|j }tt|ƒƒD ]}|| || kr8tdƒ‚q8qd S )Nz\Secondary stencil array does not have same number  of dimensions as the first stencil input.zaSecondary stencil array has some dimension smaller the same dimension in the first stencil input.)Úshaper   ÚndimÚ
ValueErrorÚrangeÚlen)Úar   ZashapeÚargZargshapeÚir   r   r   Ú!raise_if_incompatible_array_sizes$   s    
r-   c                 C   s   t | j| | j| ƒS )z_ Called by stencil in Python mode to add the loop index to a
        user-specified slice.
    )ÚsliceÚstartÚstop)Z	the_sliceÚaddendr   r   r   Úslice_addition;   s    r2   c                   @   sd   e Zd ZdZ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dd„ ZdS )ÚStencilFuncz@
    A special type to hold stencil information for the IR.
    r   c                 C   sŒ   t | ƒj| _t | ƒ jd7  _|| _|| _|| _g | _tjj	| _
tjj| _| j
 ¡  | j ¡  |  | j
¡ | j d¡| _i | _t| ƒ| _d S )Né   Úneighborhood)ÚtypeÚ
id_counterÚidÚ	kernel_irÚmodeÚoptionsÚkwsr   Z
cpu_targetZtyping_contextÚ
_typingctxZtarget_contextÚ
_targetctxÚrefreshÚ_install_typeÚgetr5   Ú_type_cacher   Ú	_lower_me)r   r9   r:   r;   r   r   r   r   H   s    



zStencilFunc.__init__c              
   C   s&  g }|  ¡ D �]\}}|j}|j}g }	|jD ]ì}
t|
tjƒ�r| |¡ t|ƒdkrŽt 	|||¡}t 	||d |¡}|	 t 
|||
j|¡¡ n~g }|D ]}t 	|||¡}||g7 }q–| d|¡}tj ||¡}|	 t |||¡¡ t 	|||¡}t 
|||
j|¡}|	 |¡ q,|	 |
¡ q,|	|_q|S )zß
        Find return statements in the IR and replace them with a SetItem
        call of the value "returned" by the kernel into the result array.
        Returns the block labels that contained return statements.
        r4   r   Ústencil_index)ÚitemsÚscopeÚlocÚbodyÚ
isinstancer   ÚReturnÚappendr)   ÚVarÚSetItemÚvalueÚredefineÚExprÚbuild_tupleÚAssign)r   ÚblocksÚ
index_varsÚout_nameÚ
ret_blocksÚlabelÚblockrF   rG   Únew_bodyÚstmtZrvarZivarZvar_index_varsZone_varÚ	index_varÚs_index_varÚ
tuple_callÚsir   r   r   Úreplace_return_with_setitemZ   s2    

z'StencilFunc.replace_return_with_setitemc           *      C   sâ  i }g }	t jdkr*td||ƒ t |j¡ |dkr8d}
n$d}
t|ƒ|kr\tdt|ƒ|f ƒ‚t |j¡}t	ƒ }|j 
¡ D �]}|j}|j}g }|jD �]ò}t|tjƒrât|jtjƒrât jdkrÒtd|jj|jjƒ |jj||jj< t|tjƒ�r t|jtjƒ�r |jjdk�r |jjj|jk�s>t|tjƒ�rF|jj|jk�rFtd	ƒ‚t|tjƒ�r~t|jtjƒ�r~|jjd
k�r~|jjj|jk�r~|jjj|k�r~|jjdk�r¬|jj}n|jj}| |jjj¡ |
�rt|dƒ�sÚt‚|j|k�rø|	||j g7 }	n&|j|k�r|	||j g7 }	ntdƒ‚|dk�rlt ||d |¡}|  d|¡}||j }t|t!j"j#ƒ�r|  d|¡}t$ %t&¡}t!j' (|¡}|||j< t )d||¡}| *t |||¡¡ tj +|||gd|¡}| ,| j-|t!j.gi ¡||< | *t |||¡¡ | *t tj /|jj||¡|j|¡¡ nNtj 0t1j|||¡}| *t |||¡¡ | *t tj /|jj||¡|j|¡¡ �qˆg }g }|  d|¡}g }g } ||j }t2|ƒD �]–}!|  d|¡}| *t t |!|¡||¡¡ ||g7 }t |||! |¡}||g7 }|  d|¡}| |g7 } |  d|¡}"tj /|||! |¡}#| *t |#|"|¡¡ t|t!j3ƒ�rP||! }$n|dd… }$t|$t!j"j#ƒ�r|  d|¡}t$ %t&¡}t!j' (|¡}|||j< t )d||¡}| *t |||¡¡ tj +||"||! gd|¡}| ,| j-|$t!j.gi ¡||< | *t |||¡¡ n,tj 0t1j|"||! |¡}| *t |||¡¡ �qštj 4| |¡}%| *t |%||¡¡ | *t tj /|jj||¡|j|¡¡ q”| *|¡ q”||_qx|
�rÚdd„ t2|ƒD ƒ}t|	ƒdk�rÀtdƒ‚|	D �]}&t|&t5ƒ�sât|&t6ƒ�rvt2t|&ƒƒD ]|}'|&|' }(t|(tjƒ�r|(j|k�r||(j }(t|(t7ƒ�r`t8||' d |(ƒ||' d< t9||' d |(ƒ||' d< ntdƒ‚�qît|&ƒ})nNt|&t7ƒ�r¼t8|d d |&ƒ|d d< t9|d d |&ƒ|d d< d})ntdƒ‚|)|k�rÄtdƒ‚�qÄ||fS )zß
        Transforms the stencil kernel as specified by the user into one
        that includes each dimension's index variable as part of the getitem
        calls.  So, in effect array[-1] becomes array[index0-1].
        r4   Úadd_indices_to_kernelNTFúD%d dimensional neighborhood specified for %d dimensional input arrayzremembering in const_dict)ÚsetitemZstatic_setitemz?Assignments to arrays passed to stencil kernels is not allowed.)ÚgetitemZstatic_getitemrc   ÚnamezDstencil kernel index is not constant, 'neighborhood' option requiredr   rD   r2   r   Úconst_indexZind_stencil_indexc                 S   s   g | ]}d d g‘qS )r   r   )Ú.0Ú_r   r   r   Ú
<listcomp>+  s     z5StencilFunc.add_indices_to_kernel.<locals>.<listcomp>z=Stencil kernel with no accesses to relatively indexed arrays.zCstencil kernel index is not constant,'neighborhood' option requiredz/Non-tuple or non-integer used as stencil index.z2Stencil index does not match array dimensionality.):r   ÚDEBUG_ARRAY_OPTÚprintr   Údump_blocksrS   r)   r'   Zget_tuple_tableÚsetÚvaluesrF   rG   rH   rI   r   rR   rN   ZConstÚtargetrd   rP   ÚopÚ	arg_namesrM   Úindexr[   ÚaddÚhasattrÚAssertionErrorr   rL   rO   r   ÚmiscZ	SliceTypeÚnumbaZnjitr2   Z	functionsZ
DispatcherÚGlobalrK   ÚcallZget_call_typer=   Úintprc   ZbinopÚoperatorr(   Z
ConstSizedrQ   ÚtupleÚlistÚintÚminÚmax)*r   ZkernelZindex_namesr&   r5   Ústandard_indexedÚtypemapÚ	calltypesZ
const_dictZkernel_constsZneed_to_calc_kernelZtuple_tableÚrelatively_indexedrX   rF   rG   rY   rZ   Zstmt_index_varr[   ZtmpvarZstmt_index_var_typZsa_varZsa_funcZsa_func_typZg_saZslice_addition_callZacc_callrT   Zsum_resultsr\   Zconst_index_varsZind_stencilsÚdimZ
getitemvarZgetitemcallZone_index_typr]   rq   r,   ÚteZ	index_lenr   r   r   r`   „   sN   

ÿÿ

ÿÿ
þý
üûÿ
þýü




 þ ÿ þ

 ÿ


 ÿ


 ÿ þ

ÿ
ÿ
ÿz!StencilFunc.add_indices_to_kernelc                 C   s¦   t jdkr"td|ƒ t | jj¡ t|d tj	j
ƒs<tdƒ‚ddlm} | | j| j| j|d i ¡\}}}}t|tj	j
ƒr€tdƒ‚tj	 
||d j|d j¡}|||fS )Nr4   Úget_return_typer   zGThe first argument to a stencil kernel must be the primary input array.)Útyped_passesz:Stencil kernel must return a scalar and not a numpy array.)r   ri   rj   r   rk   r9   rS   rI   r   ÚnpytypesÚArrayr   Ú
numba.corer‡   Ztype_inference_stager=   r>   r&   Zlayout)r   Úargtysr‡   r�   r   r‚   rg   Úreal_retr   r   r   r†   L  s,    

úÿÿzStencilFunc.get_return_typec                 C   s2   t dt| jƒ tft| | jd�ƒ}| | |¡ dS )zmConstructs and installs a typing class for a StencilFunc object in
        the input typing context.
        ZStencilFuncTyping_)ÚkeyZgenericN)r6   Ústrr8   r   ÚdictÚ_type_meZinsert_user_function)r   Z	typingctxZ_ty_clsr   r   r   r@   e  s    ÿýzStencilFunc._install_typec           
      C   s.   | j | \}}}}| j|||||f|žŽ }	|	S r   )rB   Ú_stencil_wrapper)
r   r‹   Úkwtysr   Úsigretrg   Úresultr�   r‚   Únew_funcr   r   r   r   o  s    
 ÿÿzStencilFunc.compile_for_argtysc                 C   s8  | j dk	r:t| j ƒ|d jkr:tdt| j ƒ|d jf ƒ‚|}d}d}d|krl||d f7 }|d7 }|d }d|krŠ||d f7 }|d7 }|| jkrª| j| \}}}}|S |  |¡\}}	}
t|f|žŽ }d	 d
 | j	j
¡|¡}t|ƒtƒ ktƒ f tdƒ}|jt |¡d�}| j | j| |fg¡ |||	|
f| j|< |S )z¡
        Implement AbstractTemplate.generic() for the typing class
        built by StencilFunc._install_type().
        Return the call-site signature.
        Nr   ra   Ú Úoutz
, out=Noner5   z, neighborhood=Nonez*def __numba_dummy_stencil({}{}):
    pass
ú,Z__numba_dummy_stencil)Úpysig)r5   r)   r&   r   rB   r†   r
   ÚformatÚjoinr9   rp   ÚexecÚglobalsÚlocalsÚevalÚreplacer   Úpysignaturer>   Zinsert_func_defnrC   )r   r‹   r’   Zargtys_extraÚ	sig_extrar”   Z_sigrg   rŒ   r�   r‚   r   Z
dummy_textZ
dummy_funcr   r   r   r�   v  s>    
ÿþ
 ÿzStencilFunc._type_mec           
      C   sŠ   i }|  ¡ }i |_|j ¡ D ]d\}}t  |j| ¡}g |_|j| jD ].}t  |¡}	|j |	¡ ||krF|| ||	< qF||j|< q||fS )a  
        Create a copy of a given IR along with its calltype information.
        We need a copy of the calltypes because copy propagation applied
        to the copied IR will change the calltypes and make subsequent
        uses of the original IR invalid.
        )ÚcopyrS   rE   ÚdeepcopyrH   rK   )
r   r   r‚   Úcopy_calltypesÚkernel_copyZblock_labelrX   Z	new_blockrZ   Zscopyr   r   r   Úcopy_ir_with_calltypesž  s    
z"StencilFunc.copy_ir_with_calltypesc           C   
      s&  |   | j|¡\}}t |j¡ |jd }	t |j|¡\}
}t |j¡}t |j|
|||¡ d|krjt	dƒ‚t 
d|¡}tjdkrŒtd||ƒ |d }tjdkrÂtd||jt|jƒ|ƒ t |j¡ dtt|ƒƒ d	d
¡| jf }g }t|jƒD ]"}t 
dt|ƒ |¡}||g7 }qît 
d|¡}t 
d|¡}d}|d k	�rF|d |¡7 }dt| jƒk�rd|d |¡7 }| j dg ¡}|	|k�r„t	dƒ‚tt|ƒt|jƒ ƒdk�r¨t	dƒ‚|  |||j| j|||¡\}}| jd k�rØ|| _tjdk�røtdƒ t |j¡ |   |j||¡}tjdk�r*td|ƒ t |j¡ d |d !|j¡|¡}g }t|jƒD ]Z}t"|| d t#ƒ�r€|| d }|| d }nd ||¡}d ||¡}| $||f¡ �qNt|ƒdk�rî|d|	 7 }|D ]}||	k�rÈ|d| 7 }�qÈ|d7 }t 
d|¡}|d ||	¡7 }dd„ } |d k�r(t% &|j¡jj'}!d |||!¡}"d| jk�r|| jd }#t(j) )|#¡}$| j* +|$|j¡�s€d }%t	|%ƒ‚nd}#|d!|" 7 }t|jƒD ]Ž}&d"g|j }'d"g|j }(d# | j|& d ¡|'|&< d$ | j|& d ¡|(|&< |d!d% |d !|'¡| |#ƒ¡ 7 }|d!d% |d !|(¡| |#ƒ¡ 7 }�q–n\d| jk�r„| jd }#t(j) )|#¡}$| j* +|$|j¡�shd }%t	|%ƒ‚d& || |#ƒ¡}"|d!|" 7 }d})t|jƒD ]P}t|)ƒD ]}*|d!7 }�qž|d' || || d |||| d ¡7 }|)d7 })�q’t|)ƒD ]}*|d!7 }�qì|d( |¡7 }|d) |¡7 }tjdk�r4td*ƒ t|ƒ t,|ƒt-ƒ kt.ƒ f t/|ƒ}+|d k	�rjt0 1|+¡},|,|_2dd+l3m4}- |- 5|+¡}.t 6|.j¡ t |.j¡}/i }0||||g|j | }1|/ 7¡ D ]B\}2}3|2|1k�rºt"|3t8j9ƒ�sÞt:‚|3j; <|3j=|3j>¡}4|4j=|0|2< �qºt ?|.j|0¡ t@|.j A¡ ƒd ‰ t B|jˆ ¡|_t@|j A¡ ƒd }5‡ fd,d-„|D ƒ}tjdk�r’td.|ˆ ƒ td/ƒ t |.j¡ td0ƒ t |j¡ |.j 7¡ D �] \}6}7tC|7jDƒD ]à\}}8t"|8t8jEƒ�r°|8jFj=|k�r°|8j>}9|7j;}:t8 G|:|9¡};|7jDd |… |;_D|7jD|d d … |7_DtH|j A¡ ƒ}<|; $t8 I|<|9¡¡ |j 7¡ D ]\}=}>|>|.j|=< �q:|7|.j|5< |;|.j|6< |D ]}?|.j|?  $t8 I|5|9¡¡ �qh �q–�q°�qœ �q �qœt J|.j¡|._t 6|.j¡ t"|tKjLƒ�sÌt:‚|}@tM|@ƒ}Atjdk�rútd1|Aƒ t |.j¡ t N|.j¡ |- O| j*| jP|.|Ad |-jQi ¡}B|BS )2Nr   r—   z6Cannot use the reserved word 'out' in stencil kernels.Z__sentinel__r4   Úname_var_tabler‘   z__numba_stencil_%s_%sú-rg   rq   r5   r–   z	, {}=NoneÚstandard_indexingzYThe first argument to a stencil kernel must use relative indexing, not standard indexing.z[Standard indexing requested for an array name not present in the stencil kernel definition.zAfter add_indices_to_kernelz!After replace_return_with_setitemzdef {}({}{}):
r˜   z	{}[{}][0]z	{}[{}][1]z&    raise_if_incompatible_array_sizes(z)
Z
full_shapez    {} = {}.shape
c                 S   s@   t  | ¡s4t  | ¡rdS t  | ¡r<| dk r.dS dS nt| ƒS d S )Nznp.nanr   z-np.infznp.inf)ÚnpÚisfiniteÚisnanÚisinfrŽ   )Úcvalr   r   r   Úcval_as_strD  s    


z1StencilFunc._stencil_wrapper.<locals>.cval_as_strz{} = np.empty({}, dtype=np.{})
r¯   z-cval type does not match stencil return type.z    ú:z:-{}z-{}:z{}[{}] = {}
z{}[:] = {}
z.for {} in range(-min(0,{}),{}[{}]-max(0,{})):
z{} = 0
z    return {}
znew stencil func text©Úcompilerc                    s   g | ]}|ˆ  ‘qS r   r   ©rf   Úx©Zstencil_stub_last_labelr   r   rh   ¶  s     z0StencilFunc._stencil_wrapper.<locals>.<listcomp>zret_blocks w/ offsetsz"before replace sentinel stencil_irz#before replace sentinel kernel_copyÚnew_stencil_param_types)Rr§   r9   r   Zremove_argsrS   rp   Zcopy_propagateZget_name_var_tableZapply_copy_propagater   Zget_unused_var_namer   ri   rj   Údtyper6   rk   Úhexr8   r    r(   r&   rŽ   rš   r�   r<   r;   rA   r)   rl   r`   r5   r_   r›   rI   r}   rK   r   Zas_dtyper!   r   Útypeofr=   Zcan_convertrœ   r�   rž   rŸ   r   r¡   r™   rŠ   r³   Úrun_frontendZremove_delsrE   r   rL   rt   rF   rO   rd   rG   Zreplace_var_namesr   ÚkeysZadd_offset_to_labelsÚ	enumeraterH   rR   rn   ZBlockr~   ZJumpZrename_labelsr   ÚTyper|   Zfixup_var_define_in_scopeZ
compile_irr>   ZDEFAULT_FLAGS)Cr   r”   r“   r   r�   r‚   r   r¦   r¥   Z	first_argZin_cpsZout_cpsr¨   Zsentinel_nameZ	the_arrayZstencil_func_namerT   r,   Zindex_var_namerU   Zneighborhood_namer¢   r€   Zkernel_sizerƒ   rV   Z	func_textÚrangesÚloÚhiZother_arrayZ
shape_namer°   Zreturn_type_nameZout_initr¯   Zcval_tyÚmsgr„   Zstart_itemsZ	end_itemsÚoffsetÚjZstencil_funcr™   r³   Z
stencil_irZ	var_tableZnew_var_dictÚreserved_namesrd   ÚvarZnew_varZ	new_labelrW   rX   ÚinstrG   rF   Z
prev_blockZbody_first_labelÚlÚbZ	ret_blockÚarray_typesr·   r•   r   r¶   r   r‘   ¹  s¼    ÿ
û


 ÿþÿÿ

     þ ÿ

 ÿ

ÿ  ÿ

 &



ú


ÿÿÿ
 ÿ
ÿ



ÿ


ùzStencilFunc._stencil_wrapperc                 O   s   | j d k	r:t| j ƒ|d jkr:td t| j ƒ|d j¡ƒ‚d|krž|d }|j}t |¡}tj	 
||jt |¡¡}tdd„ |D ƒƒ}tdd„ |D ƒ|g ƒ}nd }tdd„ |D ƒƒ}|}tjdkrÐtd	|||ƒ |  |¡\}	}
}| j|d |	|
|f|žŽ }|d k�r|j|Ž S |j||f Ž S d S )
Nr   zD{} dimensional neighborhood specified for {} dimensional input arrayr—   c                 S   s   g | ]}t j |¡‘qS r   ©r   rº   r´   r   r   r   rh     s     z(StencilFunc.__call__.<locals>.<listcomp>c                 S   s   g | ]}t j |¡‘qS r   rË   r´   r   r   r   rh     s     c                 S   s   g | ]}t j |¡‘qS r   rË   r´   r   r   r   rh     s     r4   r    )r5   r)   r&   r'   rš   r¸   r   Z
from_dtyper   rˆ   r‰   Z
map_layoutr{   r   ri   rj   r†   r‘   Úentry_point)r   r   Úkwargsr”   ZrdtypeZrttypeZresult_typerÊ   Zarray_types_fullrŒ   r�   r‚   r•   r   r   r   r       s@    
ÿ þ
ÿÿ
ÿÿ

zStencilFunc.__call__N)r!   r"   r#   r$   r7   r   r_   r`   r†   r@   r   r�   r§   r‘   r    r   r   r   r   r3   A   s   * I
(  Ir3   Úconstantc                 K   sX   t | tƒsd}| }n| }d }|D ]}|dkr td| ƒ‚q t||ƒ}|d k	rT||ƒS |S )NrÎ   )r¯   rª   r5   zUnknown stencil option )rI   rŽ   r'   Ú_stencil)Zfunc_or_moder;   r:   ÚfuncÚoptionÚwrapperr   r   r   Ústencil!  s    

rÓ   c                    s&   ˆ dkrt dˆ  ƒ‚‡ ‡fdd„}|S )NrÎ   zUnsupported mode style c                    s"   ddl m} | | ¡}t|ˆ ˆƒS )Nr   r²   )rŠ   r³   r»   r3   )rÐ   r³   r9   ©r:   r;   r   r   Ú	decorated7  s    
z_stencil.<locals>.decorated)r'   )r:   r;   rÕ   r   rÔ   r   rÏ   3  s    rÏ   c                 C   s   t  t  tjj¡d¡S )z lowering for dummy stencil callsr   )ÚlirÚConstantZIntTyper   ry   Zbitwidth)r   r   r   r   r   r   r   Ústencil_dummy_lower>  s    rØ   )rÎ   )&r£   Únumpyr«   Zllvmliter   rÖ   rŠ   r   r   r   r   r   r   Znumba.core.typing.templatesr	   r
   r   r   Znumba.core.imputilsr   Znumba.core.extendingr   Znumba.core.errorsr   Znumba.misc.specialr   rv   rz   Znumba.npr   Úobjectr   r-   r2   r3   rÓ   rÏ   rØ   r   r   r   r   Ú<module>   s2   $
     e
