o
    Oee                      @   s   d dl Z G dd deZedZedZedZedZedZed	Zd
d Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! ZdS )"    Nc                   @   s0   e Zd ZdZddgZdd Zdd Zdd	 Zd
S )Registryz A general registry object. nametabc                 C   s   || _ i | _d S N)r   r   selfr    r   PD:\Projects\ConvertPro\env\Lib\site-packages\paddle/incubate/autograd/primreg.py__init__   s   
zRegistry.__init__c                 C   s(   || j vsJ d| d|| j |< d S )Nzname "z"" should not be registered before.)r   )r   r   valuer   r   r	   register   s   zRegistry.registerc                 C   s   | j |S r   )r   getr   r   r   r	   lookup   s   zRegistry.lookupN)__name__
__module____qualname____doc__	__slots__r
   r   r   r   r   r   r	   r      s    r   Z	primop_fnZ	orig2primZ	prim2origZ
primop_jvpZprimop_transposeZprimop_position_argnamesc                 C   
   t | S r   )
_primop_fnr   Zoptyper   r   r	   	lookup_fn*      
r   c                 C   r   r   )
_orig2primr   r   r   r   r	   lookup_orig2prim.   r   r   c                 C   r   r   )
_prim2origr   r   r   r   r	   lookup_prim2orig2   r   r   c                 C   r   r   )_primop_jvpr   r   r   r   r	   
lookup_jvp6   r   r   c                 C   r   r   )_primop_transposer   r   r   r   r	   lookup_transpose:   r   r    c                 C   s   t | j}|dusJ d| j d|^ }}g }|D ]1}tt| jj| |}t|dks:J dt| dt|dkrF|	| q|	|d  q|S )a  
    Returns the position inputs of `op` as registered with REGISTER_FN.
    
    Args:
        op(Operator): The op that needs to get the inputs

    Returns:
        Tensor(s): Inputs of the op

    Examples: 
        .. code-block:: python
            @REGISTER_FN('div_p', 'X', 'Y', 'Z')
            def div(x, y, out=None):
                return _simple_binop(LayerHelper('div_p', **locals()))

    The registered inputs are ['X', 'Y'] for div_p and accordingly this
    function will return inputs in the order of X then Y.
    
    Nzargs of z, should not be None in op_position_inputs().r   z>len(vars) should be greater than or equal to 0, but len(vars)=.   )
_primop_position_argnamesr   typelistmapblockvarinputlenappend)opargsZinput_names_Zinputsr   varsr   r   r	   op_position_inputs>   s"   
r0   c                 C   s~   t | j}|dusJ d|^ }}tt| jj| |}t|dks/J dt| dt|dkr9|}|S |d }|S )a  
    Returns the output of `op` as registered with REGISTER_FN.
    
    Args:
        op(Operator): The op that needs to get the output

    Returns:
        Tensor(s): Output of the op

    Examples: 
        .. code-block:: python
            @REGISTER_FN('div_p', 'X', 'Y', 'Z')
            def div(x, y, out=None):
                return _simple_binop(LayerHelper('div_p', **locals()))

    The registered output is ['Z'] for div_p and accordingly this
    function will return output Z.
    
    Nz0args should not be None in op_position_output().r   zDlen(outvars) should be greater than or equal to 0, but len(outvars)=r!   r"   )	r#   r   r$   r%   r&   r'   r(   outputr*   )r,   r-   r.   Zoutput_nameZoutvarsr1   r   r   r	   op_position_outputd   s    
r2   c                    s:   t  tstdt  dt |  fdd}|S )a  
    Decorator for registering the Python function for a primitive op.        

    Args:
        op_type(str): The op name
        position_argnames(list[str]): Input and ouput names of the op

    Returns:
        wrapper: Inner wrapper function

    Examples: 
        .. code-block:: python
        @REGISTER_FN('tanh_p', 'X', 'Y')
        def tanh(x, out=None):
            return _simple_unop(LayerHelper('tanh_p', **locals()))
    
    op_type must be str, but got r!   c                    s   t  |  | S r   )r   r   fop_typer   r	   wrapper   s   zREGISTER_FN.<locals>.wrapper)
isinstancestr	TypeErrorr$   r#   r   )r7   Zposition_argnamesr8   r   r6   r	   REGISTER_FN   s
   
r<   c                    .   t  tstdt  d fdd}|S )a  
    Decorator for registering the lower function for an original op into sequence of primitive ops.
    
    Args:
        op_type(str): The op name

    Returns:
        wrapper: Inner wrapper function

    Examples:
        .. code-block:: python
            @REGISTER_ORIG2PRIM('tanh')
            def tanh_orig2prim(op):
                x, = get_input_var_list(op)
                return primops.tanh(x)

    r3   r!   c                        fdd}t | d S )Nc                    6   | j ksJ d| j  d  | g|R i |S Nz3op.type should be equal to op_type, but op.type is z and op_type is r$   r,   r-   kwargsr5   r7   r   r	   _lower       z3REGISTER_ORIG2PRIM.<locals>.wrapper.<locals>._lower)r   r   r5   rE   r6   r4   r	   r8         z#REGISTER_ORIG2PRIM.<locals>.wrapperr9   r:   r;   r$   r7   r8   r   r6   r	   REGISTER_ORIG2PRIM      
rK   c                    r=   )a  
    Decorator for registering the lower function for an primitive op into sequence of original ops.
    
    Args:
        op_type(str): The op name

    Returns:
        wrapper: Inner wrapper function

    Examples:
        .. code-block:: python
            @REGISTER_PRIM2ORIG('tanh_p')
            def tanh_prim2orig(op):
                x, = get_input_var_list(op)
                return paddle.tanh(x)

    r3   r!   c                    r>   )Nc                    r?   r@   rA   rB   rD   r   r	   rE      rF   z3REGISTER_PRIM2ORIG.<locals>.wrapper.<locals>._lower)r   r   rG   r6   r4   r	   r8      rH   z#REGISTER_PRIM2ORIG.<locals>.wrapperrI   rJ   r   r6   r	   REGISTER_PRIM2ORIG   rL   rM   c                    r=   )aa  
    Decorator for registering the JVP function for a primitive op.
    
    Args:
        op_type(str): The op name

    Returns:
        wrapper: Inner wrapper function

    Examples:
        .. code-block:: python
            @REGISTER_JVP('add_p')
            def add_jvp(op, x_dot, y_dot):
                return primops.add(x_dot, y_dot)
    
    r3   r!   c                        fdd}t |  S )Nc                    r?   r@   rA   rB   rD   r   r	   _jvp   rF   z+REGISTER_JVP.<locals>.wrapper.<locals>._jvp)r   r   )r5   rO   r6   r4   r	   r8         zREGISTER_JVP.<locals>.wrapperrI   rJ   r   r6   r	   REGISTER_JVP   s   
	rQ   c                    r=   )a  
    Decorator for registering the transpose function for a primitive op
    that denotes a linear operation in the forward AD graph.
    
    Args:
        op_type(str): The op name

    Returns:
        wrapper: Inner wrapper function

    Examples:
        .. code-block:: python
            @REGISTER_TRANSPOSE('add_p')
            def add_transpose(op, z_bar):
                return z_bar, z_bar
    
    r3   r!   c                    rN   )Nc                    s8   | j ksJ d| j  d  | |g|R i |S r@   rA   )r,   Zdot_checkerr-   rC   rD   r   r	   
_transpose  s    z7REGISTER_TRANSPOSE.<locals>.wrapper.<locals>._transpose)r   r   )r5   rR   r6   r4   r	   r8     rP   z#REGISTER_TRANSPOSE.<locals>.wrapperrI   rJ   r   r6   r	   REGISTER_TRANSPOSE  s   
	rS   )	functoolsobjectr   r   r   r   r   r   r#   r   r   r   r   r    r0   r2   r<   rK   rM   rQ   rS   r   r   r   r	   <module>   s(   &$   