o
    eiBk                     @   s  U d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
Zd dlmZ d dl
mZ d dlmZ d dlmZmZmZmZmZmZ ddlmZmZ 	 g dZdd	d
Zh dZdd Z	d<dedeje dejfddZ i Z!e"edf e#d< G dd dZ$e j%G dd dZ&dedefddZ'deddfddZ(deddfd d!Z)dede*eef fd"d#Z+d$eddfd%d&Z,d'ej-de.fd(d)Z/ded*ejddfd+d,Z0dej1d-eddfd.d/Z2d0d1 Z3d2d3 Z4d=d5d6Z5d7d8 Z6d>d:d;Z7dS )?    N)infer_schema)get_ctx)BaseTyBaseTypeFunctionSchemaListTypeOperatorName
SchemaKind   )autograd_kernel_indirectionconstruct_autograd_kernel)	custom_opCustomOpr   CPUCUDA)cpucuda>   atatenprimprimstorchpytorchc                   C   s   t jdtdd d S )Nzwtorch._custom_op is deprecated and will be removed in PyTorch 2.6, please use the equivalent torch.library API instead.   
stacklevel)warningswarnDeprecationWarning r   r   _/var/www/addictedbytheproject.nl/epg/venv/lib/python3.10/site-packages/torch/_custom_op/impl.pywarn_deprecated5   s
   
r!   qualnamemanual_schemareturnc                    s   t    fdd}|S )L
    This API is deprecated, please use torch.library.custom_op instead
    c           	   	      s,  t | stdt|  t\}}t| | j|kr,td d| d| j d d u r6t| ddn }| | }t	|}t
|  d urPt||  t|d}|| t||j}t|||||d	d
}| j|_| j|_| j|_t||jdtt| tj|ttt| |S )NzDcustom_op(...)(func): Expected `func` to be a Python function, got: zcustom_op(qualname='z-', ...)(func): expected `func` to have name 'z' but got 'zX'. Please either change the name of `func` or the qualname that is passed to `custom_op`r   )mutates_argsFRAGMENTT_private_accessAutograd)inspect
isfunction
ValueErrortypeparse_qualnamevalidate_namespace__name__r   r   parsevalidate_schema validate_function_matches_schemalibraryLibrarydefinefind_ophandle_or_thrownamer   
__module____doc__impl_opnamer   weakrefproxyr   _C#_dispatch_set_report_error_callback	functoolspartialreport_error_callback)	funcnsr9   schema
schema_strfunction_schemalibophandleresultr#   r"   r   r    innerF   sR   

	


zcustom_op.<locals>.inner)r!   )r"   r#   rN   r   rM   r    r   >   s   1r   r   global_registryc                       s   e Zd ZdZdd f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	d,dejeeje f dejfddZdd ZdejfddZd,dejfddZdd  Zd!d" Zd#d$ Zd%d& Zd,d'd(Zd-d*d+Z  ZS ).r   r%   Fr(   c                   sn   t    t  |std| d| }|| _|| _|| _|| _|| _|| _	d | _
i | _d| _| t| j	< d S )Nz|The CustomOp constructor is private and we do not guarantee BC for it. Please use custom_op(...) to create a CustomOp object::F)super__init__r!   RuntimeError_schema_cpp_ns_lib	_ophandler=   	_qualnamer1   _impls'_registered_autograd_kernel_indirectionrO   )selfrJ   cpp_nsrG   operator_namerK   r)   r9   	__class__r   r    rR      s"   
zCustomOp.__init__c                 C   s4   | j rtd| j| jtt| d d| _ d S )Nz.autograd kernel indirection already registeredr*   T)rZ   AssertionErrorrV   r<   r=   r   r>   r?   r[   r   r   r    %_register_autograd_kernel_indirection   s   
z.CustomOp._register_autograd_kernel_indirectionr   c              
   C   s   |  |r'| j| }|d u rtd|j}td| d| j d| d| d	tt	|}|j
 d|j }t||| j|< d S )Nz&func_and_location is unexpectedly NonezAttempting to register a z impl for operator z that already has a z  impl registered from Python at z. This is not supported.:)	_has_implrY   r`   locationrS   rX   r+   getframeinfosys	_getframefilenamelinenoFuncAndLocation)r[   kindrE   r   func_and_locationre   framer   r   r    _register_impl   s   

zCustomOp._register_implc                 C   s
   | j | S NrY   r[   rl   r   r   r    	_get_impl      
zCustomOp._get_implc                 C   s
   || j v S rp   rq   rr   r   r   r    rd      rt   zCustomOp._has_implc                 C   s6   | ` ttj| j}t|| jrt|| j t| j	= d S rp   )
rV   getattrr   opsrU   hasattrr=   delattrrO   rX   )r[   opnamespacer   r   r    _destroy   s
   zCustomOp._destroyc                 C   s   d| j  dS )Nz<CustomOp(op="z")>)rX   ra   r   r   r    __repr__   s   zCustomOp.__repr__c                 O   s   t j| jg|R i |}|S rp   )r@   _dispatch_call_boxedrW   )r[   argskwargsrL   r   r   r    __call__   s   zCustomOp.__call__device_typesr$   c                    s6   t trgD ]}t| q
 fdd}|S )T
        This API is deprecated, please use torch.library.custom_op instead
        c                    sJ   t D ]}| j||  d t| }tjj||  q| S )Nr   )set_check_doesnt_have_library_implro   SUPPORTED_DEVICE_TYPE_TO_KEYr5   r<   rV   r=   )fdevice_typedispatch_key_stacklevelr   r[   r   r    rN      s   
zCustomOp.impl.<locals>.inner)
isinstancestrvalidate_device_type)r[   r   r   r   rN   r   r   r    r<      s   

zCustomOp.implc                 C   s@   |  |rd S t| }t| j|rtd| d| j dd S )Nzimpl(..., device_types=z): the operator zs already has an implementation for this device type via a pre-existing torch.library or TORCH_LIBRARY registration.)rd   r   r@   ._dispatch_has_computed_kernel_for_dispatch_keyrX   rS   )r[   r   keyr   r   r    r      s   
z(CustomOp._check_doesnt_have_library_implc                    s    fdd}|S )z2Register an implementation for a factory function.c                    s&     d|  t j jd|  | S )NfactoryBackendSelect)ro   r5   r<   rV   r=   r   ra   r   r    rN     s   z$CustomOp.impl_factory.<locals>.innerr   )r[   rN   r   ra   r    impl_factory   s   zCustomOp.impl_factoryc                        fdd}|S )r   c                    sZ      jd d djjt  fdd}jj	|d  S )Nabstractr   c                     sN   fdd}t jj|  | i |W  d    S 1 s w   Y  d S )Nc                         t d d  )Nz<Attempted to call get_ctx() for the meta implementation for a  .You have presumably called get_ctx() because the operator has a data-dependent output shape; if so, there is no such meta implementation and this error is the correct behavior. Otherwise, please remove the call to get_ctx() in the implementation registered with impl_abstract at rS   r   )re   r"   r   r    error_on_ctx  s   zOCustomOp.impl_abstract.<locals>.inner.<locals>.f_with_ctx.<locals>.error_on_ctx)r   _library	fake_implset_ctx_getter)r}   r~   r   r   re   r"   r   r    
f_with_ctx  s   $z9CustomOp.impl_abstract.<locals>.inner.<locals>.f_with_ctxMeta)
$_check_doesnt_have_library_meta_implro   rs   re   rX   rB   wrapsrV   r<   r=   )r   r   r   r[   r   r    rN     s   z%CustomOp.impl_abstract.<locals>.innerr   r[   r   rN   r   r   r    impl_abstract	  s   zCustomOp.impl_abstractc                    s    fdd}j    tjkr|d  j} js|d t|dkr.tdt| tdd |D }|r=|d	 tt	j
d
tt	jdtt	jdtt	jdtt	jdttt	jd di} jD ]}|j|v rkqc|dt|  d|j d qcd S )Nc                    s   t d|  dj d  )NzCCannot use torch._custom_ops APIs to register backward formula for z. Got operator z with schema: )rS   rX   )detailrG   r[   r   r    error-  s   z4CustomOp._check_can_register_backward.<locals>.errorznon-functional operatorzoperator with no returnsr   z"expected at least one return, got c                 s   s$    | ]}|j d uo|j j V  qd S rp   )
annotationis_write).0rr   r   r    	<genexpr>>  s    
z8CustomOp._check_can_register_backward.<locals>.<genexpr>zoperator that returns viewsintSymIntboolfloatTensorzList[Tensor]zoperator with return not in z (got ))rT   rl   r	   
functionalreturnslenr`   anyr   r   r   r   r   r   r   r   r.   listvalues)r[   r   retsis_non_mutating_viewallowed_return_typesretr   r   r    _check_can_register_backward,  s8   






z%CustomOp._check_can_register_backwardc                 C   s^   | j rd S t| jdrtd| j ddD ]}t| j|r,td| j d| dqd S )NCompositeImplicitAutogradz3impl_backward/impl_save_for_backward: the operator a3   already has an implementation for this device type via a pre-existing registration to DispatchKey::CompositeImplicitAutograd.CompositeImplicitAutograd operators do not need an autograd formula; instead, the operator will decompose into its constituents and those can have autograd formulas defined on them.)r*   AutogradCPUAutogradCUDAz; already has an Autograd kernel registered to DispatchKey::z vi a pre-existing torch.library or TORCH_LIBRARY registration. Please either remove those registrations or don't use the torch._custom_ops APIs)rZ   r@   %_dispatch_has_kernel_for_dispatch_keyrX   rS   )r[   r   r   r   r    (_check_doesnt_have_library_autograd_implT  s&   z1CustomOp._check_doesnt_have_library_autograd_implc                 C   sr   |  drd S t| jdrt| jdsd S t| jdr'td| j dt| jdr7td| j dd S )Nr   CompositeExplicitAutogradr   r   z!impl_abstract(...): the operator a-   already has an implementation for this device type via a pre-existing registration to DispatchKey::CompositeImplicitAutograd.CompositeImplicitAutograd operators do not need an abstract impl; instead, the operator will decompose into its constituents and those can have abstract impls defined on them.z already has an DispatchKey::Meta implementation via a pre-existing torch.library or TORCH_LIBRARY registration. Please either remove that registration or don't call impl_abstract.)rd   r@   r   rX   rS   ra   r   r   r    r   p  s&   
	z-CustomOp._check_doesnt_have_library_meta_implc              	   C   s`   |  ds	td|  dstdt| j| j| t| j| dj| dj}| 	d| d S )Nbackwardz&backward impl must be registered firstsave_for_backwardz/save_for_backward impl must be registered firstautograd)
rd   r`   r   rT   _output_differentiabilityget_oprX   rs   rE   ro   )r[   kernelr   r   r    _register_autograd_kernel  s   



z"CustomOp._register_autograd_kernelc                    r   )zyRegister a function that tells us what to save for backward.

        Please see impl_backward for more details.
        c                    sH        js  jd|  d dr"  d S d S )Nr   r   r   )r   r   rZ   rb   ro   rd   r   r   r   r   r    rN     s   
z.CustomOp.impl_save_for_backward.<locals>.innerr   r   r   r   r    impl_save_for_backward  s   	zCustomOp.impl_save_for_backwardNc                    sl   dur,fdd}t ts|  D ]
}t |ts|  qtjjtkr,|   fdd}|S )r   Nc                      s   t d  )Nzimpl_backward(output_differentiability): expected output_differentiability to be a list of bools with length equal to the number of outputs of this CustomOp got: r   r   )output_differentiabilityr   r    yell  s
   z$CustomOp.impl_backward.<locals>.yellc                    sN        js  jd|  d _dr%  d S d S )Nr   r   r   )r   r   rZ   rb   ro   r   rd   r   r   r   r   r[   r   r    rN     s   
z%CustomOp.impl_backward.<locals>.inner)r   r   r   r   rT   r   )r[   r   r   r   diffrN   r   r   r    impl_backward  s   


zCustomOp.impl_backward)r   )Nr   )r1   r:   __qualname__r;   rR   rb   ro   rs   rd   rz   r{   r   typingUnionr   IterableCallabler<   r   r   r   r   r   r   r   r   r   __classcell__r   r   r^   r    r      s4    



#(,
c                   @   s    e Zd ZU ejed< eed< dS )rk   rE   re   N)r1   r:   r   r   r   __annotations__r   r   r   r   r    rk     s   
 
rk   r\   r]   c                 C   s0   |j d u rdn|j }t|  dt|j |S )N rP   )overload_namer@   _dispatch_find_schema_or_throwr   r9   )r\   r]   r   r   r   r    r8     s
   r8   rF   c                 C   s:   d| v rt d|  d| tv rt d|  d|  dd S )N.zcustom_op(..., ns="zC"): expected ns to not contain any . (and be a valid variable name)zcustom_op(..., ns='z'): 'z9' is a reserved namespace, please choose something else. )r-   RESERVED_NS)rF   r   r   r    r0     s   
r0   rG   c                 C   s:   t jj| std|  | jjd urtd|  d S )Nzcustom_op only supports functional operators (ops that do not mutate any inputs, do not return views of the inputs, and has at least one return). Got the following non-functional schema: zUcustom_op does not support arguments named 'self'. Please rename your argument. Got: )r   r   utilsis_functional_schemar-   	argumentsself_arg)rG   r   r   r    r3     s   r3   c                 C   sR   |  dd}t|dkrtd|  dd|d v r!td|  |d |d fS )	NrP   r
   r   z$Expected there to be a namespace in z;, i.e. The operator name should look something like ns::foor   zThe torch.custom_ops APIs do not handle overloads, i.e. operator names with '.' in them. Please name your operator something like ns::foo. Got: r   )splitr   r-   )r"   namesr   r   r    r/     s   
r/   r   c                 C   s&   | t vrtd|  dt   dd S )NzCustomOp.impl(device_types=[z(, ...]): we only support device_type in r   )r   r-   keys)r   r   r   r    r     s   r   paramc                 C   s   | j tjjtjjfv S rp   )rl   r+   	ParameterPOSITIONAL_OR_KEYWORDKEYWORD_ONLY)r   r   r   r    supported_param%  s   r   rE   c                    s   t |tdd j D std tdd j D s+jt jj	ur2td dd j D }dd j D }fd	d
 fdd fdd}||j
j ||j
j d S )Nc                 s   s    | ]	\}}t |V  qd S rp   )r   r   _pr   r   r    r   1  s    z3validate_function_matches_schema.<locals>.<genexpr>zcustom_op(..., manual_schema)(func): positional-only args, varargs, and kwargs are not supported. Please rewrite `func` to not have them. Got `func` with signature: c                 s   s"    | ]\}}|j tjjuV  qd S rp   )r   r+   r   emptyr   r   r   r    r   9  s
    
zcustom_op(..., manual_schema)(func): When passing in a manual schema, we expect `func` to have no type annotations to avoid ambiguity. Got `func` with signature: c                 S   &   g | ]\}}|j tjjkr||fqS r   )rl   r+   r   r   r   r9   r   r   r   r    
<listcomp>E  
    z4validate_function_matches_schema.<locals>.<listcomp>c                 S   r   r   )rl   r+   r   r   r   r   r   r    r   J  r   c                      r   )Nzcustom_op(..., manual_schema)(func): When passing in a manual schema, we expect `func`'s signature to match `manual_schema` (aside from type annotations). func's signature: , manual_schema: r-   r   rG   sigr   r    r   P     z/validate_function_matches_schema.<locals>.errorc                      r   )Nzycustom_op(..., manual_schema)(func): neither func nor manual_schema should have default arguments. Got func's signature: r   r   r   r   r   r    error_default_argsX  r   z<validate_function_matches_schema.<locals>.error_default_argsc                    s`   t | t |kr   t| |D ]\\}}}||jkr   |jtjjus*|jd ur-  qd S rp   )r   zipr9   defaultr+   r   r   )sig_argsschema_argsr9   r   arg)r   r   r   r    compare`  s   
z1validate_function_matches_schema.<locals>.compare)r+   	signatureall
parametersitemsr-   r   return_annotation	Signaturer   r   flat_positionalflat_kwarg_only)rG   rE   
positional	kwargonlyr   r   )r   r   rG   r   r    r4   ,  s8   
	r4   r   c              	   C   sp   |dkrt |  d|dkrt |  d|dv r.| }t |  d| d| d| d	t |  d
| d)N	Undefineda  : There were no Tensor inputs to this operator (e.g. you passed an empty list of Tensors). If your operator is a factory function (that is, it takes no Tensors and constructs a new one), then please use CustomOp.impl_factory to register an implementation for itr   z: when running with device='Meta' tensors: there is no abstract impl registered for this CustomOp. Please register one via CustomOp.impl_abstract to get this CustomOp to work with Meta tensors)r   r   z: when running with device='z' tensors: there is no zW impl registered for this CustomOp. Please register one via CustomOp.impl(device_type='z')z%: No implementation for dispatch key z. It is likely that we have not added this functionality yet, please either open an issue or if you're feeling adventurous, use the low-level torch.library API)NotImplementedErrorlower)r   r   devicer   r   r    rD   m  s(   rD   c                 C   s`   | j }tj|d}|  dd }t| j}|jdddd }t	
|}t||||| ddS )Nr'   rP   r
   )maxsplitTr(   )	namespacer   r5   r6   r9   r   r   rT   rsplitr   r2   r   )oprF   rJ   r9   rH   rG   r   r   r    custom_op_from_existing  s   

r  c                    sf    fdd}t  \}}ttj|s|  ttj|}t||s#|  t||}t|ds0|  |jS )Nc                      s   t d  d)NzCould not find the operator z~. Please make sure you have already registered the operator and (if registered from C++) loaded it via torch.ops.load_library.r   r   r"   r   r    error_not_found  s   
zget_op.<locals>.error_not_foundr   )r/   rw   r   rv   ru   r   )r"   r  rF   r9   ry   packetr   r  r    r     s   


r   Fc                 C   s8   | t v rt |  S |std|  dt| }t|}|S )NzCould not find custom op "z5". Did you register it via the torch._custom_ops API?)rO   rS   r   r  )r"   also_check_torch_libraryoverloadrL   r   r   r    _find_custom_op  s   
r  c                 C   sF   | t jjjvr	d S t jjj|  }|d u rd S |dsd S |djS )Nr   )r   
_custom_opr<   rO   rd   rs   rE   )r"   r   r   r   r    get_abstract_impl  s   
r  Tc              	   C   s   |  d\}}| | }t|}t| |rtjjjgng }t	|d}|j
||d t||j}	t|||||	dd}
|
  tj|	ttt|
 t| S )NrP   r'   )tagsTr(   )r   r   r2   r3   r   r@   Tagneeds_fixed_stride_orderr5   r6   r7   r8   r9   r   rb   rA   rB   rC   rD   r>   r?   r   )r"   rG   r  rF   r9   rH   rI   r  rJ   rK   rL   r   r   r    _custom_op_with_schema  s   
r  rp   )F)T)8dataclassesrB   r+   rg   r   r   r>   r   torch._Cr@   torch._library.infer_schematorch.libraryr5   r   r   torchgen.modelr   r   r   r   r   r	   r   r   r   __all__r   r   r!   r   Optionalr   r   rO   dictr   r   	dataclassrk   r8   r0   r3   tupler/   r   r   r   r   r4   AnyrD   r  r   r  r  r  r   r   r   r    <module>   sn   
 	


B  ^	
A
