U
    d "                     @   s"  d dl Z d dlmZ d dlmZmZmZmZm	Z	 d dlm  m
Z
 d dlmZ 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mZ eeeef e jeeeef ddd	Zeeed
ddZdd ZG dd deZedddZ eedddZ!eedddZ"dd Z#dS )    N)Number
NumberType
TensorLikeTensorLikeTypeELEMENTWISE_TYPE_PROMOTION_KIND)tree_flatten)CallableSequenceUnion)wrapsreduce)chain)adtypereturnc                    sr   t | tr$| j kr t|  S | S t | tr<t | S t | tr\t	 fdd| D S t
dt| d S )Nc                 3   s   | ]}t | V  qd S N)_maybe_convert_to_dtype.0xr    9/tmp/pip-unpacked-wheel-ua33x9lu/torch/_prims/wrappers.py	<genexpr>!   s     z*_maybe_convert_to_dtype.<locals>.<genexpr>z7Received type {0} that is neither a tensor or a number!)
isinstancer   r   primsZconvert_element_typer   utilsZdtype_to_typer	   tuple
ValueErrorformattype)r   r   r   r   r   r      s    



r   )r   typr   c                 C   sR   t | ts dt| }t|tt| |sJd| t| |}t||| S )Nz6Found unknown type {0} when trying to convert scalars!z9Scalar {0} of type {1} cannot be safely cast to type {2}!)r   r   r   r    r   r   Zis_weakly_lesser_type)r   r!   msgr   r   r   _maybe_convert_to_type(   s    
  r#   c                 C   s4   t |dr,|jD ]}t| |dr dS qdS | |kS )N__args__)r!   
annotationTF)hasattrr$   _annotation_has_type)r!   r%   r   r   r   r   r'   5   s    

r'   c                   @   s:   e Zd ZdZddeee dddZeeddd	Z	dS )
"elementwise_type_promotion_wrappera  
    Adds elementwise type promotion to a Python reference implementation.

    Takes two kwargs, type_promoting_args and type_promotion_kind.

    type_promoting_args must be a string Sequence specifiying the argument names of all
    arguments that participate in type promotion (and should be type promoted). If the
    arg specifies a Sequence-type then every element of the Sequence will participate in
    type promotion.

    type_promotion_kind must be one of the kinds specified by ELEMENTWISE_TYPE_PROMOTION_KIND.
    See its documentation for details.

    Other type promotion behavior, like validating the Python type of scalar arguments, must
    be handled separately.
    N)type_promoting_args)type_promotion_kindr)   c                C   s   || _ || _d S r   )type_promoting_arg_namesr*   )selfr*   r)   r   r   r   __init__Q   s    z+elementwise_type_promotion_wrapper.__init__fnr   c                    s,   t  t  fdd}|_|S )Nc                     s   j | | t fddjD }t|d }tj|dji\} fddjD } j| f  j}t	|t
stt||S )Nc                 3   s&   | ]}| j  kr j | V  qd S r   )	argumentskeysr   )boundr   r   r   `   s   zKelementwise_type_promotion_wrapper.__call__.<locals>._fn.<locals>.<genexpr>r   r*   c                    s,   i | ]$}| j  kr|t j | qS r   )r0   r1   r   r   r2   Zcompute_dtyper   r   
<dictcomp>l   s    zLelementwise_type_promotion_wrapper.__call__.<locals>._fn.<locals>.<dictcomp>)bindr   r+   r   r   Zelementwise_dtypesr*   r0   updater   r   AssertionErrorr   )argskwargsr)   Zflattened_type_promoting_argsZresult_dtypeZpromoted_argsresultr/   r,   sigr3   r   _fn]   s"    
z8elementwise_type_promotion_wrapper.__call__.<locals>._fn)inspect	signaturer   __signature__)r,   r/   r=   r   r;   r   __call__Z   s
    
z+elementwise_type_promotion_wrapper.__call__)
__name__
__module____qualname____doc__r   r	   strr-   r   rA   r   r   r   r   r(   ?   s   	r(   outc                 C   s^   |   dkrt| |S |   ttj|dkrZdt| jt|}t	
| t| |S | S )Nr      aY  An output with one or more elements was resized since it had shape {0} which does not match the required output shape {1}. This behavior is deprecated, and in a future PyTorch release outputs will not be resized unless they have zero elements. You can explicitly reuse an out tensor t by resizing it, inplace, to zero elements with t.resize_(0).)Znumelr   resizer   operatormulr   rF   shapewarningswarn)rH   rM   r"   r   r   r   _maybe_resize_out~   s     	
rP   	copy_fromcopy_toc                 C   sZ   | j |j kr$d| j |j }t|tj| j|jdsNd| j|j}t|t|| S )NzZAttempting to copy from device {0} to device {1}, but cross-device copies are not allowed!)Z	cast_fromZcast_tozhAttempting to cast from {0} to out tensor with dtype {1}, but this can't be cast because it is not safe!)Zdevicer   RuntimeErrorr   Zcan_safe_cast_tor   r   rS   )rR   rS   r"   r   r   r   _safe_copy_out   s      rU   r.   c                    st   t  dd fdd
}t }tjdtjjdtd}t|j |f}tj	||j
d|_ j|_t|jd< |S )z
    Adds the out parameter to a Python reference.

    Note that this currently only supports operations that return a single tensor.
    NrG   c                    s<    ||}| d k	r8t | ts tt| |j} t|| dS |S NrQ   )r   r   r7   rP   rM   rU   )rH   r8   r9   r:   r/   r   r   r=      s    
 zout_wrapper.<locals>._fnrH   kinddefaultr%   
parametersreturn_annotation)r   r>   r?   	ParameterKEYWORD_ONLYr   r   r\   values	Signaturer]   r@   __annotations__)r/   r=   r<   Z	out_paramparamsr   rW   r   out_wrapper   s"    	
 
rd   c                     s   t t d fdd}|S )Nr.   c              	      s   t   fdd}t }g }D ] }|tj|tjjd td q(t|j	 |}tj
||jd|_ j|_D ]}t|j|< qx|S )Nc            	         s   i }d }D ]>}| |d ||< |d kr6|| d k	}q||| d k	kstq | |}t|tsdt|rg }tD ]D\}}|| }t|tstt||| j}|t	|| |d qtt|S |S rV   )
popr7   r   r   	enumerater   rP   rM   appendrU   )	r8   r9   Z
out_kwargsZhas_out_kwargsor:   Zfinal_resultirH   )r/   	out_namesr   r   r=      s$    
z*out_wrapper_multi.<locals>.go.<locals>._fnrX   r[   )r   r>   r?   rg   r^   r_   r   r   r\   r`   ra   r]   r@   rb   )r/   r=   r<   Z
out_paramsrh   rc   rj   rW   r   go   s,    
 zout_wrapper_multi.<locals>.go)r   )rj   rl   r   rk   r   out_wrapper_multi   s    ,rm   )$ZtorchZtorch._primsZ_primsr   Ztorch._prims.utilsr   r   r   r   r   r   Ztorch.utils._pytreer   typingr   r	   r
   r>   	functoolsr   r   rK   rN   	itertoolsr   r   r   r    r#   r'   objectr(   rP   rU   rd   rm   r   r   r   r   <module>   s*    
?!