a
    .;b j                     @   s.  d dl mZ d dlZd dlmZmZmZmZ d dl	m
Z
 d dlmZmZ d dlmZ d dlmZmZ edg d	Zd
d Zdd Zdd Zdd Zdd Zdd ZG dd deZedZG dd deZG dd deZdd Zdd  Z G d!d" d"eZ!G d#d$ d$eZ"G d%d& d&eZ#G d'd( d(e#Z$dS ))    )
namedtupleN)TypeBuilderICMP_EQConstant)ir)typescgutils)global_compiler_lock)make_library_cache	NullCache_wrapper_infolibraryenvnamec              	   C   s  |  }|j |||	j|	j|\}}|j|jdd\}}| || W d    n1 sZ0    Y  |2 |
 }|j ||
| |
| W d    n1 s0    Y  W d    n1 s0    Y  t	||D ]$\}}|
||||j| q|
||||j| |jS NTZlikely)	call_convcall_functionreturn_typeargsif_elseis_ok
gil_ensureraise_errorgil_releasezipstoreaddloadstepcode)r    r   contextfuncbuilderarraysoutoffsetsstore_offset	signaturepyapir   elemsstatusretvalZif_okZif_errorgiloffary r2   6lib/python3.9/site-packages/numba/np/ufunc/wrappers.py_build_ufunc_loop_body   s$    
&Fr4   c                 C   s   |  }t jgt|	j }|jdd> |j||t j||\}}|D ]}|| qDW d    n1 sh0    Y  || t||D ]$\}}|	|
|||j| q|	|
|||j| |jS )NT)Zkeep_new)r   pyobjectlenr   Zerr_pushr   r   decrefr   r   r   r    r!   r"   )r    r   r#   r$   r%   r&   r'   r(   r)   r*   r   r+   r,   Z_objargsr-   r.   elemr0   r1   r2   r2   r3   _build_ufunc_loop_body_objmode,   s     
*r9   c
                    s@    fdd}
fdd}t |
|| | |||	dS )Nc                     s   fddt  D } | S )Nc                    s    g | ]\}}|  |qS r2   load_directr    .0r0   r1   r%   r2   r3   
<listcomp>O   s   z6build_slow_loop_body.<locals>.load.<locals>.<listcomp>)r   r,   )r&   r%   r(   r2   r3   r    N   s    
z"build_slow_loop_body.<locals>.loadc                    s    |   d S N)store_directr    r.   )r%   r'   r)   r2   r3   r   S   s    z#build_slow_loop_body.<locals>.storer   r4   )r#   r$   r%   r&   r'   r(   r)   r*   r+   r   r    r   r2   )r&   r%   r(   r'   r)   r3   build_slow_loop_bodyL   s    
rF   c                    sb   |  |	}|
||	 fdd}fdd}t||| | |	S )Nc                     s8   fddt  D } fddt | jD } | S )Nc                    s    g | ]\}}|  |qS r2   r:   r<   r>   r2   r3   r?   b   s   z5build_obj_loop_body.<locals>.load.<locals>.<listcomp>c                    s   g | ]\}} || qS r2   )from_native_value)r=   vt)env_managerr+   r2   r3   r?   e   s   )r   r   r@   )r&   r%   rJ   r(   r+   r*   r2   r3   r    `   s    

z!build_obj_loop_body.<locals>.loadc                    sx   t  | } j|ddJ j| }|jd u s8J |j  	|  W d    n1 sj0    Y  d S r   )
r	   Zis_not_nullif_thenZto_native_valuer   ZcleanuprB   valuer    r7   )r.   r   Znative)r%   r'   r+   r*   r)   r2   r3   r   i   s    z"build_obj_loop_body.<locals>.store)Zget_env_bodyZget_env_managerr9   )r#   r$   r%   r&   r'   r(   r)   r*   r+   envptrr   Zenv_bodyr    r   r2   )r&   r%   rJ   r(   r'   r+   r*   r)   r3   build_obj_loop_body[   s    	rN   c                    s<    fdd}fdd}t ||| || ||||	|
dS )Nc                     s   fdd D } | S )Nc                    s   g | ]}|  qS r2   )load_aligned)r=   r1   )indr2   r3   r?   ~   s   z6build_fast_loop_body.<locals>.load.<locals>.<listcomp>r2   r@   )r&   rP   r2   r3   r    }   s    
z"build_fast_loop_body.<locals>.loadc                    s    |   d S rA   )store_alignedrC   )rP   r'   r2   r3   r      s    z#build_fast_loop_body.<locals>.storerD   rE   )r#   r$   r%   r&   r'   r(   r)   r*   rP   r+   r   r    r   r2   )r&   rP   r'   r3   build_fast_loop_body{   s    
rR   c           *      C   s  t |tsJ td}t|}t|}|tj}	t|	}
tt	 ||
|
|g}|
 d}|d}|r|jtjtjgt|j }n|j|j|j}tj|||d}|jd t||d|j }|j\}}}}d|_d|_d	|_d
|_t|d}||j}|j}|||j|}|j|dd}g }t |jD ]"\}}|!t"|||||| qNt"||||t||j}g }|#tjd}|D ](} t$%||	}!|!|! |&||! qt$%||	}"|&||" t$j'}#|D ]}$|(|#|$j)}#q|*|}%|r~|%+ }&t$j,|||	d, t-|||||||"||%|| W d   n1 s^0    Y  |%.|& |/  n&|0|# \}'}(|'b t$j,|||	d0})t1|||||||"||)j2|%|d W d   n1 s0    Y  W d   n1 s0    Y  |(^ t$j,|||	d, t3|||||||"||%|d
 W d   n1 sR0    Y  W d   n1 sr0    Y  W d   n1 s0    Y  |/  ~|4| |5|  t6|||jdS )z
    Wrap the scalar function with a loop that iterates over the arguments

    Returns
    -------
    (library, env, name)
       Zufunc_wrapper r   alwaysinlinez
__ufunc__.r   dimsstepsdataentry	loopcountr   intpNrD   r   )7
isinstancestrr   intpointerget_value_typer   r]   functionvoidcodegencreate_librarycreate_ir_moduler   get_function_typer5   r6   r   r   r   Function
attributesr   r   r   append_basic_blockZget_env_namefndescenvironmentr    Zdeclare_env_globalmodule	enumerateappend	UArrayArgget_constantr	   alloca_oncer   true_bitand_is_unit_stridedget_python_apir   	for_rangerN   r   ret_voidr   rR   indexrF   add_ir_moduleadd_linking_libraryr   )*r   r#   fnamer*   Zobjmodecresbyte_t
byte_ptr_tbyte_ptr_ptr_tintp_t
intp_ptr_tfnty
wrapperlibwrapper_module	func_typer$   wrapperarg_argsarg_dims	arg_stepsarg_datar%   Zenvnamer   rM   r[   r&   itypr'   r(   zero_pr)   Zunit_stridedr1   r+   r/   rv   Z
is_stridedloopr2   r2   r3   build_ufunc_wrapper   s    







$

Ff

r   c                   @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )rq   c                 C   s   || _ || _|| _| j tj|}| j|||g}||}	| j	||	
 | _| j |	}
| j tj|
| _| j||g}| j|| _|t| j| j| _|| _d S rA   )r#   r%   fe_typerr   r   r]   r    gepget_data_typebitcast
as_pointerdataptrget_abi_sizeofZabisizer!   Zicmpr   rv   )selfr#   r%   r   rX   r   r   offsetZoffseted_argsZ	data_typeZsizeofZoffseted_stepr2   r2   r3   __init__   s    
zUArrayArg.__init__c                 C   s&   t | j| j|}| j| j| j|S )zm
        Generic load from the given *byteoffset*.  load_aligned() is
        preferred if possible.
        )r	   pointer_addr%   r   r#   unpack_valuer   )r   
byteoffsetptrr2   r2   r3   r;   
  s    zUArrayArg.load_directc                 C   s&   | j | j|g}| j| j | j|S rA   )r%   r   r   r#   r   r   )r   rP   r   r2   r2   r3   rO     s    zUArrayArg.load_alignedc                 C   s,   t | j| j|}| j| j| j|| d S rA   )r	   r   r%   r   r#   
pack_valuer   )r   rL   r   r   r2   r2   r3   rB     s    zUArrayArg.store_directc                 C   s,   | j | j|g}| j| j | j|| d S rA   )r%   r   r   r#   r   r   )r   rL   rP   r   r2   r2   r3   rQ     s    zUArrayArg.store_alignedN)__name__
__module____qualname__r   r;   rO   rB   rQ   r2   r2   r2   r3   rq      s
   rq   Zgufc                   @   s   e Zd Zdd Zedd Zedd Zedd Zed	d
 Zedd Z	edd Z
dd Zdd Zdd Zedd Zdd Zdd Zdd ZdS )_GufuncWrapperc                 C   sN   || _ || _|| _|| _| jjtjk| _|r8t	| j dnt
 | _t|| _dS )a,  
        The *is_parfors* argument is a boolean that indicates if the GUfunc
        being built is to be used as a ParFors kernel. If True, it disables
        the caching on the wrapper as a separate unit because it will be linked
        into the caller function and cached along with it.
        )py_funcN)r   r~   sinsoutr*   r   r   r5   Zis_objectmodeGufWrapperCacher   cachebool
is_parfors)r   r   r~   r   r   r   r   r2   r2   r3   r   %  s    z_GufuncWrapper.__init__c                 C   s   | j jS rA   )r~   r   r   r2   r2   r3   r   5  s    z_GufuncWrapper.libraryc                 C   s   | j jS rA   )r~   target_contextr   r2   r2   r3   r#   9  s    z_GufuncWrapper.contextc                 C   s   | j jS rA   )r#   r   r   r2   r2   r3   r   =  s    z_GufuncWrapper.call_convc                 C   s   | j jS rA   )r~   r*   r   r2   r2   r3   r*   A  s    z_GufuncWrapper.signaturec                 C   s   | j jS rA   )r~   rl   r   r2   r2   r3   rl   E  s    z_GufuncWrapper.fndescc                 C   s   | j jS rA   )r~   rm   r   r2   r2   r3   r   I  s    z_GufuncWrapper.envc                 C   sR   t d}t |}t |}| jtj}t |}t t  ||||g}|S )NrS   )	r   r`   ra   r#   rb   r   r]   rc   rd   )r   r   r   r   r   r   r   r2   r2   r3   _wrapper_function_typeM  s    



z%_GufuncWrapper._wrapper_function_typec           !         s  | j tj}|  }|d}| j| jj	| jj
}| jj}tj|||d}|jd t|||}	d|	_|	j\}
}}}d|
_d|_d|_d|_t|	d	}|j|d
d}| j |}t }| j| jfD ]}|D ]}|t|O }qqi }| jD ]"}|D ]}||vrt|||< qqi }| D ]2\}}|||| j tj|d g||< q$g }t| jt| j }tt| j j| j| j D ]>\}\}}t!| j ||
||||||	}|t|7 }|"| q|d}| #|| t$j%|||dD  fdd|D }| &||||\}} t$'|| | W d   n1 s<0    Y  |(| |)| | *|| |+  |,| |-| j. dS )z
        The LLVM IRBuilder code to create the gufunc wrapper.
        The *library* arg is the CodeLibrary to which the wrapper should
        be added.  The *name* arg is the name of the wrapper function being
        created.
        Z_gufunc_wrapperrU   rV   Zweak_odrr   rW   rX   rY   rZ   r[      z.returnr\   c                    s   g | ]}|  jqS r2   )get_array_at_offsetrz   )r=   ar   r2   r3   r?         z1_GufuncWrapper._build_wrapper.<locals>.<listcomp>N)/r#   rb   r   r]   r   rg   r   rh   rl   ZrestypeargtypesZllvm_func_namer   ri   rj   r   Zlinkager   r   r   rk   r    rw   setr   r   r6   itemsr   rr   ro   r   r*   
GUArrayArgrp   gen_prologuer	   rx   gen_loop_bodycbranch_or_continuebranchposition_at_endgen_epiloguery   r{   r|   r   )!r   r   r   r   r   r   r   r}   r$   r   r   r   r   r   r%   r[   r+   Zunique_symsZgrpsymsZsym_mapssym_dimr   r&   step_offsetr   Zsymr1   Zbbreturnr   	innercallerrorr2   r   r3   _build_wrapperX  st    






.


z_GufuncWrapper._build_wrapperc                 C   s   | j r(| j t| }| || nX| j| jj	| jj
}|d u r| j t| }|  | || | j| jj	| |S rA   )r   r#   re   rf   r_   r   r   Zload_overloadr~   r*   r   Zenable_object_cachingZsave_overloadr   Zwrapper_namer   r2   r2   r3   _compile_wrapper  s    z_GufuncWrapper._compile_wrapperc                 C   s&   d| j j }| |}t|| j|dS )Nz__gufunc__.r   )rl   Zmangled_namer   r   r   r   r2   r2   r3   build  s
    
z_GufuncWrapper.buildc                 C   s   | j ||| jj| jj|\}}|j|jdd4 | }| jj 	||| |
| W d    n1 sj0    Y  |j|jfS )NFr   )r   r   r*   r   r   rK   is_errorr   r#   r   r   r"   )r   r%   r+   r$   r   r-   r.   r/   r2   r2   r3   r     s    (z_GufuncWrapper.gen_loop_bodyc                 C   s   d S rA   r2   r   r%   r+   r2   r2   r3   r     s    z_GufuncWrapper.gen_prologuec                 C   s   d S rA   r2   r   r2   r2   r3   r     s    z_GufuncWrapper.gen_epilogueN)r   r   r   r   propertyr   r#   r   r*   rl   r   r   r   r   r
   r   r   r   r   r2   r2   r2   r3   r   $  s*   





T
r   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )_GufuncObjectWrapperc                 C   s"   t | j|||| j|\}}||fS rA   )_prepare_call_to_object_moder#   r*   )r   r%   r+   r$   r   r   r   r2   r2   r3   r     s    z"_GufuncObjectWrapper.gen_loop_bodyc                 C   s   |  | _d S rA   )r   r/   r   r2   r2   r3   r     s    z!_GufuncObjectWrapper.gen_prologuec                 C   s   | | j d S rA   )r   r/   r   r2   r2   r3   r     s    z!_GufuncObjectWrapper.gen_epilogueN)r   r   r   r   r   r   r2   r2   r2   r3   r     s   r   c                 C   s2   |j }|jtjkrtnt}|| |||||d S )N)r   )r*   r   r   r5   r   r   r   )r   r~   r   r   r   r   r*   Zwrapclsr2   r2   r3   build_gufunc_wrapper  s    
r   c           &   
   C   sd  |j }|d}| tj}| tj}	t|	}
| tj}| tj	}t
|||
|
|||g}t||d}tj|tddd}|tj| g }g }tt||jD ].\}\}}tj||dd}|| t|tjr| |}|| ||d}t|d	}t||j}||d
||g}||d||g}||j|}tt |j}t||j!}t||j"}|#|||||||g} n|$||} || | ||  t%|| }!||!| t&||!| qtj	gt'| }"| j()||tj	|"|\}#}$||#j*| |+|$ |,| |-| |D ]}|+|.| q8|#j/}%|%|.|fS )Nzufunc.core.returnZnumba_ndarray_newr   r   rU   T)zfill)rL   r   shapestrides)0rn   rk   rb   r   Zint32r]   r   ra   Zvoidptrr5   rc   r	   Zget_or_insert_functionrs   r`   r   rt   ro   r   r   rp   r^   Array
make_arrayr   ndimr   Z_get_ptr_by_namer   rY   npdtyper_   ZnumitemsizeZcallrG   Zis_nullr   r6   r   r   r   r7   r   r   r    r"   )&r#   r%   r+   r$   r*   r   modZbb_core_returnZll_intZll_intpZll_intp_ptrZ
ll_voidptrZll_pyobjr   Zfn_array_newZerror_pointerZobject_argsZobject_pointersr   argZargtyZobjptraryclsarrayr   ZndrW   r   rY   r   Ztype_numr   objZobj_is_nullZ
object_sigr-   r.   r   r2   r2   r3   r     sp    










r   c                   @   s   e Zd Zdd Zdd ZdS )r   c
                    sV  || _ || _|tj|}
|j|j||
gdddd}|| _|j||
gdd}||}t|tj	r*| }t
||jkrt
|dkr|jdkrntd|d |j} fdd	|D }g }t|D ]8}|j||tj|| gd
d}||}|| q|rtnt}||j|||||d| _n(|rDtd||d t||d| _d S )Nzdata.ptrrU   rY   zcore.step.ptrr   r   z.type and shape signature mismatch for arg #{0}c                    s   g | ]} | qS r2   r2   )r=   r   r   r2   r3   r?   z  r   z'GUArrayArg.__init__.<locals>.<listcomp>zstep.ptrr   r   	core_step	as_scalarr   r   z2scalar type {0} given for non scalar argument #{1}r   stride)r#   r%   rr   r   r]   r    r   rY   r^   r   r6   r   	TypeErrorformatrangerp   _ArrayAsScalarArgLoader_ArrayArgLoaderr   _loader_ScalarArgLoader)r   r#   r%   r   rX   r   r   r   r   r   r   rY   Zcore_step_ptrr   r   r   r   r   jZstepptrr!   Zldclsr2   r   r3   r   [  sZ    


zGUArrayArg.__init__c                 C   s   | j j| j| j| j|dS )N)r#   r%   rY   rP   )r   r    r#   r%   rY   )r   rP   r2   r2   r3   r     s    zGUArrayArg.get_array_at_offsetN)r   r   r   r   r   r2   r2   r2   r3   r   Z  s   ;r   c                   @   s    e Zd ZdZdd Zdd ZdS )r   z
    Handle GFunc argument loading where a scalar type is used in the core
    function.
    Note: It still has a stride because the input to the gufunc can be an array
          for this argument.
    c                 C   s   || _ || _d S rA   r   )r   r   r   r2   r2   r3   r     s    z_ScalarArgLoader.__init__c                 C   s:   | |||| jg}|||| j }||S rA   )r   mulr   r   r   r   r   r    )r   r#   r%   rY   rP   Zdptrr2   r2   r3   r      s
    z_ScalarArgLoader.loadN)r   r   r   __doc__r   r    r2   r2   r2   r3   r     s   r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r   zD
    Handle GUFunc argument loading where an array is expected.
    c                 C   s(   || _ || _|| _|| _|| _|| _d S rA   r   )r   r   r   r   r   r   r   r2   r2   r3   r     s    z_ArrayArgLoader.__init__c              	   C   s   t j| j| jdd}||}|||}t|||| j|}| 	||\}	}
|
|| j}|j||||jj|	|
|t j|d d | S )NA)r   r   Zlayout)rY   r   r   r   Zmeminfo)r   r   r   r   r   r	   r   r   r   _shape_and_stridesr   r   Zpopulate_arrayr   rY   typerr   r]   Z	_getvalue)r   r#   r%   rY   rP   Zarytypr   r   Zoffseted_datar   r   r   r2   r2   r3   r      s.    

	z_ArrayArgLoader.loadc                 C   s$   t || j}t || j}||fS rA   )r	   
pack_arrayr   r   )r   r#   r%   r   r   r2   r2   r3   r     s    z"_ArrayArgLoader._shape_and_stridesN)r   r   r   r   r   r    r   r2   r2   r2   r3   r     s   r   c                   @   s   e Zd ZdZdd ZdS )r   z
    Handle GUFunc argument loading where the shape signature specifies
    a scalar "()" but a 1D array is used for the type of the core function.
    c                 C   s@   | tjd}| tjd}t||g}t||g}||fS )Nr   r   )rr   r   r]   r	   r   )r   r#   r%   Zoner   r   r   r2   r2   r3   r     s
    z*_ArrayAsScalarArgLoader._shape_and_stridesN)r   r   r   r   r   r2   r2   r2   r3   r     s   r   )%collectionsr   Znumpyr   Zllvmlite.llvmpy.corer   r   r   r   Zllvmliter   Z
numba.corer   r	   Znumba.core.compiler_lockr
   Znumba.core.cachingr   r   r   r4   r9   rF   rN   rR   r   objectrq   r   r   r   r   r   r   r   r   r   r2   r2   r2   r3   <module>   s0     o( <
`A+