o
    Qe;                     @   s   d dl ZddlmZ ddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ d d	lmZ d d
lmZmZ ddlmZmZmZ ddlmZmZ ddlmZ ddlmZ g ZdddZdddZdd Ze dddZ dS )    N   )check_dtype)LayerHelper)Variable)assign)dygraph_utils)templatedoc)in_dynamic_mode)_C_ops_legacy_C_ops)_non_static_mode_in_legacy_dygraphin_dygraph_mode)check_variable_and_dtype
check_type)core)convert_np_dtype_to_dtype_c           	   	   C   s   t | ts	t| } t rt| |||S t r"t| d|d|d|S d| gi}|||d}dd }|| ||| tdi t	 }|j
| jd	}|jdd| gi|||dd
|gid d|_|S )a  
    This OP creates a tensor whose diagonals of certain 2D planes (specified by dim1 and dim2)
    are filled by ``input``. By default, a 2D plane formed by the last two dimensions
    of the returned tensor will be selected.

    The argument ``offset`` determines which diagonal is generated:

    - If offset = 0, it is the main diagonal.
    - If offset > 0, it is above the main diagonal.
    - If offset < 0, it is below the main diagonal.

    Args:
        input(Tensor|numpy.ndarray): The input tensor. Must be at least 1-dimensional. The input data type should be float32, float64, int32, int64.
        offset(int, optional): Which diagonal to consider. Default: 0 (main diagonal).
        dim1(int, optional): The first dimension with respect to which to take diagonal. Default: -2.
        dim2(int, optional): The second dimension with respect to which to take diagonal. Default: -1.

    Returns:
        Tensor, the output data type is the same as input data type.

    Examples:
        .. code-block:: python

            import paddle.nn.functional as F
            import numpy as np

            diag_embed = np.random.randn(2, 3).astype('float32')
            # [[ 0.7545889 , -0.25074545,  0.5929117 ],
            #  [-0.6097662 , -0.01753256,  0.619769  ]]

            data1 = F.diag_embed(diag_embed)
            data1.numpy()
            # [[[ 0.7545889 ,  0.        ,  0.        ],
            #  [ 0.        , -0.25074545,  0.        ],
            #   [ 0.        ,  0.        ,  0.5929117 ]],

            # [[-0.6097662 ,  0.        ,  0.        ],
            #  [ 0.        , -0.01753256,  0.        ],
            #  [ 0.        ,  0.        ,  0.619769  ]]]

            data2 = F.diag_embed(diag_embed, offset=-1, dim1=0, dim2=2)
            data2.numpy()
            # [[[ 0.        ,  0.        ,  0.        ,  0.        ],
            #   [ 0.7545889 ,  0.        ,  0.        ,  0.        ],
            #   [ 0.        , -0.25074545,  0.        ,  0.        ],
            #   [ 0.        ,  0.        ,  0.5929117 ,  0.        ]],
            #
            #  [[ 0.        ,  0.        ,  0.        ,  0.        ],
            #   [-0.6097662 ,  0.        ,  0.        ,  0.        ],
            #   [ 0.        , -0.01753256,  0.        ,  0.        ],
            #   [ 0.        ,  0.        ,  0.619769  ,  0.        ]]]

            data3 = F.diag_embed(diag_embed, offset=1, dim1=0, dim2=2)
            data3.numpy()
            # [[[ 0.        ,  0.7545889 ,  0.        ,  0.        ],
            #   [ 0.        , -0.6097662 ,  0.        ,  0.        ]],
            #
            #  [[ 0.        ,  0.        , -0.25074545,  0.        ],
            #   [ 0.        ,  0.        , -0.01753256,  0.        ]],
            #
            #  [[ 0.        ,  0.        ,  0.        ,  0.5929117 ],
            #   [ 0.        ,  0.        ,  0.        ,  0.619769  ]],
            #
            #  [[ 0.        ,  0.        ,  0.        ,  0.        ],
            #   [ 0.        ,  0.        ,  0.        ,  0.        ]]]
    offsetdim1dim2Input)r   r   r   c                 S   s   t | jdg dd t| j}t|dksJ dt| t|t|ks6J dt|d  t||f t|t|ksOJ dt|d  t||f |dkrU|nt|| d }|dkrc|nt|| d }||kswJ d	||f d S )
Nr   )int32int64Zfloat16float32float64
diag_embed   zLInput must be at least 1-dimensional, But received Input's dimensional: %s.
zHDim1 is out of range (expected to be in range of [%d, %d], but got %d).
zHDim2 is out of range (expected to be in range of [%d, %d], but got %d).
r   zMdim1 and dim2 cannot be the same dimension.But received dim1 = %d, dim2 = %d
)r   dtypelistshapelennpabs)inputr   r   r   Zinput_shapeZdim1_Zdim2_ r&   ND:\Projects\ConvertPro\env\Lib\site-packages\paddle/nn/functional/extension.py__check_inputv   s:   

z!diag_embed.<locals>.__check_inputr   r   Out)typeinputsattrsoutputsTN)r   )
isinstancer   r   r   r
   r   r	   r   r   locals"create_variable_for_type_inferencer   	append_opstop_gradient)	r%   r   r   r   r,   r-   r(   helperoutr&   r&   r'   r   &   s,   
C

r   r   c                 C   s   t  r=t|tjjst|}|dur=t|tjjr(d|f}tj	| |g|R  }nd|d|f}tj	| dg|R  }d|_
|S tdi t }|j|d}d| gi}d|ji}|durgt|trc||d< n||d< |jd|d	|i|d
 d|_
|S )aR  
    **SequenceMask Layer**

    This layer outputs a mask according to the input :code:`x` and
    :code:`maxlen` with data type of :code:`dtype`.

    Supposing :code:`x` is a Tensor with shape [d_1, d_2, ..., d_n], the
    :code:`y` is a mask with shape [d_1, d_2, ..., d_n, maxlen], where:

    .. math::

        y(i_1, i_2,..., i_n, j) = (j < x(i_1, i_2,..., i_n))

    .. code-block:: text

        Case:

        Consider input:
            x = [3, 1, 1, 0]    max_len = 4

        then we get out:
            mask = [[1, 1, 1, 0],
                    [1, 0, 0, 0],
                    [1, 0, 0, 0],
                    [0, 0, 0, 0]]

    Args:
        x (Variable): Input tensor of sequence_mask layer, \
            whose elements are integers less than :code:`maxlen`. \
            Tensor or LodTensor with shape [d_1, d_2, ..., d_n].
        maxlen (int, optional): Maximum length of the sequence. If :code:`maxlen` \
                           is None, it would be replace with :math:`max(x)`.
        dtype (np.dtype|paddle.dtype|str, optional): Data type of the output, \
             ``int64`` by default.
        name(str, optional): For detailed information, please refer \
            to :ref:`api_guide_Name`. Usually name is no need to set and \
            None by default.

    Returns: 
            Tensor, The output sequence mask. Tensor with shape [d_1, d_2, ..., d_n, maxlen] \
            and data type of :code:`dtype`. The data type should be bool, float32, float64, int8, \
            int32 or int64.

    Examples:
        .. code-block:: python

            import paddle

            lengths = paddle.to_tensor([10, 9, 8])
            mask = paddle.nn.functional.sequence_mask(lengths)

            print(mask.numpy())
            # [[1 1 1 1 1 1 1 1 1 1]
            #  [1 1 1 1 1 1 1 1 1 0]
            #  [1 1 1 1 1 1 1 1 0 0]]

    NZ	out_dtypemaxlenTsequence_maskr)   XZMaxLenTensorYr+   r,   r.   r-   )r7   )r   r/   r   ZVarDescZVarTyper   eagerZTensorr   r7   r3   r   r0   r1   r   r   r2   )xr6   r   namer-   r5   r4   r,   r&   r&   r'   r7      s0   ;



r7   c                 C   s   | j dkr	td| j |j krtdt rt| |S t r%t| |S tdi t }t	| dddgd t	|dddgd |j
| jd	}|jd| |d
d|id |S )aj  
    To be used after beam search. After beam search, we get selected ids at
    each time step and the corresponding parents in the search tree. Both ids
    and parents have the layout :attr:`[max_time, batch_size, beam_size]`. Then
    :attr:`gather_tree` is used to backtrace from the last time step and
    generate the full sequences by collecting selected ids.

    Here is an example:

    .. code-block:: text

            Given:
                ids = [[[2 2]
                        [6 1]]
                       [[3 9]
                        [6 1]]
                       [[0 1]
                        [9 0]]]
                parents = [[[0 0]
                            [1 1]]
                           [[1 0]
                            [1 0]]
                           [[0 0]
                            [0 1]]]

            Then:
                gather_tree(ids, parents)
                         = [[[2 2]
                             [1 6]]
                            [[3 3]
                             [6 1]]
                            [[0 1]
                             [9 0]]]

    Args:
        ids(Tensor): A Tensor with shape :attr:`[length, batch_size, beam_size]`
            and data type :attr:`int32` or :attr:`int64`. It contains the selected
            ids of all time steps.
        parents(Tensor): A Tensor with the same shape and data type as :attr:`ids`,
            It contains the parents corresponding to selected ids when searching
            among beams.

    Returns:
            A Tensor with the same shape and data type as :attr:`ids`. \
            It contains the full sequences. The sequences are collected from \
            :attr:`ids` by backtracing according to :attr:`parents`.

    Examples:
        .. code-block:: python

            import paddle

            ids = paddle.to_tensor([[[2, 2], [6, 1]], [[3, 9], [6, 1]], [[0, 1], [9, 0]]])

            parents = paddle.to_tensor([[[0, 0], [1, 1]], [[1, 0], [1, 0]], [[0, 0], [0, 1]]])

            final_sequences = paddle.nn.functional.gather_tree(ids, parents)
            # [[[2, 2], [1, 6]], [[3, 3], [6, 1]], [[0, 1], [9, 0]]]

    r   zLThe input ids must be a 3D tensor with shape [length, batch_size, beam_size]z4The ids's shape must be the same as parents' shape. gather_treeidsr   r   parentsr)   )ZIdsZParentsr*   )r+   r,   r.   N)r>   )ndim
ValueErrorr   r
   r>   r   r   r   r0   r   r1   r   r2   )r?   r@   r4   r5   r&   r&   r'   r>      s0   
=r>         ?NCHWc              	   C   s   |dvrt d|t rt| |||S t r$t| d|d|d|S tdi t }t	| ddd	gd t
|dtd t
|dtd |j| jd
}t|tsStd|jdd| id|i|||dd |S )a  

    **Temporal Shift Operator**

    ${comment}

    Args:
        x(Tensor): ${x_comment}
        seg_num(int): ${seg_num_comment}
        shift_ratio(float): ${shift_ratio_comment}
        name(str, optional): For detailed information, please refer
                             to :ref:`api_guide_Name`. Usually name is no need to set and
                             None by default.
        data_format(str, optional): Data format that specifies the layout of input.
            It can be "NCHW" or "NHWC". Default: "NCHW".

    Returns:
        out(Tensor): The temporal shifting result is a tensor with the
        same shape and same data type as the input.

    Examples:
        .. code-block:: python

            import paddle
            import paddle.nn.functional as F

            input = paddle.randn([6, 4, 2, 2])
            out = F.temporal_shift(x=input, seg_num=2, shift_ratio=0.2)
    )rD   ZNHWCzMAttr(data_format) should be 'NCHW' or 'NHWC'. Received Attr(data_format): {}.seg_numshift_ratiodata_formattemporal_shiftr<   r   r   r)   zseg_num must be int type.r8   r*   )rE   rF   rG   r:   N)rH   )rB   formatr   r
   rH   r   r   r   r0   r   r   intfloatr1   r   r/   	TypeErrorr2   )r<   rE   rF   r=   rG   r4   r5   r&   r&   r'   rH   [  sD   


rH   )r   r   r   )Nr   N)rC   NrD   )!numpyr#   Zfluid.data_feederr   Zfluid.layer_helperr   Zstaticr   Ztensor.creationr   Zfluidr   Ztensor.layer_function_generatorr   Zpaddler	   r
   r   Zfluid.frameworkr   r   r   r   r   Z	frameworkr   Zcommon_ops_importr   __all__r   r7   r>   rH   r&   r&   r&   r'   <module>   s&   

~[\