U
    Kc                     @   s  d dl Z d dlmZmZmZ d dl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mZ d dl	mZ d dl	mZ d d	lmZ ed
Zedd Zdd Zeejdd Zeejdd Zeedd Zeej  eej! eej" dS )    N)DispatchKeyDispatchKeySetExcludeDispatchKeyGuard)
PyOperator)tree_flatten)get_isolated_graphmoduleget_proxy_slot)TorchDispatchMode_get_current_dispatch_mode)track_tensor_tree)ProxyTorchDispatchMode)contextmanagercondc              	   c   sT   | d k	st dt| ts*t d| j tjd  z
d V  W 5 tj|  X d S )NzCannot suspend None modezUnexpected mode type )AssertionError
isinstancer	   	__class__torchZ_CZ_set_torch_dispatch_mode)mode r   ?/tmp/pip-unpacked-wheel-gikjz4vx/functorch/experimental/cond.pysuspend_mode   s    
r   c                    s   fdd}t |tstdtdd |D s8tdt||i }t||i }g }	g }
|jjD ]}|jdkr`|	|j	 q`|jjD ]}|jdkr|
|j	 qt
|	\}}t
|
\}}t|t|ksttdt|D ]$}|| }|| }|j|jkstqd }d}|s>d| }t jj|r6|d	7 }n|}q|}d
| }t jj|r`t jj||  jj|| ||||gf}t
||} jjd||i dd}|r|| }n|| }t||d  jdS )Nc                    s   t |  j| dd S )Nc                 S   s   | j S N)proxyer   r   r   <lambda>#       z3trace_cond.<locals>._unwrap_proxy.<locals>.<lambda>)r   tracerr   
proxy_moder   r   _unwrap_proxy"   s    z!trace_cond.<locals>._unwrap_proxyz'Cond operands must be a list of tensorsc                 s   s   | ]}t |tjV  qd S r   )r   r   Tensor).0or   r   r   	<genexpr>&   s     ztrace_cond.<locals>.<genexpr>outputr   Ztrue_graph_   Zfalse_graph_call_functionZconditional)name)Zconstantr   )r   listr   allr   graphZnodesopextendargspytreer   lenrangemetahasattrr   rootZregister_moduleZtree_mapZcreate_proxyr   )r   Zfunc_overloadpredtrue_fnfalse_fnoperandsr    Z
true_graphZfalse_graphZ	true_outsZ
false_outsnodeZflat_true_outs_Zflat_false_outsiZtrue_outZ	false_outZ	next_name	candidateZ	true_nameZ
false_namer.   Z
proxy_argsZ	out_proxyoutr   r   r   
trace_cond!   sR    





r>   c                 C   s.   t  }|d kstd| r"|| S || S d S )Nz(Mode should never be enabled for CPU key)r
   r   )r5   r6   r7   r8   r   r   r   r   
cond_dense`   s
    r?   c                 G   sL   t ||g|g \}}tdd |D s,ttttj}t| ||f| S )Nc                 S   s    g | ]}t |tjr|j qS r   )r   r   r!   Zrequires_grad)r"   fr   r   r   
<listcomp>n   s    z!cond_autograd.<locals>.<listcomp>)r   r*   r   r   r   r   AutogradCPUr   )r5   r6   r7   r8   Zflat_operandsr:   Zguardr   r   r   cond_autogradj   s    rC   c              	   C   s@   t  }|d k	stdt| t|t| |||}W 5 Q R X |S )Nz5Mode should always be enabled for python fallback key)r
   r   r   r>   r   )r5   r6   r7   r8   r   resr   r   r   inneru   s
    
rE   )#r   Ztorch._Cr   r   r   Z
torch._opsr   Ztorch.utils._pytreer   Z"torch.fx.experimental.proxy_tensorr   r   utilsZ_pytreer/   Ztorch.utils._python_dispatchr	   r
   r   r   
contextlibr   r   r   r>   Zpy_implZCPUr?   rB   rC   rE   ZfallthroughZPythonTLSSnapshotZADInplaceOrViewZBackendSelectr   r   r   r   <module>   s,   

?

	



	