U
    <cb                     @   s(  d dl Z d dl mZ d dlZd dl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lm  mZ d dlmZ d dlZdd	 Zd
d Zdd Zdd Zdd Zd/ddZdd Zdd Zdd Zdd Zdd Zd0d d!Z d"d# Z!d$d% Z"d&d' Z#d1d(d)Z$d2ed*d+d,Z%d3ed*d-d.Z&dS )4    N)Tensor)TorchDispatchMode)tree_maptree_flattentree_unflatten)partial)no_dispatchall_same_mode)Callablec                 C   s6   | j }|| }||}||kr"d S td| dd S )Nz.This operator is not Composite Compliant: the zR of the tensor was modified directly without going through the PyTorch dispatcher.)elemRuntimeError)wrapper_tensormetadata_namemetadata_accessorr   Zmetadata_wrapper_tensorZmetadata_elem r   P/tmp/pip-unpacked-wheel-gikjz4vx/torch/testing/_internal/composite_compliance.pycheck_attr_consistency   s    
r   c                 C   sR   t | |sd S tjdd dd tjtjtjd}| D ]\}}t| || q8d S )Nc                 S   s   | j S N)dtypexr   r   r   <lambda>       z,check_metadata_consistency.<locals>.<lambda>c                 S   s   | j S r   )devicer   r   r   r   r       r   )shaper   r   numelstridestorage_offset)
isinstancer   sizer   r   r   itemsr   )r   CCTZthings_to_checkr   r   r   r   r   check_metadata_consistency   s    
r"   c                 C   s   | j jdkS )N>"   vsplit_unsafe_viewviewtensor_splitselectdiagonalunbind	unsqueezetexpandrealhsplitunfoldnarrow_reshape_alias	expand_as	unflattenslice_conjsplitsplit_with_sizes	transposepermuteimagdetachswapaxesmovedimsqueezeview_asaliasview_as_realchunkview_as_complex
as_stridedoverloadpacket__name__funcr   r   r   
is_view_fn(   s    rJ   c                 C   s   | j jdkS )N>   	swapaxes_detach_t_as_strided_squeeze_
transpose_	swapdims_
unsqueeze_rE   rH   r   r   r   is_inplace_view_fnP   s    rS   c                 C   s4   | j j}td|rdS td|r(dS |d dkS )Nz__i.+__Tz__.+__F_)rF   rG   rematch)rI   namer   r   r   
is_inplace^   s    rY   Tc                    s6   G  fdddt j G  fdddt} | fS )Nc                       sL   e Zd ZU ejed< dgZejjZ	e
dd Zdd Zed
 fdd		ZdS )z7generate_cct_and_mode.<locals>.CompositeCompliantTensorr   c              
   _   s   t || k	stdtjj| | |j|j|j|j	|
 | d}|j	rtj|j|
 |j|j|jdd}||  ||_n||_|
 |j
 ksttj||j  tj||j  ||_|S )NzRWrapping a CompositeCompliantTensor in a CompositeCompliantTensor is not supported)r   layoutr   requires_gradstridesr   F)r   r   rZ   r[   )typeAssertionErrortorchr   Z_make_wrapper_subclassr   r   rZ   r   r[   r   r   Zempty_stridedr   Zcopy_r;   r   _CZ	_set_conjZis_conjZ_set_negZis_negmode)clsr   ra   argskwargsrtmpr   r   r   __new__w   s6         z?generate_cct_and_mode.<locals>.CompositeCompliantTensor.__new__c                 S   s   d| j  dS )NzCompositeCompliantTensor())r   selfr   r   r   __repr__   s    z@generate_cct_and_mode.<locals>.CompositeCompliantTensor.__repr__r   Nc              
      sh   t |d t |d  }t fdd|D }t|s>td|d  |||W  5 Q R  S Q R X d S )Nr   c                 3   s   | ]}t | r|jV  qd S r   )r   ra   .0eCompositeCompliantTensorr   r   	<genexpr>   s     
 z]generate_cct_and_mode.<locals>.CompositeCompliantTensor.__torch_dispatch__.<locals>.<genexpr>z*Multiple CompositeCompliantTensorModes NYI)r   tupler	   r   )rb   rI   typesrc   rd   Zall_argsmodesro   r   r   __torch_dispatch__   s    
zJgenerate_cct_and_mode.<locals>.CompositeCompliantTensor.__torch_dispatch__)r   N)rG   
__module____qualname__r_   r   __annotations__	__slots__r`   Z_disabled_torch_function_implZ__torch_function__staticmethodrg   rk   classmethodru   r   ro   r   r   rp   q   s   


$rp   c                       s   e Zd Zd fdd	ZdS )z;generate_cct_and_mode.<locals>.CompositeCompliantTensorModer   Nc              	      s  fdd} fdd}|t jjjjkr2td|jjdkrNt|j dt|r|d }t	|st
fd	d
|dd  D rtd|j dt||}t||}	|||	}
t||
}t|r.r.t R |||}t	|tst	|trt||D ]\}}|| qn
|| W 5 Q R X t  t|rJ||| W 5 Q R X ttd}t|| t|| t|| |S )Nc                    s   t |  r| jS | S r   r   r   rn   ro   r   r   unwrap   s    z^generate_cct_and_mode.<locals>.CompositeCompliantTensorMode.__torch_dispatch__.<locals>.unwrapc                    s   t | tjr | S | S r   r   r_   r   r}   )rp   rj   r   r   wrap   s    z\generate_cct_and_mode.<locals>.CompositeCompliantTensorMode.__torch_dispatch__.<locals>.wrapz.item() is not allowed to be called inside of composite functions in the PyTorch library because not all backends and/or Tensor subclasses (e.g. vmap, ProxyTensor) support them.)set_Zresize_z; is not allowed to be called inside of Composite operators.r   c                    s   g | ]}t | qS r   )r   rm   aro   r   r   
<listcomp>   s     zbgenerate_cct_and_mode.<locals>.CompositeCompliantTensorMode.__torch_dispatch__.<locals>.<listcomp>   z7Not composite compliant: performing in-place operation z where the Tensor being written to is regular Tensor but the other tensors are Tensor Subclasses. Please try to avoid this in-place operation.r!   )r_   opsZatenZ_local_scalar_densedefaultr   rF   rG   rY   r   anyr   rJ   r   rr   listzipr   rS   r   r"   )rj   rI   rs   rc   rd   r~   r   Zmutated_argumentZunwrapped_argsZunwrapped_kwargsZunwrapped_rsrsresultr   bcheckrp   autograd_view_consistencyri   r   ru      sJ    










zNgenerate_cct_and_mode.<locals>.CompositeCompliantTensorMode.__torch_dispatch__)r   N)rG   rv   rw   ru   r   r   r   r   CompositeCompliantTensorMode   s   r   )r_   r   r   )r   r   r   r   r   generate_cct_and_modeg   s    
7Mr   c                 C   sd   t | tst | tsdS t| dkr(dS tdd | D }|rBdS tdd | D }|r`tddS )NFr   c                 S   s   g | ]}t |tjqS r   r   rm   eltr   r   r   r      s     z!is_tensorlist.<locals>.<listcomp>Tc                 S   s   g | ]}t |tjqS r   r   r   r   r   r   r      s     zVThis test assumes that PyTorch APIs cannot take mixed lists of Tensor and other things)r   r   rr   lenallr   )lstZall_tensorsZexists_one_tensorr   r   r   is_tensorlist   s    r   c                 C   s   |r| |S |S r   r   )fnZ
should_mapargr   r   r   	maybe_map  s    r   c                    s>   t | tjr | S t| r2 fdd| D S tdd S )Nc                    s   g | ]} |qS r   r   r   r!   cct_moder   r   r     s     zwrap.<locals>.<listcomp>z*wrap assumes that the input can be wrapped)r   r_   r   r   r   )r   r!   r   r   r   r   r   
  s
    
r   c                 #   sT   dd | D }dd |D }t j| D ](} fddt|| D }||fV  q&d S )Nc                 S   s    g | ]}t |tjpt|qS r   )r   r_   r   r   rm   r   r   r   r   r     s     z-generate_subclass_choices.<locals>.<listcomp>c                 S   s   g | ]}|rd dgnd gqS )FTr   )rm   Zis_tensor_liker   r   r   r      s     c                    s&   g | ]\}}t tt d ||qS )r   )r   r   r   )rm   Zshould_wrap_argr   r   r   r   r   $  s   )	itertoolsproductr   )Z	flat_argsr!   r   Zis_tensor_likesZsubclass_optionswhich_args_are_wrappedr   r   r   r   generate_subclass_choices  s    r   c                 c   s   t |\}}t| t| }t|||D ]b\}}|d t|  }	t|t| d  |}
|d t|  }t|t| d  |}|	|
||fV  q(d S r   )r   r   r   r   r   )rc   rd   r!   r   flat_kwargsspecZflat_args_kwargschoiceZdebug_metadatanew_args
new_kwargsr   which_kwargs_are_wrappedr   r   r   %generate_subclass_choices_args_kwargs,  s    r    c                 C   s   t d| d| d S )Nz8Composite compilance check failed with the above error.
a(  If you are adding an OpInfo of an existing operator, please feel free to skip this test because the problem was pre-existing and file an issue. Otherwise, if you added a new operator, please read through the Composite Compliance section in aten/src/ATen/native/README.md for how to resolve this. )r   )errZadditional_infor   r   r    raise_composite_compliance_error8  s
    

r   c                    s   t  \ }| ||}t|| |D ]v}|\}}}	}
z| ||}W n: tk
rz } zt|d|	 d|
 d W 5 d }~X Y nX  fdd}|t||| q"d S )N- wrapped_args: 
- wrapped_kwargs: 
c                    s   t |  r| jS | S r   r|   r}   r   r   r   r~   j  s    z&check_all_permutations.<locals>.unwrap)r   r   r   r   r   )oprc   rd   assert_equal_fnr   expectedr   r   r   r   r   actualr   r~   r   r   r   check_all_permutationsN  s    

r   c           	   
      s   t  \  fdd}| ||}t||}t||}z | ||}W 5 Q R X W n* tk
r~ } zt| W 5 d }~X Y nX  fdd}|t||| d S )Nc                    s   t | tjr | S | S r   r   r}   r   r   r   r   ~  s    zcheck_with_mode.<locals>.wrapc                    s   t |  r| jS | S r   r|   r}   r   r   r   r~     s    zcheck_with_mode.<locals>.unwrap)r   r   r   r   )	r   rc   rd   r   r   r   r   r   r~   r   r   r   check_with_mode{  s    



r   c                 C   sP   g }t | \} }t |\}}| | } | D ]"}t|tjs:q(|jr(|| q(|S r   )r   r   r_   r   r[   append)rc   rd   leaf_tensorsZ	args_specZkwargs_specr   r   r   r   gather_leaf_tensors  s    r   c                 C   s   |d kr| ||}n|| f||}|d k	r4||}t |\}}dd |D }t|dks^tdd |D }	t||}
t|
dksttjj||
|	dddS )Nc                 S   s   g | ]}|j r|qS r   r[   rm   re   r   r   r   r     s      z*compute_expected_grads.<locals>.<listcomp>r   c                 S   s"   g | ]}t j|j|j|jd qS )r   r   r_   Zonesr   r   r   r   r   r   r   r     s     TZallow_unusedZretain_graph)r   r   r^   r   r_   autogradgrad)r   rc   rd   output_process_fn_gradgradcheck_wrapperresultsflat_resultsrU   flat_diff_resultsgradsr   r   r   r   compute_expected_grads  s     

  r   )r   c                    s  t  \ }t| ||||}t|| |D ]p}|\}	}
}}t|	|
}t|dksTtz8|d krj| |	|
}n|| f|	|
}|d k	r||}W n: tk
r } zt|d| d| d W 5 d }~X Y nX t|\}}dd |D }t|dkstdd |D }t	| |D ]\}}zt
jj|||ddd	}W nB tk
rp } z"t|d| d| d
| d W 5 d }~X Y nX  fdd}|tt|||dd qq(d S )Nr   r   r   r   c                 S   s   g | ]}|j r|qS r   r   r   r   r   r   r     s      z*check_backward_formula.<locals>.<listcomp>c                 S   s"   g | ]}t j|j|j|jd qS r   r   r   r   r   r   r     s   Tr   z
- wrapped_grads: c                    s   t |  r| jS | S r   r|   r}   r   r   r   r~     s    z&check_backward_formula.<locals>.unwrapZ	equal_nan)r   r   r   r   r   r^   r   r   r   r   r_   r   r   rr   map)r   rc   rd   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rU   r   r   Zflat_new_gradsZwhich_grad_is_batchedr   r~   r   r   r   check_backward_formula  sH    

 
r   c                    s   t dd\ } fddtfdd|D }t|\}}tfdd|D }	t|	|}
t  dd	 fd
d}|||||
}ttj|}tdd |}tdd |}t|| |D ]*}|\}}}}t||
 |D ]}|\}}}tt	t
||}fdd| D }z*d kr:||}nf||}W nH tk
r } z(t|d| d| d| d| d	 W 5 d }~X Y nX  fddttj|}tfdd|}tfdd|}|||dd |||dd qqW 5 Q R X d S )NF)r   c                    sJ   t |  k	stt| tjr,| jr,t| S t| rFtdd | D S d S )Nc                 s   s"   | ]}|j rt|nd V  qd S r   )r[   r_   
randn_likerl   r   r   r   rq     s     zBcheck_forward_ad_formula.<locals>.maybe_tangent.<locals>.<genexpr>)	r]   r^   r   r_   r   r[   r   r   r   )r+   r   r   r   maybe_tangent  s    
z/check_forward_ad_formula.<locals>.maybe_tangentc                 3   s   | ]} |V  qd S r   r   r   r   r   r   rq     s     z+check_forward_ad_formula.<locals>.<genexpr>c                 3   s   | ]} |V  qd S r   r   r   r   r   r   rq     s     c                 S   sN   | \}}t |tjr*|jr*t| |S t|rJtdd t	||D S |S )Nc                 s   s.   | ]&\}}|d k	r"t | |n|V  qd S r   )fwAD	make_dualr;   )rm   priZtangr   r   r   rq     s   zDcheck_forward_ad_formula.<locals>.maybe_make_dual.<locals>.<genexpr>)
r   r_   r   r[   r   r   r;   r   rr   r   )Zdualprimaltangentr   r   r   maybe_make_dual  s    z1check_forward_ad_formula.<locals>.maybe_make_dualc                    sN   t tt| |} fdd| D }d kr>||S f||S )Nc                    s"   i | ]\}}| || fqS r   r   rm   kv)r   tangent_kwargsr   r   
<dictcomp>  s      zKcheck_forward_ad_formula.<locals>.compute_expected_grad.<locals>.<dictcomp>)rr   r   r   r    )rc   tangent_argsrd   r   op_args	op_kwargs)r   r   r   )r   r   compute_expected_grad  s
    
z7check_forward_ad_formula.<locals>.compute_expected_gradc                 S   s   | j S r   r   r   r   r   r   r     r   z*check_forward_ad_formula.<locals>.<lambda>c                 S   s   | j S r   r   r   r   r   r   r     r   c                    s"   i | ]\}}| || fqS r   r   r   )r   new_tang_kwargsr   r   r   )  s      z,check_forward_ad_formula.<locals>.<dictcomp>r   r   z
- wrapped_tangent_args: z
- wrapped_tangent_kwargs: r   c                    s   t |  r| jS | S r   r|   r}   r   r   r   r~   :  s    z(check_forward_ad_formula.<locals>.unwrapc                    s
    | j S r   r   r   r~   r   r   r   >  r   c                    s
    | j S r   r   r   r   r   r   r   ?  r   Tr   )r   rr   r   r   r   Z
dual_levelr   Zunpack_dualr   r   r   r    r   r   )r   rc   rd   r   r   r   r   r   r   Zflat_tangent_kwargsr   r   r   Zexpected_primalsZexpected_tangentsr   r   r   r   r   Ztang_choiceZnew_tang_argsZwhich_tang_args_are_wrappedZwhich_tang_kwargs_are_wrappedr   r   r   r   Zactual_primalsZactual_tangentsr   )r!   r   r   r   r   r   r~   r   check_forward_ad_formula  sJ    

 
r   )T)r   )NN)NNN)NN)'r_   r   r   Ztorch.utils._python_dispatchr   Ztorch.utils._pytreer   r   r   	functoolsr   Ztorch.utils._mode_utilsr   r	   Ztorch.autograd.forward_adr   Z
forward_adr   typingr
   rV   r   r"   rJ   rS   rY   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s>   (	
 
-
    ;