o
    8ήc                     @   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)selfsf r   =/tmp/pip-target-vg8gfxp4/lib/python/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_typecall_internalfndescadd_linking_libslibrary)r   contextbuildersigr   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 ]$}| j|jkrtd|j }tt|D ]}|| || kr*tdqq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   ashapeargargshapeir   r   r   !raise_if_incompatible_array_sizes$   s   
r5   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)	the_sliceaddendr   r   r   slice_addition;   s   r;   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   
cpu_targettyping_context
_typingctxtarget_context
_targetctxrefresh_install_typegetr>   _type_cacher   	_lower_me)r   rB   rC   rD   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rEt	|||}t	||d |}|	t
|||
j| qg }|D ]}t	|||}||g7 }qItd}t	|||}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.
        r=   r   stencil_index)itemsscopelocbody
isinstancer   Returnappendr/   VarSetItemvaluer   mk_unique_varExprbuild_tupleAssign)r   blocks
index_varsout_name
ret_blockslabelblockrR   rS   new_bodystmtrvarivarvar_index_varsone_var	index_vars_index_names_index_var
tuple_callsir   r   r   replace_return_with_setitemZ   s4   


z'StencilFunc.replace_return_with_setitemc           -      C   s  i }g }	t jdkrtd|| t|j |du rd}
nd}
t||kr.tdt||f t|j}t	 }|j
 D ]}|j}|j}g }|jD ]}t|tjrqt|jtjrqt jdkritd|jj|jj |jj||jj< t|tjrt|jtjr|jjdv r|jjj|jv st|tjr|jj|jv rtd	t|tjrt|jtjr|jjd
v r|jjj|jv r|jjj|vr|jjdkr|jj}n|jj}||jjj |
rt|dsJ |j|v r|	||j g7 }	n|j|v r|	||j g7 }	ntd|dkrt||d |}td}t|||}||j }t|t j!j"rt|t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| qJtj/t0j|||}|)t||| |)ttj.|jj|||j| qJg }g }td}t|||} g }!g }"||j }t1|D ]}#td}t|||}|)tt|#||| |!|g7 }!t|||# |}||g7 }td}t|||}|"|g7 }"td}$t||$|}%tj.||!|# |}&|)t|&|%| t|t j2r?||# }'n|dd }'t|'t j!j"rt|td|}t#$t%}t j&'|}|||j< t(d||}|)t||| tj*||%||# gd|}|+| j,|'t j-gi ||< |)t||| qtj/t0j|%||# |}|)t||| qtj3|"|}(|)t|(| | |)ttj.|jj| ||j| qJ|)| qJ||_q<|
rdd t1|D }t|	dkrtd|	D ]})t|)t4st|)t5rUt1t|)D ]=}*|)|* }+t|+tjr*|+j|v r*||+j }+t|+t6rLt7||* d |+||* d< t8||* d |+||* d< qtdt|)},n't|)t6rxt7|d d |)|d d< t8|d d |)|d d< d},ntd|,|krt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].
        r=   add_indices_to_kernelNTFD%d dimensional neighborhood specified for %d dimensional input arrayzremembering in const_dict)setitemstatic_setitemz?Assignments to arrays passed to stencil kernels is not allowed.)getitemstatic_getitemru   namezDstencil kernel index is not constant, 'neighborhood' option requiredr   rP   r;   r   const_indexind_stencil_indexc                 S   s   g | ]}d d gqS )r   r   ).0_r   r   r   
<listcomp>1      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.)9r   DEBUG_ARRAY_OPTprintr   dump_blocksr_   r/   r-   get_tuple_tablesetvaluesrR   rS   rT   rU   r   r^   rZ   Consttargetrw   r\   op	arg_namesrY   indexrk   addhasattrr   rX   r[   r   misc	SliceTypenumbanjitr;   	functions
DispatcherGlobalrW   callget_call_typerH   intpru   binopoperatorr.   
ConstSizedr]   tuplelistintminmax)-r   kernelindex_namesr,   r>   standard_indexedtypemap	calltypes
const_dictkernel_constsneed_to_calc_kerneltuple_tablerelatively_indexedrd   rR   rS   re   rf   stmt_index_varrk   tmpnametmpvarstmt_index_var_typsa_varsa_funcsa_func_typg_saslice_addition_callacc_callr`   sum_resultsrl   rm   const_index_varsind_stencilsdimgetitemname
getitemvargetitemcallone_index_typrn   r   r4   te	index_lenr   r   r   rq      sL  



























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 )Nr=   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   r~   r   r   r   rB   r_   rU   r   npytypesArrayr   
numba.corer   type_inference_stagerH   rJ   r,   layout)r   argtysr   r   r   r   r{   real_retr   r   r   r   R  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.
        StencilFuncTyping_)keygenericN)r?   strrA   r   dict_type_meinsert_user_function)r   	typingctx_ty_clsr   r   r   rL   k  s   zStencilFunc._install_typec           
      C   s0   | j | \}}}}| j|||||g|R  }	|	S r   )rN   _stencil_wrapper)
r   r   kwtysr   sigretr{   resultr   r   new_funcr   r   r   r   u  s   
zStencilFunc.compile_for_argtysc                 C   s:  | j durt| j |d jkrtdt| j |d jf |}d}d}d|v r6||d f7 }|d7 }|d }d|v rE||d f7 }|d7 }|| jv rU| j| \}}}}|S | |\}}	}
t|g|R  }d	d
| j	j
|}t|t v 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   rr    outz
, out=Noner>   z, neighborhood=Nonez*def __numba_dummy_stencil({}{}):
    pass
,__numba_dummy_stencil)pysig)r>   r/   r,   r   rN   r   r
   formatjoinrB   r   execglobalslocalsevalreplacer   pysignaturerJ   insert_func_defnrO   )r   r   r   argtys_extra	sig_extrar   _sigr{   r   r   r   r#   
dummy_text
dummy_funcr   r   r   r   |  s<   

zStencilFunc._type_mec           
      C   s   i }|  }i |_|j D ]2\}}t |j| }g |_|j| jD ]}t |}	|j|	 ||v r:|| ||	< q#||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.
        )copyr_   rQ   deepcopyrT   rW   )
r   r   r   copy_calltypeskernel_copyblock_labelrd   	new_blockrf   scopyr   r   r   copy_ir_with_calltypes  s   
z"StencilFunc.copy_ir_with_calltypesc           B   
      s  |  | j|\}}t|j |jd }	t|j|\}
}t|j}t|j|
||| d|v r5t	dt
d|}tjdkrFtd|| |d }tjdkratd||jt|j| t|j dtt|d	d
| jf }g }t|jD ]}t
dt| |}||g7 }qwt
d|}t
d|}d}|d ur|d|7 }dt| jv r|d|7 }| jdg }|	|v rt	dtt|t|j dkrt	d| |||j| j|||\}}| jd u r|| _tjdkrtd t|j |  |j||}tjdkrtd| t|j d|d!|j|}g }t|jD ]-}t"|| d t#r:|| d }|| d }nd||}d||}|$||f q!t|dkrq|d|	 7 }|D ]}||	krk|d| 7 }q^|d7 }t
d|}|d||	7 }dd } |d u rt%&|jjj'}!d|||!}"d| jv r| jd }#t(j))|#}$| j*+|$|jsd }%t	|%nd}#|d!|" 7 }t|jD ]G}&d"g|j }'d"g|j }(d#| j|& d |'|&< d$| j|& d |(|&< |d!d%|d!|'| |# 7 }|d!d%|d!|(| |# 7 }qn.d| jv r<| jd }#t(j))|#}$| j*+|$|js.d }%t	|%d&|| |#}"|d!|" 7 }d})t|jD ](}t|)D ]}*|d!7 }qI|d'|| || d |||| d 7 }|)d7 })qCt|)D ]}*|d!7 }qp|d(|7 }|d)|7 }tjdkrtd* t| t,|t- v t. f t/|}+|d urt01|+},|,|_2dd+l3m4}- |-5|+}.t6|.j t|.j}/i }0||||g|j | }1|/7 D ]\}2}3|2|1vrt8|2|0|2< qt9|.j|0 t:|.j; d  t<|j |_t:|j; d }4 fd,d-|D }tjdkr3td.|  td/ t|.j td0 t|j |.j7 D ]{\}5}6t=|6j>D ]o\}}7t"|7t?j@r|7jAjB|kr|7jC}8|6jD}9t?E|9|8}:|6j>d | |:_>|6j>|d d  |6_>tF|j; };|:$t?G|;|8 |j7 D ]
\}<}=|=|.j|<< q|6|.j|4< |:|.j|5< |D ]}>|.j|> $t?G|4|8 q nqAq8 tH|.j|._t6|.j t"|tIjJsJ |}?tK|?}@tjdkrtd1|@ t|.j tL|.j |-M| j*| jN|.|@d |-jOi }A|AS )2Nr   r   z6Cannot use the reserved word 'out' in stencil kernels.__sentinel__r=   name_var_tabler   z__numba_stencil_%s_%s-r{   r   r>   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)

full_shapez    {} = {}.shape
c                 S   s>   t | st | rdS t | r| dk rdS dS d S t| S )Nznp.nanr   z-np.infznp.inf)npisfiniteisnanisinfr   )cvalr   r   r   cval_as_strJ  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   rz   xstencil_stub_last_labelr   r   r|     r}   z0StencilFunc._stencil_wrapper.<locals>.<listcomp>zret_blocks w/ offsetsz"before replace sentinel stencil_irz#before replace sentinel kernel_copynew_stencil_param_types)Pr   rB   r   remove_argsr_   r   copy_propagateget_name_var_tableapply_copy_propagater   get_unused_var_namer   r~   r   dtyper?   r   hexrA   r   r.   r,   r   r   r   rE   rD   rM   r/   r   rq   r>   rp   r   rU   r   rW   r   as_dtyper'   r   typeofrH   can_convertr   r   r   r   r   r   r   r   r   run_frontendremove_delsrQ   r[   replace_var_namesr   keysadd_offset_to_labels	enumeraterT   r   r^   r   rw   rS   rR   Blockr   Jumprename_labelsr   Typer   fixup_var_define_in_scope
compile_irrJ   DEFAULT_FLAGS)Br   r   r   r   r   r   r   r   r   	first_argin_cpsout_cpsr   sentinel_name	the_arraystencil_func_namer`   r4   index_var_namera   neighborhood_namer   r   kernel_sizer   rb   	func_textrangeslohiother_array
shape_namer   return_type_nameout_initr   cval_tymsgr   start_items	end_itemsoffsetjstencil_funcr   r   
stencil_ir	var_tablenew_var_dictreserved_namesrw   var	new_labelrc   rd   instrS   rR   
prev_blockbody_first_labellb	ret_blockarray_typesr   r   r   r   r   r     s  











 $













zStencilFunc._stencil_wrapperc                 O   s  | j d urt| j |d jkrtdt| j |d jd|v rO|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rhtd	||| | |\}	}
}| j|d |	|
|g|R  }|d u r|j| S |j||f  S )
Nr   zD{} dimensional neighborhood specified for {} dimensional input arrayr   c                 S      g | ]}t j|qS r   r   r  r   r   r   r   r|         z(StencilFunc.__call__.<locals>.<listcomp>c                 S   r<  r   r=  r   r   r   r   r|     r>  c                 S   r<  r   r=  r   r   r   r   r|     r>  r=   r&   )r>   r/   r,   r-   r   r  r   
from_dtyper   r   r   
map_layoutr   r   r~   r   r   r   entry_point)r   r   kwargsr   rdtyperttyperesult_typer;  array_types_fullr   r   r   r   r   r   r   r&     sB   



zStencilFunc.__call__N)r'   r(   r)   r*   r@   r   rp   rq   r   rL   r   r   r   r   r&   r   r   r   r   r<   A   s     + N
(  Gr<   constantc                 K   sX   t | ts
d}| }n| }d }|D ]}|dvrtd| qt||}|d ur*||S |S )NrG  )r   r   r>   zUnknown stencil option )rU   r   r-   _stencil)func_or_moderD   rC   funcoptionwrapperr   r   r   stencil%  s   

rM  c                    s&    dkr
t d   fdd}|S )NrG  zUnsupported mode style c                    s"   ddl m} || }t| S )Nr   r   )r   r   r
  r<   )rJ  r   rB   rC   rD   r   r   	decorated;  s   
z_stencil.<locals>.decorated)r-   )rC   rD   rO  r   rN  r   rH  7  s   rH  c                 C   s   t t tjjdS )z lowering for dummy stencil callsr   )lirConstantIntTyper   r   bitwidth)r!   r"   r#   r   r   r   r   stencil_dummy_lowerB  s   rT  )rG  )&r   numpyr   llvmliter   rP  r   r   r   r   r   r   r   numba.core.typing.templatesr	   r
   r   r   numba.core.imputilsr   numba.core.extendingr   numba.core.errorsr   numba.misc.specialr   r   r   numba.npr   objectr   r5   r;   r<   rM  rH  rT  r   r   r   r   <module>   s4   $
     
i