B
     \le                 @   s   d dl mZmZmZ d dlZd dlmZmZm	Z	m
Z
 d dlmZmZmZ d dlmZ ddlmZm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 )'    )print_functiondivisionabsolute_importN)TypeBuilderICMP_EQConstant)typescgutilscompiler)global_compiler_lock   )make_library_cache	NullCachec          
   C   s   |  }|j |||	j|	j|\}}|j|jddT\}}| || W d Q R X |( |
 }|j ||
| |
| W d Q R X W d Q R X x2t	||D ]$\}}|
||||j| qW |
||||j| |jS )NT)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pyapienvelemsstatusretvalZif_okZif_errorgiloffary r0   6lib/python3.7/site-packages/numba/npyufunc/wrappers.py_build_ufunc_loop_body   s     
 r2   c          	   C   s   |  }t jgt|	j }|jdd8 |j||t j||\}}x|D ]}|| qFW W d Q R X || x2t||D ]$\}}|	|
|||j| qvW |	|
|||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,   elemr.   r/   r0   r0   r1   _build_ufunc_loop_body_objmode'   s    

 r7   c
                s@    fdd}
fdd}t |
|| | |||	dS )Nc                 s   fddt  D } | S )Nc                s    g | ]\}}|  |qS r0   )load_directr   ).0r.   r/   )r"   r0   r1   
<listcomp>J   s   z6build_slow_loop_body.<locals>.load.<locals>.<listcomp>)r   )r*   )r#   r"   r%   r0   r1   r   I   s    
z"build_slow_loop_body.<locals>.loadc                s    |   d S )N)store_directr   )r,   )r"   r$   r&   r0   r1   r   N   s    z#build_slow_loop_body.<locals>.store)r)   )r2   )r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r   r   r0   )r#   r"   r%   r$   r&   r1   build_slow_loop_bodyG   s
    
r<   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 r0   )r8   r   )r9   r.   r/   )r"   r0   r1   r:   ]   s   z5build_obj_loop_body.<locals>.load.<locals>.<listcomp>c                s   g | ]\}} || qS r0   )from_native_value)r9   vt)env_managerr(   r0   r1   r:   `   s   )r   r   )r*   )r#   r"   r@   r%   r(   r'   r0   r1   r   [   s
    
z!build_obj_loop_body.<locals>.loadc          	      sd   t  | } j|dd@ j| }|jd ks8t|j 	 
|  W d Q R X d S )NT)r   )r
   Zis_not_nullif_thenZto_native_valuer   ZcleanupAssertionErrorr;   valuer   r5   )r,   r   Znative)r"   r$   r(   r'   r&   r0   r1   r   d   s    z"build_obj_loop_body.<locals>.store)Zget_env_bodyZget_env_managerr7   )r    r!   r"   r#   r$   r%   r&   r'   r(   envptrr)   Zenv_bodyr   r   r0   )r#   r"   r@   r%   r$   r(   r'   r&   r1   build_obj_loop_bodyV   s    	rE   c                s<    fdd}fdd}t ||| || ||||	|
dS )Nc                 s   fdd D } | S )Nc                s   g | ]}|  qS r0   )load_aligned)r9   r/   )indr0   r1   r:   y   s   z6build_fast_loop_body.<locals>.load.<locals>.<listcomp>r0   )r*   )r#   rG   r0   r1   r   x   s    
z"build_fast_loop_body.<locals>.loadc                s    |   d S )N)store_aligned)r,   )rG   r$   r0   r1   r   }   s    z#build_fast_loop_body.<locals>.store)r)   )r2   )r    r!   r"   r#   r$   r%   r&   r'   rG   r(   r)   r   r   r0   )r#   rG   r$   r1   build_fast_loop_bodyv   s
    
rI   c       ,      C   sF  t |tst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}|j||d}|jd ||d|j }|j\}}}}d|_d|_d	|_d
|_t|d}||j}|j}|||j|}|j|dd}g }x0t |jD ]"\}}|!t"|||||| qLW t"||||t||j}g }|#tjd}x0|D ](} t$%||	}!|!|! |&||! qW t$%||	}"|&||" t$j'}#x|D ]}$|(|#|$j)}#qW |*|}%|rn|%+ }&t$j,|||	d" t-|||||||"||%||}'W dQ R X |%.|& |/  n|0|#\}(})|(B t$j,|||	d&}*t1|||||||"||*j2|%|d}+W dQ R X W dQ R X |)> t$j,|||	d" t3|||||||"||%|d
}'W dQ R X W dQ R X W dQ R X |/  ~|4| |5|  |6|jS )zO
    Wrap the scalar function with a loop that iterates over the arguments
       Zufunc_wrapper )namealwaysinlinez
__ufunc__.r   dimsstepsdataentry	loopcountr   )intpN)r)   )7
isinstancestrrB   r   intpointerget_value_typer	   rS   functionvoidcodegencreate_librarycreate_ir_moduler   get_function_typer3   r4   r   r   add_function
attributesr   rL   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_rangerE   r   ret_voidr   rI   indexr<   add_ir_moduleadd_linking_libraryget_pointer_to_function),libraryr    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)   rD   rR   r#   itypr$   r%   zero_pr&   Zunit_stridedr/   r(   r-   Zslowlooprl   Z
is_stridedloopZfastloopr0   r0   r1   build_ufunc_wrapper   s    











(

r   c               @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )rg   c             C   s   || _ || _|| _| j tj|}| j|||g}||}	| j	||	
 | _| j |	}
| j tj|
| _| j||g}| j|| _|t| j| j| _|| _d S )N)r    r"   fe_typerh   r	   rS   r   gepget_data_typebitcast
as_pointerdataptrget_abi_sizeofZabisizer   Zicmpr   rl   )selfr    r"   r   rO   r   r   offsetZoffseted_argsZ	data_typeZsizeofZoffseted_stepr0   r0   r1   __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ptrr0   r0   r1   r8      s    zUArrayArg.load_directc             C   s&   | j | j|g}| j| j | j|S )N)r"   r   r   r    r   r   )r   rG   r   r0   r0   r1   rF     s    zUArrayArg.load_alignedc             C   s,   t | j| j|}| j| j| j|| d S )N)r
   r   r"   r   r    
pack_valuer   )r   rC   r   r   r0   r0   r1   r;     s    zUArrayArg.store_directc             C   s,   | j | j|g}| j| j | j|| d S )N)r"   r   r   r    r   r   )r   rC   rG   r   r0   r0   r1   rH     s    zUArrayArg.store_alignedN)__name__
__module____qualname__r   r8   rF   r;   rH   r0   r0   r0   r1   rg      s
   rg   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edd Zdd Zdd Zdd ZdS )_GufuncWrapperc             C   sD   || _ || _|| _|| _| jjtjk| _|r8t	| j dnt
 | _d S )N)py_func)r   rv   sinsoutr'   r   r	   r3   Zis_objectmodeGufWrapperCacher   cache)r   r   rv   r   r   r   r0   r0   r1   r     s    z_GufuncWrapper.__init__c             C   s   | j jS )N)rv   rt   )r   r0   r0   r1   rt   $  s    z_GufuncWrapper.libraryc             C   s   | j jS )N)rv   target_context)r   r0   r0   r1   r    (  s    z_GufuncWrapper.contextc             C   s   | j jS )N)r    r   )r   r0   r0   r1   r   ,  s    z_GufuncWrapper.call_convc             C   s   | j jS )N)rv   r'   )r   r0   r0   r1   r'   0  s    z_GufuncWrapper.signaturec             C   s   | j jS )N)rv   rb   )r   r0   r0   r1   rb   4  s    z_GufuncWrapper.fndescc             C   s   | j jS )N)rv   rc   )r   r0   r0   r1   r)   8  s    z_GufuncWrapper.envc       %         s  t d}t |}t |}| jtj}t |}t t  ||||g}|	d}	| j
| jj| jj}
| jj}|	j|
|d}|jd |	||}|j\}}}}d|_d|_d|_d|_t|d	}|j|d
d}| j|}t }x0| j| jfD ] }x|D ]}|t|O }qW qW i }x6| jD ],}x$|D ]}||kr8t|||< q8W q.W i }x>| D ]2\}}|||| jtj|d g||< qlW g }t| jt| j }x\t t!| j"j| j| j D ]>\}\}}t#| j||||||||	} |t|7 }|$|  qW |d}!| %|| t&j'|||d:  fdd|D }"| (||||"\}#}$t&)||$|! W dQ R X |*|! |+|! | ,|| |-  |.|	 |/| j0 dS )z
        The LLVM IRBuilder code to create the gufunc wrapper.
        The *library* arg is the CodeLibrary for which the wrapper should
        be added to.  The *name* arg is the name of the wrapper function being
        created.
        rJ   Z_gufunc_wrapper)rL   rM   r   rN   rO   rP   rQ   rR      z.return)rS   c                s   g | ]}|  jqS r0   )get_array_at_offsetrp   )r9   a)r   r0   r1   r:     s    z1_GufuncWrapper._build_wrapper.<locals>.<listcomp>N)1r   rV   rW   r    rX   r	   rS   rY   rZ   r]   r   r^   rb   ZrestypeZargtypesZllvm_func_namer_   r`   r   r   rL   r   ra   r   rm   setr   r   r4   itemsr   rh   re   r   r'   
GUArrayArgrf   gen_prologuer
   rn   gen_loop_bodycbranch_or_continuebranchposition_at_endgen_epiloguero   rq   rr   rt   )%r   rt   rL   rw   rx   ry   rz   r{   r|   r~   r   ru   r!   r   r   r   r   r   r"   rR   r(   Zunique_symsZgrpsymsZsym_mapssym_dimr   r#   step_offsetr   Zsymr/   Zbbreturnr   	innercallerrorr0   )r   r1   _build_wrapper<  sr    















z_GufuncWrapper._build_wrapperc             C   sz   | j | jj| jj}d| jj }|d krd| j 	t
| }|  | || | j | jj| ||}|| j|fS )Nz__gufunc__.)r   Zload_overloadrv   r'   r   rb   Zmangled_namer    r[   r\   rU   Zenable_object_cachingr   Zsave_overloadrs   r)   )r   r}   Zwrapper_namer   r0   r0   r1   build  s    
z_GufuncWrapper.buildc          	   C   sl   | j ||| jj| jj|\}}|j|jdd* | }| jj 	||| |
| W d Q R X |j|jfS )NF)r   )r   r   r'   r   r   rA   is_errorr   r    r   r   r   )r   r"   r(   r!   r   r+   r,   r-   r0   r0   r1   r     s    
z_GufuncWrapper.gen_loop_bodyc             C   s   d S )Nr0   )r   r"   r(   r0   r0   r1   r     s    z_GufuncWrapper.gen_prologuec             C   s   d S )Nr0   )r   r"   r(   r0   r0   r1   r     s    z_GufuncWrapper.gen_epilogueN)r   r   r   r   propertyrt   r    r   r'   rb   r)   r   r   r   r   r   r   r0   r0   r0   r1   r     s   	W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 )N)_prepare_call_to_object_moder    r'   )r   r"   r(   r!   r   r   r   r0   r0   r1   r     s
    
z"_GufuncObjectWrapper.gen_loop_bodyc             C   s   |  | _d S )N)r   r-   )r   r"   r(   r0   r0   r1   r     s    z!_GufuncObjectWrapper.gen_prologuec             C   s   | | j d S )N)r   r-   )r   r"   r(   r0   r0   r1   r     s    z!_GufuncObjectWrapper.gen_epilogueN)r   r   r   r   r   r   r0   r0   r0   r1   r     s   r   c             C   s.   |j }|jtjkrtnt}|| |||| S )N)r'   r   r	   r3   r   r   r   )r   rv   r   r   r   r'   Zwrapclsr0   r0   r1   build_gufunc_wrapper  s    r   c       &   
   C   sn  |j }|d}| tj}| tj}	t|	}
| tj}| tj	}t
|||
|
|||g}|j|dd}tj|tddd}|tj| g }g }xDt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&||!| qW tj	gt'| }"| j()||tj	|"|\}#}$||#j*| |+|$ |,| |-| x|D ]}|+|.| q@W |#j/}%|%|.|fS )Nzufunc.core.returnZnumba_ndarray_new)rL   r   r   T)zfill)rC   r   shapestrides)0rd   ra   rX   r	   Zint32rS   r   rW   Zvoidptrr3   rY   Zget_or_insert_functionr
   ri   rV   r   rj   re   r   r   rf   rT   Array
make_arrayr   ndimr   Z_get_ptr_by_namer   rP   npdtyperU   ZnumitemsizeZcallr=   Zis_nullr   r4   r   r   r   r5   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ndrN   r   rP   r   Ztype_numr   objZobj_is_nullZ
object_sigr+   r,   r   r0   r0   r1   r     sb    




"








r   c               @   s   e Zd Zdd Zdd ZdS )r   c
                sZ  || _ || _|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 }xDt|D ]8}|j||tj|| gd
d}||}|| qW |rtnt}||j|||||d| _n(|rHtd||d t||d| _d S )Nzdata.ptr)rL   rP   zcore.step.ptrr   r   z.type and shape signature mismatch for arg #{0}c                s   g | ]} | qS r0   r0   )r9   r   )r   r0   r1   r:   O  s    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"   rh   r	   rS   r   r   rP   rT   r   r4   r   	TypeErrorformatrangerf   _ArrayAsScalarArgLoader_ArrayArgLoaderr   _loader_ScalarArgLoader)r   r    r"   r   rO   r   r   r   r   r   r   rP   Zcore_step_ptrr   r   r   r   r   jZstepptrr   Zldclsr0   )r   r1   r   0  sJ    



zGUArrayArg.__init__c             C   s   | j j| j| j| j|dS )N)r    r"   rP   rG   )r   r   r    r"   rP   )r   rG   r0   r0   r1   r   k  s    zGUArrayArg.get_array_at_offsetN)r   r   r   r   r   r0   r0   r0   r1   r   /  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 )N)r   r   )r   r   r   r0   r0   r1   r   x  s    z_ScalarArgLoader.__init__c             C   s:   | |||| jg}|||| j }||S )N)r   mulr   r   r   r   r   r   )r   r    r"   rP   rG   Zdptrr0   r0   r1   r   |  s    z_ScalarArgLoader.loadN)r   r   r   __doc__r   r   r0   r0   r0   r1   r   p  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 )N)r   r   r   r   r   r   )r   r   r   r   r   r   r   r0   r0   r1   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)rP   r   r   r   Zmeminfo)r	   r   r   r   r   r
   r   r   r   _shape_and_stridesr   r   Zpopulate_arrayr   rP   typerh   rS   Z	_getvalue)r   r    r"   rP   rG   Zarytypr   r   Zoffseted_datar   r   r   r0   r0   r1   r     s$    

z_ArrayArgLoader.loadc             C   s$   t || j}t || j}||fS )N)r
   
pack_arrayr   r   )r   r    r"   r   r   r0   r0   r1   r     s    z"_ArrayArgLoader._shape_and_stridesN)r   r   r   r   r   r   r   r0   r0   r0   r1   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   )rh   r	   rS   r
   r   )r   r    r"   Zoner   r   r   r0   r0   r1   r     s
    z*_ArrayAsScalarArgLoader._shape_and_stridesN)r   r   r   r   r   r0   r0   r0   r1   r     s   r   )%Z
__future__r   r   r   Znumpyr   Zllvmlite.llvmpy.corer   r   r   r   Znumbar	   r
   r   Znumba.compiler_lockr   Zcachingr   r   r2   r7   r<   rE   rI   r   objectrg   r   r   r   r   r   r   r   r   r   r0   r0   r0   r1   <module>   s,     j( ^A+