U
    ªÊ¹jà  ã                   @   sÈ   d dl Z d dlmZ d dlmZ d dlmZ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  mZ d dlZeeeddœd	d
„Zdd„ Zdd„ Zedœdd„Zedœdd„Zedœdd„ZdS )é    N)ÚLibrary)Ú
OpOverload)ÚFunctionSchemaÚOperatorNameÚ
SchemaKindÚBaseTyÚBaseType)Ú_ExcludeDispatchKeyGuardÚDispatchKeySetÚDispatchKeyé   )Úautograd_not_implemented)ÚlibÚnew_op_nameÚ
mutable_opÚreturnc                 C   s|   t |ƒ t||ƒ}|  |¡ t|ƒ}|  ||d¡ tttj| jƒ|ƒj	}|  |t
|ƒd¡ tt |¡|ƒ}|  ||d¡ dS )a)  Given a mutable operator, registers the functional variant.

    This API also correctly links the functional variant with the mutable
    operator for the purposes of functionalization.

    All of the new registrations are performed on the ``lib`` passed in.

    Arguments:
        lib (Library): Should be a torch.library.Library object that has
            the same namespace as ``mutable_op``'s namespace.
            lib will be used to register the new functional op as well
            as a functionalization kernel for the ``mutable_op``
            If you don't have a library handy, use
            ``torch.library.Library(ns, 'FRAGMENT')`` to construct one.
        new_op_name (str): The name of the functional operator (without the
            namespace). If no namespace, the new functional variant will be
            accessible under ``torch.ops.{lib.ns}.new_op_name``.
        mutable_op (OpOverload): The mutable custom operator. Note
            that you may need to add a `.default` to it, like
            `torch.ops.aten.abs_.default`.

    ZCompositeExplicitAutogradZAutogradÚFunctionalizeN)ÚvalidateÚfunctional_schemaZdefineÚconstruct_functional_implÚimplÚgetattrÚtorchZopsÚnsÚdefaultr   Ú"construct_functionalization_kernelÚweakrefÚproxy)r   r   r   ÚschemaÚfunctional_implÚfunctional_opZf_kernel© r!   úZ/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/_custom_op/functional.pyÚregister_functional_op   s    

r#   c                    s   ‡ fdd„}|S )Nc                     s€   g }g }t tˆ ƒ| ƒD ]4\}}|r@| ¡ }| |¡ | |¡ q| |¡ qˆ |Ž }|d krdt|ƒS t|tƒrv||˜S |f|˜S ©N)ÚzipÚmutable_argsÚcloneÚappendÚtupleÚ
isinstance)ÚargsÚnew_argsZ
extra_retsÚis_writeÚargZclonedÚresult©r   r!   r"   r   <   s    

z2construct_functional_impl.<locals>.functional_implr!   )r   r   r!   r0   r"   r   ;   s    r   c                    s   ‡ ‡fdd„}|S )Nc            
   
      s˜  t  tjdd„ | ¡r>tttjƒƒ� ˆ| Ž W  5 Q R £ S Q R X t  tjtj| ¡sXt	dƒ‚g }| D ]D}t
|tjƒršt |¡ršt |¡ t |¡}| |¡ q`| |¡ q`tttjƒƒ� ˆ |Ž }W 5 Q R X tˆjjƒ}t  tj|d |… ¡}||d … }dd„ ttˆƒ| ƒD ƒ}t|ƒt|ƒk�s$t‚t||ƒD ]<\}	}tj ||	¡ tj ||	¡ tj |¡ t |¡ �q.t|ƒdk�r‚|d S t|ƒdk�r”d S |S )Nc                 S   s   t  | ¡ S r$   )r   Ú_is_functional_tensor)Úxr!   r!   r"   Ú<lambda>W   ó    zDconstruct_functionalization_kernel.<locals>.kernel.<locals>.<lambda>z={mutable_op}: expected all args to be FunctionalTensorWrapperc                 S   s   g | ]\}}|r|‘qS r!   r!   )Ú.0r-   r.   r!   r!   r"   Ú
<listcomp>t   s    ÿzFconstruct_functionalization_kernel.<locals>.kernel.<locals>.<listcomp>r   r   )ÚpytreeZtree_all_onlyr   ÚTensorr	   r
   r   r   r1   ÚRuntimeErrorr*   Z_syncZ_from_functional_tensorr(   ÚlenÚ_schemaÚreturnsZtree_mapZ_to_functional_tensorr%   r&   ÚAssertionErrorZ_CZ_propagate_xla_dataZ	_replace_Z_commit_update)
r+   Zunwrapped_argsr.   Z	unwrappedÚoutputZnum_actual_outputZactual_outputZnew_values_to_propagateZinputs_to_replaceÚ	new_value©r    r   r!   r"   ÚkernelT   s@    

 
ÿz2construct_functionalization_kernel.<locals>.kernelr!   )r   r    rA   r!   r@   r"   r   S   s    /r   r0   c                 C   s”   t | tƒstdt| ƒ› �ƒ‚t t| jƒ¡}| ¡ t	j
ksBtdƒ‚|jD ]}|jd k	rHtdƒ‚qH|jjD ]&}|j ¡ rh|jttjƒkrhtdƒ‚qhd S )Nz]register_functional_op(mutable_op): expected mutable_op to be instance of OpOverload but got zDExpected op to be mutable (as opposed to functional, inplace or out)z¸NYI: register_functional_op(op) where op returns a mutated or aliased value. Please file an issue (and as a workaround, modify your operator to not return the mutated value or aliases)zbNYI: register_functional_op(op) where op accepts Optional or List of tensors.Please file an issue.)r*   r   Ú	TypeErrorÚtyper   ÚparseÚstrr;   Úkindr   Zmutabler9   r<   Ú
annotationÚNotImplementedErrorÚ	argumentsZflat_allZis_tensor_liker   r   r8   )r   r   Úretr.   r!   r!   r"   r   †   s"    
ÿ

ÿÿr   ©Úopc                 C   s,   t  t|jƒ¡}| ¡  t | ¡¡}t|ƒS r$   )r   rD   rE   r;   Ú	signatureÚ	with_namer   )r   rL   r   r!   r!   r"   r   ¥   s    r   c                 C   s   t dd„ | jjD ƒƒS )Nc                 s   s$   | ]}|j d krdn|j jV  qd S )NF)Z
alias_infor-   )r5   r.   r!   r!   r"   Ú	<genexpr>¬   s   ÿzmutable_args.<locals>.<genexpr>)r)   r;   rI   rK   r!   r!   r"   r&   «   s    ÿr&   )r   Ztorch.libraryr   Z
torch._opsr   Ztorchgen.modelr   r   r   r   r   Ztorch._Cr	   r
   r   Zautogradr   Ztorch.utils._pytreeÚutilsZ_pytreer7   r   rE   r#   r   r   r   r   r&   r!   r!   r!   r"   Ú<module>   s"   ü03