U
    Kc2                     @   s>  d dl Z d dlmZ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mZ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df e jeeeed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!ddeee"dddZ#dde$e"dddZ%dd Z&eeddd Z'dS )!    N)Number
NumberType
TensorLikeTensorLikeTypeELEMENTWISE_TYPE_PROMOTION_KIND)tree_flattentree_unflatten)CallableSequenceUnionTuple
NamedTuple)wrapsreduce)chain)adtypereturnc                    s   dd l m} t| tr0| j kr,||  S | S t| trHt | S t| t	rht
 fdd| D S | d krtd S tdt| d S )Nr   c                 3   s   | ]}t | V  qd S N_maybe_convert_to_dtype.0xr    @/tmp/pip-unpacked-wheel-gikjz4vx/torch/_prims_common/wrappers.py	<genexpr>!   s     z*_maybe_convert_to_dtype.<locals>.<genexpr>z7Received type {0} that is neither a tensor or a number!)Ztorch._primsZ_prims
isinstancer   r   Zconvert_element_typer   utilsZdtype_to_type_ctorr
   tuple
ValueErrorformattype)r   r   Zprimsr   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*   9   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__U   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
rt|S t	|trtfdd|D S tdt| d S )	Nc                 3   s&   | ]}| j  kr j | V  qd S r   )	argumentskeysr   )boundr   r   r   d   s   zKelementwise_type_promotion_wrapper.__call__.<locals>._fn.<locals>.<genexpr>r   r-   c                    s,   i | ]$}| j  kr|t j | qS r   )r3   r4   r   r   )r5   compute_dtyper   r   
<dictcomp>p   s    zLelementwise_type_promotion_wrapper.__call__.<locals>._fn.<locals>.<dictcomp>c                 3   s   | ]}t | V  qd S r   r   r   )result_dtyper   r   r   |   s     zUnhandled result type: )bindr    r.   r   r   Zelementwise_dtypesr-   r3   updater   r   r   r
   AssertionErrorr#   )argskwargsr,   Zflattened_type_promoting_argsZpromoted_argsresultr2   r/   sig)r5   r6   r8   r   _fna   s(    



z8elementwise_type_promotion_wrapper.__call__.<locals>._fninspect	signaturer   __signature__)r/   r2   rA   r   r?   r   __call__^   s
    
z+elementwise_type_promotion_wrapper.__call__)
__name__
__module____qualname____doc__r   r
   strr0   r	   rF   r   r   r   r   r+   C   s   	r+   outc                 C   sZ   |   dkr| |S |   ttj|dkrVdt| j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numelZresize_r   operatormulr"   rK   shapewarningswarn)rM   rQ   r%   r   r   r   _maybe_resize_out   s    
 	

rT   F)exact_dtype	copy_fromcopy_torU   c                    st    j j kr$d j j }t||rFt jjk fdd n$ttj jjd fdd  S )NzZAttempting to copy from device {0} to device {1}, but cross-device copies are not allowed!c                      s   d j  dS )Nz"Expected out tensor to have dtype z  but got {copy_to.dtype} insteadr   r   )rW   r   r   <lambda>       z _safe_copy_out.<locals>.<lambda>)Z	cast_fromZcast_toc                      s   d j  dj  dS )NzAttempting to cast from z to out tensor with dtype z0, but this can't be cast because it is not safe!r   r   rW   rX   r   r   rY      rZ   )devicer"   RuntimeErrorr   checkr   Zcan_safe_cast_toZcopy_)rW   rX   rU   r%   r   r[   r   _safe_copy_out   s      

r_   )	out_namesrU   c                    s<   t dks t dks tttd fdd}|S )Nr      r1   c              	      s   rt nttdd ttD  }r.t ntdj dd D td t	fdd D t
dd	 fd
d
}tjdtjjd|d}jj|fksttj |f}tj|d|_j|_||jd< |jd< |S )z?
        Adds the out parameter to a Python reference.
        c                 s   s   | ]
}t V  qd S r   r   )r   _r   r   r   r      s     z4out_wrapper.<locals>._out_wrapper.<locals>.<genexpr>Zreturn_types_c                 S   s   g | ]}|t fqS r   rb   )r   or   r   r   
<listcomp>   s     z5out_wrapper.<locals>._out_wrapper.<locals>.<listcomp>)r\   r   c                 3   s   | ]}| j kV  qd S r   )
parameters)r   p)r@   r   r   r      s     NrL   c                    s  r0 d k	r0D ]}t  |}||kr|||< q||ttrHsfttrbttksft d k	rrt tstt j t d n`t tstt	
t tk fddt t D ]"\}}t||j t||d qn r S   S )NrV   c                      s   dt  dt   S )Nzexpected tuple of z elements but got )lenr   rM   r>   r   r   rY      rZ   z@out_wrapper.<locals>._out_wrapper.<locals>._fn.<locals>.<lambda>)getattrr   r   r   rh   r;   rT   rQ   r_   r   r^   	TypeErrorzip)rM   r<   r=   kZout_attrrrd   )rU   factory_kwargsr2   is_factory_fn	is_tensorr`   return_typeri   r   rA      s<    


z.out_wrapper.<locals>._out_wrapper.<locals>._fnrM   )kinddefaultr(   )rf   return_annotationr   )r   r   r    rangerh   r   rG   rC   rD   allr   	ParameterKEYWORD_ONLYru   emptyr;   r   rf   values	SignaturerE   __annotations__)r2   Zout_typerA   Z	out_paramparamsrU   rq   r`   )ro   r2   rp   rr   r@   r   _out_wrapper   s@    
 
 4 

z!out_wrapper.<locals>._out_wrapper)rh   r;   r	   )rU   r`   r   r   r   r   out_wrapper   s    [r   c                    s>   fddG fdddt jj t fdd}|S )Nc                    s"   t j }z | |W S ~X d S r   )torchZ_CZ_AutoDispatchBelowAutograd)r<   r=   g)primr   r   redispatch_prim  s    
z0backwards_not_supported.<locals>.redispatch_primc                       s(   e Zd Ze fddZedd ZdS )z6backwards_not_supported.<locals>.BackwardsNotSupportedc                    s   t ||\}} ||S r   )r   )ctx	args_spec	flat_argsr<   r=   r   r   r   forward  s    z>backwards_not_supported.<locals>.BackwardsNotSupported.forwardc                 W   s   t dd S )Nzbackwards not supported on prim)r]   )r   r<   r   r   r   backward#  s    z?backwards_not_supported.<locals>.BackwardsNotSupported.backwardN)rG   rH   rI   staticmethodr   r   r   r   r   r   BackwardsNotSupported  s   r   c                     sH   t | |f\}}t r:tdd |D r: j|f| S | |S d S )Nc                 s   s    | ]}t |tjr|jV  qd S r   )r   r   TensorZrequires_grad)r   r   r   r   r   r   *  s      zBbackwards_not_supported.<locals>._autograd_impl.<locals>.<genexpr>)r   r   Zis_grad_enabledanyapply)r<   r=   r   r   )r   r   r   r   _autograd_impl'  s    z/backwards_not_supported.<locals>._autograd_impl)r   ZautogradZFunctionr   )r   r   r   )r   r   r   r   backwards_not_supported  s
    
r   r1   c                    s(   t  }t  fdd}||_|S )zQ
    Allows unary operators that accept tensors to work with Python numbers.
    c                     sv   t | dkrlt| d trltt| d }t| }tj| d |d|d<  ||}t|tj	sdt
| S  | |S )Nr   r   )rh   r   r   r   Ztype_to_dtyper#   listr   Ztensorr   r;   item)r<   r=   r   Zargs_r>   r2   r   r   rA   E  s    
z-elementwise_unary_scalar_wrapper.<locals>._fnrB   )r2   r@   rA   r   r   r    elementwise_unary_scalar_wrapper?  s
    
r   )(r   Ztorch._prims_commonr   r   r   r   r   Z_prims_commonr   Ztorch.utils._pytreer   r   typingr	   r
   r   r   r   rC   	functoolsr   r   rO   rR   	itertoolsr   r   r   r#   r&   r*   objectr+   rT   boolr_   rK   r   r   r   r   r   r   r   <module>   s4    
A  b*