o
    #jv                    @   s.  d dl 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 ddlmZ ddlmZmZmZmZmZmZmZmZ d	d
lmZmZmZ g ZdddZdd Zedd Zdd Z dddZ!dddZ"dddZ#dddZ$edd Z%edd  Z&edd!d"Z'dd#d$Z(dd%d&Z)dd'd(Z*ed)d* Z+dd+d,Z,dd-d.Z-dd/d0Z.d	d d	gdfd1d2Z/dd3d4Z0edd5d6Z1dd7d8Z2dd9d:Z3dd;d<Z4dd=d>Z5dd?d@Z6eddAdBZ7				C	ddDdEZ8					C	ddFdGZ9ddHdIZ:eddJdKZ;ddLdMZ<ddNdOZ=ddQdRZ>eddSdTZ?ddUdVZ@ddWdXZAddYdZZBdd[d\ZCdd]d^ZDdd_d`ZEddadbZFddcddZGeddedfZHddgdhdiZIddgdjdkZJddgdldmZKddndoZLddpdqZMddrdsZNddtduZOddvdwZPddxdyZQddzd{ZRdd|d}ZSedd~dZTdd ZUdd ZVdddZW		P	PdddZXe	PdddZYdddZZedddZ[edddZ\dddZ]dddZ^edddZ_edddZ`edddZaedddZbe%e&e'e)e*e+dZcecd D ]\ZeZfegejhjieeef qdd ZjdddZkedddZldddZmdddZndS )    N)_C_ops)fill_constant)inplace_apis_in_dygraph_only   )check_dtype
check_typecheck_variable_and_dtypeconvert_dtype)Variable)LayerHelper_current_expected_placeconvert_np_dtype_to_dtype_coredygraph_onlyin_dynamic_modein_dynamic_or_pir_modein_pir_mode   )_complex_to_real_dtype_real_to_complex_dtypezerosFc                    s  t  r3t| tsJ dddlm}m} |r|n|}||  d}tt fdd| D }||fS t	 rwt
| dttjjfd t| trgt| D ]\}	}
t
|
d	t|	 d
 tjjd |
 setdqJn|  sotdtj|  |S t
| dttfd t| trt| D ]\}	}
t
|
d	t|	 d
 td qtdi t }|j| d}|jdd}|jdd| i|g|gd |dd ||fS )a
  
    This function concatenates or stacks all tensors in the input LoDTensorArray
    along the axis mentioned and returns that as the output.

    For Example:

    .. code-block:: text

        Case 1:

            Given:

                input.data = {[[0.6, 0.1, 0.3],
                               [0.5, 0.3, 0.2]],
                              [[1.3],
                               [1.8]],
                              [[2.3, 2.1],
                               [2.5, 2.4]]}

                axis = 1, use_stack = False

            Then:

                output.data = [[0.6, 0.1, 0.3, 1.3, 2.3, 2.1],
                               [0.5, 0.3, 0.2, 1.8, 2.5, 2.4]]

                output_index.data = [3, 1, 2]

        Case 2:

            Given:

                input.data = {[[0.6, 0.1],
                               [0.5, 0.3]],
                              [[0.3, 1.3],
                               [0.2, 1.8]],
                              [[2.3, 2.1],
                               [2.5, 2.4]]}

                axis = 1, use_stack = True

            Then:

                output.data = [[[0.6, 0.1]
                                [0.3, 1.3]
                                [2.3, 2.1],
                               [[0.5, 0.3]
                                [0.2, 1.8]
                                [2.5, 2.4]]]

                output_index.data = [2, 2, 2]

    Args:
        input(TensorArray): A TensorArray variable.
        axis(int): The axis along which the tensors in attr::`input` will be
            concatenated or stacked.
        use_stack(bool): Act as concat_op or stack_op. For stack mode, all
            tensors in the tensor array must have the same shape.
        name(str|None): A name for this layer(optional). If set None, the layer
                       will be named automatically.

    Returns:
        Tensor: The concatenated or stacked tensor variable.
        Tensor: A 1-D tensor variable with int32 data type. The data in this \
            tensor contains all input including tensors' sizes along the axis.

    Examples:
        .. code-block:: python

            >>> import numpy
            >>> import paddle
            >>> x0 = paddle.assign(numpy.random.rand(2, 2).astype("float32"))
            >>> x1 = paddle.assign(numpy.random.rand(2, 2).astype("float32"))
            >>> i = paddle.full(shape=[1], dtype="int64", fill_value=0)
            >>> array = paddle.tensor.array.create_array(dtype='float32')
            >>> paddle.tensor.array.array_write(x0, i, array)
            >>> paddle.tensor.array.array_write(x1, i + 1, array)
            >>> output, output_index = paddle.tensor.manipulation.tensor_array_to_tensor(input=array)
    z2The 'input' in tensor_array_to_tensor must be listr   )concatstackaxisc                    s   g | ]	}t |j  qS  )intshape).0xr   r   [/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/tensor/manipulation.py
<listcomp>   s    z*tensor_array_to_tensor.<locals>.<listcomp>inputtensor_array_to_tensorinput[]z%input should be tensor array vairabledtypeint32XOutZOutIndexr   	use_stacktypeinputsoutputsattrsN)r#   )r   
isinstancelistpaddler   r   	to_tensornparrayr   r   pirOpResult	enumeratestrZis_dense_tensor_array_type	TypeErrorZ_pir_opsZarray_to_tensorr
   r   locals"create_variable_for_type_inferenceinput_dtype	append_op)r"   r   r-   namer   r   opressizesiZinput_xhelperout	out_indexr   r   r    r#   .   sl   P



r#   c                 C   s   t |tjjtjfst|}t rt| |S t	| dg dd t
|dg dd tdi t }|j|| jd}|jdd| gid|gi| j|jd	d
 |S )a  

    Take in the Tensor :attr:`x` with :attr:`x.dtype` and cast it
    to the output with :attr:`dtype`. It's meaningless if the output dtype
    equals the input dtype, but it's fine if you do so.

    Args:
        x (Tensor): An input N-D Tensor with data type bool, float16,
            float32, float64, int32, int64, uint8.
        dtype (np.dtype|str): Data type of the output:
            bool, float16, float32, float64, int8, int32, int64, uint8.

    Returns:
        Tensor, A Tensor with the same shape as input's.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.to_tensor([2, 3, 4], 'float64')
            >>> y = paddle.cast(x, 'uint8')
    r   )	boolfloat16float32float64int16r(   int64uint8uint16castr'   )
rJ   rK   rL   rM   int8rN   r(   rO   rP   rQ   r'   stop_gradientr)   r+   )Zin_dtypeZ	out_dtyper.   N)rR   )r3   r   VarDescVarTypeZDataTyper   r   r   rR   r   r   r   r>   r?   rU   rA   r'   )r   r'   rG   rH   r   r   r    rR      s6   rR   c                 C   s,   t  rt|tjjst|}t| |S dS )z
    Inplace version of ``cast`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_cast`.
    N)r   r3   r   rV   rW   r   r   cast_)r   r'   r   r   r    rX     s
   rX   c                 C   s  t |ttfrBt|}t|dkrtdtt|D ]%}|| dk r2td|| t| j ||< qtt| jd || ||< qn	tdt	| t
 rd}d}d}dd tt|D }t |ttfrnd	d |D }nt |tjjr|d
}	t|	}dd tt|D }t |ttfrdd |D }nt |tjjr|d
}	t|	}dd tt|D }t| ||||g S t rut |tttjjfstdt |tttjjfstddd tt|D }t |tjjrd|_dd tt|D }n+t |ttfr)tj|r)t|D ]\}}
t |
tjjr!d||< qtj|}t |tjjr@d|_dd tt|D }n+t |ttfrktj|rkt|D ]\}}
t |
tjjrcd||< qStj|}t| ||||g S t |tttfstdt |tttfstdtd(i t }d| i}d|i}dd tt|D }t |trd|_||d< dd tt|D }nDt |ttfrg |d< tj|rtj||d< t|D ]\}}
t |
tr|d d d||< q|d |
 qn||d< t |tr d|_||d< d d tt|D }nDt |ttfrdg |d!< tj|r`tj||d"< t|D ]\}}
t |
trV|d! d d||< q?|d! |
 q?n||d!< ||d#< |j| d$d%}|j!d||d&|id' |S ))a  
    This operator produces a slice of ``input`` along multiple axes. Similar to numpy:
    https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
    Slice uses ``axes``, ``starts`` and ``ends`` attributes to specify the start and
    end dimension for each axis in the list of axes and Slice uses this information
    to slice the input data tensor. If a negative value is passed to
    ``starts`` or ``ends`` such as :math:`-i`,  it represents the reverse position of the
    axis :math:`i-1` (here 0 is the initial position).
    If the value passed to ``starts`` or ``ends`` is greater than n
    (the number of elements in this dimension), it represents n.
    For slicing to the end of a dimension with unknown size, it is recommended
    to pass in INT_MAX. The size of ``axes`` must be equal to ``starts`` and ``ends``.
    Following examples will explain how slice works:

    .. code-block:: text

        Case1:
            Given:
                data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
                axes = [0, 1]
                starts = [1, 0]
                ends = [2, 3]
            Then:
                result = [ [5, 6, 7], ]

        Case2:
            Given:
                data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
                axes = [0, 1]
                starts = [0, 1]
                ends = [-1, 1000]       # -1 denotes the reverse 0th position of dimension 0.
            Then:
                result = [ [2, 3, 4], ] # result = data[0:1, 1:4]

    Args:
        input (Tensor): A ``Tensor`` . The data type is ``float16``, ``float32``, ``float64``, ``int32`` or ``int64``.
        axes (list|tuple): The data type is ``int32`` . Axes that `starts` and `ends` apply to .
        starts (list|tuple|Tensor): The data type is ``int32`` . If ``starts`` is a list or tuple, each element of
                it should be integer or 0-D int Tensor with shape []. If ``starts`` is an Tensor, it should be an 1-D Tensor.
                It represents starting indices of corresponding axis in ``axes``.
        ends (list|tuple|Tensor): The data type is ``int32`` . If ``ends`` is a list or tuple, each element of
                it should be integer or 0-D int Tensor with shape []. If ``ends`` is an Tensor, it should be an 1-D Tensor .
                It represents ending indices of corresponding axis in ``axes``.

    Returns:
        Tensor, A ``Tensor``. The data type is same as ``input``.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> input = paddle.rand(shape=[4, 5, 6], dtype='float32')
            >>> # example 1:
            >>> # attr starts is a list which doesn't contain tensor.
            >>> axes = [0, 1, 2]
            >>> starts = [-3, 0, 2]
            >>> ends = [3, 2, 4]
            >>> sliced_1 = paddle.slice(input, axes=axes, starts=starts, ends=ends)
            >>> # sliced_1 is input[1:3, 0:2, 2:4].

            >>> # example 2:
            >>> # attr starts is a list which contain tensor.
            >>> minus_3 = paddle.full([1], -3, "int32")
            >>> sliced_2 = paddle.slice(input, axes=axes, starts=[minus_3, 0, 2], ends=ends)
            >>> # sliced_2 is input[1:3, 0:2, 2:4].
    r   z-Input axes should not be an empty list/tuple.r   z8Input axes must be a python list or tuple, but reveived r   Nc                 S      g | ]}d qS r   r   r   rF   r   r   r    r!   e      zslice.<locals>.<listcomp>c                 S   (   g | ]}t |tjjr|d n|qS r   r3   r   eagerTensoritemr   rb   r   r   r    r!   h      Fc                 S   rY   r   r[   r   r   r    r!   o  r\   c                 S   r]   r^   r_   rc   r   r   r    r!   r  rd   c                 S   rY   re   r   r[   r   r   r    r!   y  r\   z7Input starts must be an OpResult, python list or tuple.z5Input ends must be an OpResult, python list or tuple.c                 S   rY   rZ   r   r[   r   r   r    r!     r\   Tc                 S   rY   re   r   r[   r   r   r    r!     r\   rf   c                 S   rY   re   r   r[   r   r   r    r!     r\   z7Input starts must be an Variable, python list or tuple.z5Input ends must be an Variable, python list or tuple.sliceInputaxesc                 S   rY   rZ   r   r[   r   r   r    r!     r\   StartsTensorc                 S   rY   re   r   r[   r   r   r    r!     r\   startsStartsTensorList
EndsTensorc                 S   rY   re   r   r[   r   r   r    r!     r\   endsEndsTensorListinfer_flagsr"   r&   r+   r/   r0   r2   r1   )rg   )"r3   r4   tuplelen
ValueErrorrangemaxr   minr/   r   r   r`   ra   numpyr   rg   r   r5   r9   r:   rU   utils_contain_varr;   get_int_tensor_listr
   r   r>   _convert_to_tensor_listappendr?   r@   rA   )r"   ri   rk   rn   rF   r2   Zstarts_tensorZends_tensorrp   Ztensor_tdimrG   r0   rH   r   r   r    rg     s   D


rg   c                 C   s  t  r	t| |S t| dg dd t|dttfd t|tr$t|}t|t| j	kr=t
dt| j	 dt| dt|D ]\}}|t| j	krZt
d||| t| j	f qAtdi t }|| j}|| j}|jd	d
| gi|g|gdd|id |S )a  
    Permute the data dimensions of `input` according to `perm`.

    The `i`-th dimension  of the returned tensor will correspond to the
    perm[i]-th dimension of `input`.

    Args:
        x (Tensor): The input Tensor. It is a N-D Tensor of data types bool, float32, float64, int32.
        perm (list|tuple): Permute the input according to the data of perm.
        name (str): The name of this layer. It is optional.

    Returns:
        Tensor, A transposed n-D Tensor, with data type being bool, float32, float64, int32, int64.

    For Example:

        .. code-block:: text

         x = [[[ 1  2  3  4] [ 5  6  7  8] [ 9 10 11 12]]
             [[13 14 15 16] [17 18 19 20] [21 22 23 24]]]
         shape(x) =  [2,3,4]

         # Example 1
         perm0 = [1,0,2]
         y_perm0 = [[[ 1  2  3  4] [13 14 15 16]]
                   [[ 5  6  7  8]  [17 18 19 20]]
                   [[ 9 10 11 12]  [21 22 23 24]]]
         shape(y_perm0) = [3,2,4]

         # Example 2
         perm1 = [2,1,0]
         y_perm1 = [[[ 1 13] [ 5 17] [ 9 21]]
                   [[ 2 14] [ 6 18] [10 22]]
                   [[ 3 15]  [ 7 19]  [11 23]]
                   [[ 4 16]  [ 8 20]  [12 24]]]
         shape(y_perm1) = [4,3,2]

    Examples:

        .. code-block:: python

            >>> import paddle

            >>> x = paddle.randn([2, 3, 4])
            >>> x_transposed = paddle.transpose(x, perm=[1, 0, 2])
            >>> print(x_transposed.shape)
            [3, 2, 4]

    r   	rJ   rK   rL   rM   r(   rO   rQ   	complex64
complex128	transposepermzInput(perm) is the permutation of dimensions of Input(x), its length should be equal to dimensions of Input(x), but received dimension of Input(x) is z, the length of Input(perm) is .zEach element in Input(perm) should be less than Input(x)'s dimension, but %d-th element in Input(perm) is %d which exceeds Input(x)'s dimension %d.
transpose2r)   r+   ZXShaper   r.   N)r   )r   r   r   r   r   r4   rr   r3   rs   r   rt   r;   r   r>   r?   r'   rA   )r   r   rB   idxr~   rG   rH   x_shaper   r   r    r     sJ   2
r   c                 C   s&  | j  |  kr| j k sn td| j  d| j  d|dur5|dk s*|| j| kr5td| j|  dt rN|du rA| j| }|dkrGg S t| ||S tdi t }|du rn|du se| j| dkritd| j| }g }t|D ]}|	|
| j qt|jdd	| gid
|i||dd |S )a(  
    This layer unstacks input Tensor :code:`x` into several Tensors along :code:`axis`.

    If :code:`axis` < 0, it would be replaced with :code:`axis+rank(x)`.
    If :code:`num` is None, it would be inferred from :code:`x.shape[axis]`,
    and if :code:`x.shape[axis]` <= 0 or is unknown, :code:`ValueError` is
    raised.

    Args:
        x (Tensor): Input Tensor. It is a N-D Tensors of data types float32, float64, int32, int64, complex64, complex128.
        axis (int): The axis along which the input is unstacked.
        num (int|None): The number of output variables.

    Returns:
        list(Tensor), The unstacked Tensors list. The list elements are N-D Tensors of data types float32, float64, int32, int64, complex64, complex128.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> x = paddle.ones(name='x', shape=[2, 3, 5], dtype='float32')  # create a tensor with shape=[2, 3, 5]
            >>> y = paddle.unstack(x, axis=1)  # unstack with second axis, which results 3 tensors with shape=[2, 5]

    z`axis` must be in the range [-, )Nr   z`num` must be in the range [0, unstackzunknown unstack numberr)   Y)r   numr.   )r   )ndimrt   r   r   r   r   r   r>   ru   r}   r?   r'   rA   )r   r   r   rG   outs_r   r   r    r   C  s2   

r   rf   c              	   C   s   t  rt| ||||S t| dddgd d}t|fi t }|dk s(||kr0td||f |j| jd}|j	|d| gid	|i||||d
dd |S )a  
    Reset the values of `input` according to the shard it beloning to.
    Every value in `input` must be a non-negative integer, and
    the parameter `index_num` represents the integer above the maximum
    value of `input`. Thus, all values in `input` must be in the range
    [0, index_num) and each value can be regarded as the offset to the beginning
    of the range. The range is further split into multiple shards. Specifically,
    we first compute the `shard_size` according to the following formula,
    which represents the number of integers each shard can hold. So for the
    i'th shard, it can hold values in the range [i*shard_size, (i+1)*shard_size).
    ::

        shard_size = (index_num + nshards - 1) // nshards

    For each value `v` in `input`, we reset it to a new value according to the
    following formula:
    ::

        v = v - shard_id * shard_size if shard_id * shard_size <= v < (shard_id+1) * shard_size else ignore_value

    That is, the value `v` is set to the new offset within the range represented by the shard `shard_id`
    if it in the range. Otherwise, we reset it to be `ignore_value`.

    Args:
        input (Tensor): Input tensor with data type int64 or int32. It's last dimension must be 1.
        index_num (int): An integer represents the integer above the maximum value of `input`.
        nshards (int): The number of shards.
        shard_id (int): The index of the current shard.
        ignore_value (int, optional): An integer value out of sharded index range. The default value is -1.

    Returns:
        Tensor.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> label = paddle.to_tensor([[16], [1]], "int64")
            >>> shard_label = paddle.shard_index(input=label,
            ...                                  index_num=20,
            ...                                  nshards=2,
            ...                                  shard_id=0)
            >>> print(shard_label.numpy())
            [[-1]
             [ 1]]
    r"   rO   r(   shard_indexr   z%The shard_id(%d) should be in [0, %d)r&   r)   r+   )	index_numnshardsshard_idignore_valueT)r/   r0   r1   r2   rU   )
r   r   r   r   r   r>   rt   r?   r'   rA   )r"   r   r   r   r   op_typerG   rH   r   r   r    r   {  s0   /

r   c                 C   s  t di t }t| dg dd t|dttttdtj	j
fd t|dttttdtj	j
fd |du r=dgt| j }|du rD| j}t rNt| ||S || j}d| i}i }d	d
 }dd }	t|tryd|_||d< dgt| j |d< nUtj|rg }
g }|D ]2}t|trd|_|
| |d q|	| |d}tdgd|d|d |
| || q|
|d< ||d< n|D ]}|	| q||d< t|trd|_||d< nWtj|r$g }g }|D ]2}t|trd|_|| |d q|| |d}tdgd|d|d || || q||d< ||d< n|D ]}|| q&||d< |jd|d|it|dkrBdn|d |S )a  
    Crop input into output, as specified by offsets and shape.

    .. code-block:: text

        * Case 1 (input is a 2-D Tensor):
            Input:
                X.shape = [3, 5]
                X.data = [[0, 1, 2, 0, 0],
                          [0, 3, 4, 0, 0],
                          [0, 0, 0, 0, 0]]
            Parameters:
                shape = [2, 2]
                offsets = [0, 1]
            Output:
                Out.shape = [2, 2]
                Out.data = [[1, 2],
                            [3, 4]]
        * Case 2 (input is a 3-D Tensor):
            Input:
                X.shape = [2, 3, 4]
                X.data =  [[[0, 1, 2, 3],
                            [0, 5, 6, 7],
                            [0, 0, 0, 0]],
                           [[0, 3, 4, 5],
                            [0, 6, 7, 8],
                            [0, 0, 0, 0]]]
            Parameters:
                shape = [2, 2, -1]
                offsets = [0, 0, 1]
            Output:
                Out.shape = [2, 2, 3]
                Out.data  = [[[1, 2, 3],
                              [5, 6, 7]],
                             [[3, 4, 5],
                              [6, 7, 8]]]

    Parameters:
        x (Tensor): 1-D to 6-D Tensor, the data type is float32, float64, int32 or int64.
        shape (list|tuple|Tensor, optional): The output shape is specified
            by `shape`. Its data type is int32. If a list/tuple, it's length must be
            the same as the dimension size of `x`. If a Tensor, it should be a 1-D Tensor.
            When it is a list, each element can be an integer or a Tensor of shape: [1].
            If Variable contained, it is suitable for the case that the shape may
            be changed each iteration.
        offsets (list|tuple|Variable, optional): Specifies the cropping
            offsets at each dimension. Its data type is int32. If a list/tuple, it's length
            must be the same as the dimension size of `x`. If a Tensor, it should be a 1-D
            Tensor. When it is a list, each element can be an integer or a Tensor of shape: [1].
            If Variable contained, it is suitable for the case that the offsets may be changed
            each iteration. Default: None, the offsets are 0 at each dimension.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, The cropped Tensor has same data type with `x`.

    Examples:

        .. code-block:: python

            >>> import paddle
            >>> x = paddle.to_tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
            >>> # x.shape = [3, 3]
            >>> # x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

            >>> # shape can be a 1-D Tensor or list or tuple.
            >>> shape = paddle.to_tensor([2, 2], dtype='int32')
            >>> # shape = [2, 2]
            >>> # shape = (2, 2)
            >>> out = paddle.crop(x, shape)
            >>> # out.shape = [2, 2]
            >>> # out = [[1,2], [4,5]]

            >>> # offsets can be a 1-D Tensor or list or tuple.
            >>> offsets = paddle.to_tensor([0, 1], dtype='int32')
            >>> # offsets = [1, 0]
            >>> # offsets = (1, 1)
            >>> out = paddle.crop(x, shape, offsets)
            >>> # out.shape = [2, 2]
            >>> # if offsets = [0, 0], out = [[1,2], [4,5]]
            >>> # if offsets = [0, 1], out = [[2,3], [5,6]]
            >>> # if offsets = [1, 0], out = [[4,5], [7,8]]
            >>> # if offsets = [1, 1], out = [[5,6], [8,9]]

    crop_tensorr   rL   rM   r(   rO   r   Noffsetsr   r)   c                 S   sN   t | tstdt|  | dkrtdt|  | dk r%tdt|  d S )NzIAttr(shape)'s dtype of Op(crop_tensor) should be int32, but received: %s.r   zDAttr(shape) of Op(crop_tensor) should not be zero, but received: %s.rf   zgWhen the element in Attr(shape) of Op(crop_tensor) is negative, only -1 is supported, but received: %s.r3   r   r=   r/   rt   r<   )Z	shape_valr   r   r    _attr_shape_check<  s&   
zcrop.<locals>._attr_shape_checkc                 S   s6   t | tstdt|  | dk rtdt|  d S )NzKAttr(offsets)'s dtype of Op(crop_tensor) should be int32, but received: %s.r   zVAttr(offsets) of Op(crop_tensor) should be greater or equal to zero, but received: %s.r   )Z
offset_valr   r   r    _attr_offsets_checkM  s   
z!crop.<locals>._attr_offsets_checkTZOffsetsrf   r(   r   Z	force_cpurH   ZOffsetsTensorShapeShapeTensorr+   r.   )r   )r   r>   r   r   r4   rr   r
   r/   r5   r9   r:   rs   r   r   r   cropr?   r'   r3   rU   ry   rz   r}   r   rA   )r   r   r   rB   rG   rH   Ziptsr2   r   r   Znew_offsets_tensorZoffsets_attrr~   temp_outoffsetZnew_shape_tensorZ
shape_attrdim_sizer   r   r    r     s   W













r   c                 C   s*   t |ttfstdt| t| |S )aF  
    **Notes**:
        **This API is ONLY available in Dygraph mode**

    This function fill the Tensor with value inplace.

    Args:
        x (Tensor): ``x`` is the Tensor we want to filled data inplace
        value (Scale): ``value`` is the value to be filled in x

    Returns:
        x(Tensor), Tensor x filled with value inplace

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> tensor = paddle.to_tensor([0, 1, 2, 3, 4])

            >>> tensor.fill_(0)
            >>> print(tensor.tolist())
            [0, 0, 0, 0, 0]

    z;The type of 'value'  must be int or float, but received %s.)r3   floatr   r=   r/   r   fill_)r   valuer   r   r    r     s   r   c                 C   s   t | dS )a	  
    **Notes**:
        **This API is ONLY available in Dygraph mode**

    This function fill the Tensor with zero inplace.

    Args:
        x (Tensor): ``x`` is the Tensor we want to filled with zero inplace

    Returns:
        x (Tensor), Tensor x filled with zero inplace

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> tensor = paddle.to_tensor([0, 1, 2, 3, 4])

            >>> tensor.zero_()
            >>> print(tensor.tolist())
            [0, 0, 0, 0, 0]

    g        )r   r   r   r   r   r    zero_  s   r   c                 C   s8   t  rt| jdkrt| |||S t| ||dS dS )a[  
    Note:
        This API is ONLY available in Dygraph mode.

    This function fill the value into the x Tensor's diagonal inplace.

    Args:
        x(Tensor): ``x`` is the original Tensor
        value(Scale): ``value`` is the value to filled in x
        offset(int,optional): the offset to the main diagonal. Default: 0 (main diagonal).
        wrap(bool,optional): the diagonal 'wrapped' after N columns for tall matrices.
        name(str,optional): Name for the operation (optional, default is None)

    Returns:
        Tensor, Tensor with diagonal filled with value.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> x = paddle.ones((4, 3)) * 2
            >>> x.fill_diagonal_(1.0)
            >>> print(x.tolist())
            [[1.0, 2.0, 2.0], [2.0, 1.0, 2.0], [2.0, 2.0, 1.0], [2.0, 2.0, 2.0]]
    r   TN)r   rs   r   r   fill_diagonal_)r   r   r   wraprB   r   r   r    r     s
   r   c                 C   s  | j }|t|k r|t| ksJ d|t|k r!|t| ks%J dt|dks/J d|t|; }|t|; }g }tt|D ]}||krT||krT|||  qCt|| || | || || | }	||	 t|t|j ks}J d| t|j dkr|ddg}t r|rt	| ||||S t
| ||||S t| dg d	d
 t|dg d	d
 tdi t }
|
| j}|
jd| |dd|i|||dd |S )Nz9dim1 should between [-rank,rank) in fill_diagonal_tensor_z9dim2 should between [-rank,rank) in fill_diagonal_tensor_r   z0Tensor dims should >= 2 in fill_diagonal_tensor_zthe y shape should be r   rf   r)   )rK   rL   rM   rQ   rP   rS   rN   r(   rO   rJ   r   r   z/paddle.tensor.manipulation.fill_diagonal_tensorr   fill_diagonal_tensorr)   r   r+   )r   dim1dim2r.   r   )r   rs   ru   r}   rw   rr   reshaper   r   fill_diagonal_tensor_r   r   r   r>   r?   r'   rA   )r   yr   r   r   inplaceZinshapeZ	predshaperF   ZdiaglenrG   rH   r   r   r    _fill_diagonal_tensor_impl  s~   




r   c                 C      t | ||||ddS )a7  
    Note:
        This API is ONLY available in Dygraph mode.

    This function fill the source Tensor y into the x Tensor's diagonal inplace.

    Args:
        x (Tensor): ``x`` is the original Tensor
        y (Tensor): ``y`` is the Tensor to filled in x
        dim1 (int,optional): first dimension with respect to which to fill diagonal. Default: 0.
        dim2 (int,optional): second dimension with respect to which to fill diagonal. Default: 1.
        offset (int,optional): the offset to the main diagonal. Default: 0 (main diagonal).
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, Tensor with diagonal filled with y.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.ones((4, 3)) * 2
            >>> y = paddle.ones((3,))
            >>> x.fill_diagonal_tensor_(y)
            >>> print(x.tolist())
            [[1.0, 2.0, 2.0], [2.0, 1.0, 2.0], [2.0, 2.0, 1.0], [2.0, 2.0, 2.0]]

    Tr   r   r   r   r   r   r   r   r   r   rB   r   r   r    r   Q  s   r   c                 C   r   )a  
    This function fill the source Tensor y into the x Tensor's diagonal.

    Args:
        x (Tensor): ``x`` is the original Tensor
        y (Tensor): ``y`` is the Tensor to filled in x
        dim1 (int,optional): first dimension with respect to which to fill diagonal. Default: 0.
        dim2 (int,optional): second dimension with respect to which to fill diagonal. Default: 1.
        offset (int,optional): the offset to the main diagonal. Default: 0 (main diagonal).
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, Tensor with diagonal filled with y.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.ones((4, 3)) * 2
            >>> y = paddle.ones((3,))
            >>> nx = x.fill_diagonal_tensor(y)
            >>> print(nx.tolist())
            [[1.0, 2.0, 2.0], [2.0, 1.0, 2.0], [2.0, 2.0, 1.0], [2.0, 2.0, 2.0]]

    Fr   r   r   r   r   r    r   t  s   r   c                 C   s   |  d S )az  
    Note:
        This API is ONLY available in Dygraph mode.

    This function translate the paddle.Tensor to python list.

    Args:
        x (Tensor): ``x`` is the Tensor we want to translate to list.

    Returns:
        list, A list that contain the same value of current Tensor.


    Examples:
        .. code-block:: python

            >>> import paddle

            >>> t = paddle.to_tensor([0,1,2,3,4])
            >>> expectlist = t.tolist()
            >>> print(expectlist)
            [0, 1, 2, 3, 4]

            >>> expectlist = paddle.tolist(t)
            >>> print(expectlist)
            [0, 1, 2, 3, 4]

    F)rx   tolistr   r   r   r    r     s   r   c           
      C   s  | }t  r%t|tr|d}t|ttjjfsdd |D }t||S t	|dt
ttfd t|tsYt|D ]\}} t| dt| d g dd | j|d jkrWtd	q8n|g}t	|d
ttfd t|trut|jd
ddgdd tdi t }|j| d}|d j tjjjkrt|dksJ dt| |jdd}|jdd|d i|g|gd|ddd |S d|i}i }	t|trd|_||d< n||	d
< |jd|d|gi|	d |S )a	  

    Concatenates the input along the axis. It doesn't support 0-D Tensor because it requires a certain axis, and 0-D Tensor
    doesn't have any axis.

    Args:
        x (list|tuple): ``x`` is a Tensor list or Tensor tuple which is with data type bool, float16,
            float32, float64, int32, int64, int8, uint8. All the Tensors in ``x`` must have same data type.
        axis (int|Tensor, optional): Specify the axis to operate on the input Tensors.
            Tt should be integer or 0-D int Tensor with shape []. The effective range is [-R, R), where R is Rank(x). When ``axis < 0``,
            it works the same way as ``axis+R``. Default is 0.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, A Tensor with the same data type as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x1 = paddle.to_tensor([[1, 2, 3],
            ...                        [4, 5, 6]])
            >>> x2 = paddle.to_tensor([[11, 12, 13],
            ...                        [14, 15, 16]])
            >>> x3 = paddle.to_tensor([[21, 22],
            ...                        [23, 24]])
            >>> zero = paddle.full(shape=[1], dtype='int32', fill_value=0)
            >>> # When the axis is negative, the real axis is (axis + Rank(x))
            >>> # As follow, axis is -1, Rank(x) is 2, the real axis is 1
            >>> out1 = paddle.concat(x=[x1, x2, x3], axis=-1)
            >>> out2 = paddle.concat(x=[x1, x2], axis=0)
            >>> out3 = paddle.concat(x=[x1, x2], axis=zero)
            >>> print(out1)
            Tensor(shape=[2, 8], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[1 , 2 , 3 , 11, 12, 13, 21, 22],
             [4 , 5 , 6 , 14, 15, 16, 23, 24]])
            >>> print(out2)
            Tensor(shape=[4, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[1 , 2 , 3 ],
             [4 , 5 , 6 ],
             [11, 12, 13],
             [14, 15, 16]])
            >>> print(out3)
            Tensor(shape=[4, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[1 , 2 , 3 ],
             [4 , 5 , 6 ],
             [11, 12, 13],
             [14, 15, 16]])
    r   c                 S   s    g | ]}|j d d kr|qS r^   )r   count)r   tr   r   r    r!     s     zconcat.<locals>.<listcomp>r"   r   r$   r%   )	rJ   rK   rL   rM   r(   rO   rS   Zunit8rQ   :All the Tensors in the input must have the same data type.r   r(   rO   zBThe data type of axis must be int32 or int64 when axis is a Tensorr&   r   zuIf the elements of 'input' in concat are Variable(LoDTensorArray), number of the elements must be 1, but received %s.r#   r)   r*   Fr,   r.   T
AxisTensorr+   N)r   ) r   r3   r
   rb   r5   r9   Valuer   r   r   r4   rr   r;   r   r<   r'   r=   r   r   r   r>   r?   r@   descr/   r   rV   rW   LOD_TENSOR_ARRAYrs   rA   rU   )
r   r   rB   r"   idrG   rH   rI   r0   r2   r   r   r    r     s~   3






r   c                 C   s  t | }t rt| S t| dttfd |dk rtdt| D ]\}}t	|dt
| d g dd |j| d jkr@td	q!g }g }d}|t | k r| | }tt|j}	d}
|
t |	k rt ||
krs||	|
  || n9||
 |	|
 ko||
 dko|	|
 dk}|r||
 }td
| d| d|
 ||
 |	|
 kr|	|
 ||
< |||
< |
d7 }
|
t |	k s`|d7 }|t | k sMtdi t }d}
g }|
|k r||j| d |
d7 }
|
|k sd| i}|jd|d|ii d |S )a  
    Broadcast a list of tensors following broadcast semantics

    Note:
        If you want know more about broadcasting, please refer to `Introduction to Tensor`_ .

        .. _Introduction to Tensor: ../../guides/beginner/tensor_en.html#chapter5-broadcasting-of-tensor

    Args:
        input (list|tuple): ``input`` is a Tensor list or Tensor tuple which is with data type bool,
            float16, float32, float64, int32, int64, complex64, complex128. All the Tensors in ``input`` must have same data type.
            Currently we only support tensors with rank no greater than 5.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        list(Tensor), The list of broadcasted tensors following the same order as ``input``.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> x1 = paddle.rand([1, 2, 3, 4]).astype('float32')
            >>> x2 = paddle.rand([1, 2, 1, 4]).astype('float32')
            >>> x3 = paddle.rand([1, 1, 3, 1]).astype('float32')
            >>> out1, out2, out3 = paddle.broadcast_tensors(input=[x1, x2, x3])
            >>> # out1, out2, out3: tensors broadcasted from x1, x2, x3 with shape [1,2,3,4]
    r"   broadcast_tensorsr   z8At least 1 tensor is needed to perform broadcast_tensorsr$   r%   r   r   r   zIInput tensors to broadcast_tensors does not follow bcast semanticsTensor z conflicts with Tensor z in reversed dimension r&   r)   r+   r.   N)r   )rs   r   r   r   r   r4   rr   r=   r;   r   r<   r'   reversedr   r}   r   r>   r?   r@   rA   )r"   rB   Z
num_inputsr   r   Z output_shape_r_last_tensor_indexZoutput_shape_rjtensorr   rF   invalidZ
last_indexrG   rH   r0   r   r   r    r   =  s   


r   c                 C   s   t |tr|g}t rt| |S tdi t }t| dtd |	d}t
|dg dd t|dttfd |du rA||}n|j||dd}|jdd| id	|id|id
 |S )a  
    Reverse the order of a n-D tensor along given axis in axis.

    Args:
        x (Tensor): A Tensor(or LoDTensor) with shape :math:`[N_1, N_2,..., N_k]` . The data type of the input Tensor x
            should be float32, float64, int32, int64, bool.
        axis (list|tuple|int): The axis(axes) to flip on. Negative indices for indexing from the end are accepted.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, Tensor or LoDTensor calculated by flip layer. The data type is same with input x.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> image_shape=(3, 2, 2)
            >>> img = paddle.arange(image_shape[0] * image_shape[1] * image_shape[2]).reshape(image_shape)
            >>> tmp = paddle.flip(img, [0,1])
            >>> print(tmp)
            Tensor(shape=[3, 2, 2], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[[10, 11],
              [8 , 9 ]],
             [[6 , 7 ],
              [4 , 5 ]],
             [[2 , 3 ],
              [0 , 1 ]]])

            >>> out = paddle.flip(tmp,-1)
            >>> print(out)
            Tensor(shape=[3, 2, 2], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[[11, 10],
              [9 , 8 ]],
             [[7 , 6 ],
              [5 , 4 ]],
             [[3 , 2 ],
              [1 , 0 ]]])
    flipr)   r   rK   rL   rM   r(   rO   rJ   r   NF)rB   r'   Zpersistabler+   r.   )r   )r3   r   r   r   r   r   r>   r   r
   r@   r   r4   rr   r?   Zcreate_variablerA   )r   r   rB   rG   r'   rH   r   r   r    r     s4   
(
r   c           	      C   s  t di t }t| dtd |d}t|dg dd t|dttfd t| j	}t|}|dkr:t
d| |dk rEt
d| |d	 |d
 krYt|d	 |d
  |kset
d|d	 |d
 |d	 |k rr|d	 | ks{t
d|d	  |d
 |k r|d
 | kst
d|d
  |d; }|d	kr| S |dkrtt| |d	 |d
 S ttd	|}||d
  ||d	  ||d	 < ||d
 < |d
krtt| |d
 |S tt| ||d
 S )a  
    Rotate a n-D tensor by 90 degrees. The rotation direction and times are specified by axes and the absolute value of k. Rotation direction is from axes[0] towards axes[1] if k > 0, and from axes[1] towards axes[0] for k < 0.

    Args:
        x (Tensor): The input Tensor(or LoDTensor). The data type of the input Tensor x
            should be float16, float32, float64, int32, int64, bool. float16 is only supported on gpu.
        k (int, optional): Direction and number of times to rotate, default value: 1.
        axes (list|tuple, optional): Axes to rotate, dimension must be 2. default value: [0, 1].
        name (str, optional): The default value is None.  Normally there is no need for user to set this property.
            For more information, please refer to :ref:`api_guide_Name` .

    Returns:
        Tensor, Tensor or LoDTensor calculated by rot90 layer. The data type is same with input x.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> data = paddle.arange(4)
            >>> data = paddle.reshape(data, (2, 2))
            >>> print(data.numpy())
            [[0 1]
             [2 3]]

            >>> y = paddle.rot90(data, 1, [0, 1])
            >>> print(y.numpy())
            [[1 3]
             [0 2]]

            >>> y= paddle.rot90(data, -1, [0, 1])
            >>> print(y.numpy())
            [[2 0]
             [3 1]]

            >>> data2 = paddle.arange(8)
            >>> data2 = paddle.reshape(data2, (2,2,2))
            >>> print(data2.numpy())
            [[[0 1]
              [2 3]]
             [[4 5]
              [6 7]]]

            >>> y = paddle.rot90(data2, 1, [1, 2])
            >>> print(y.numpy())
            [[[1 3]
              [0 2]]
             [[5 7]
              [4 6]]]
    rot90r)   r   r   ri   r   z2expected total rotation axes == 2, but got axes = z/expected total dims >= 2, but got total dims = r   r   zJexpected rotation axes to be different, but got axis0 = {}, and axis1 = {}z%Rotation axis0 out of range, axis0 = z%Rotation axis1 out of range, axis1 =    N)r   )r   r>   r   r
   r@   r   r4   rr   rs   r   rt   absformatr   ru   r   )	r   kri   rB   rG   r'   Zinput_total_dimsZtotal_rot_dimsZ	axes_listr   r   r    r     sT   4

(

r   c                 C   sV  t | ttjjfstdt| j}|dkr1t |tr|dvr#tdt |tr,|dvr0tdn@t |trA||d ksA|| k rEtdt |trU||d ksU|| k rYtd|dk ra|| }|dk ri|| }||krqtd	t	 r{t
| ||S t| d
g dd tdi t }|| j}|| j}|jdd| i||d||dd |S )a	  
    Flattens a contiguous range of axes in a tensor according to start_axis and stop_axis.

    Note:
        The output Tensor will share data with origin Tensor and doesn't have a Tensor copy in ``dygraph`` mode.
        If you want to use the Tensor copy version, please use `Tensor.clone` like ``flatten_clone_x = x.flatten().clone()``.

    For Example:

    .. code-block:: text

        Case 1:

          Given
            X.shape = (3, 100, 100, 4)

          and
            start_axis = 1
            end_axis = 2

          We get:
            Out.shape = (3, 100 * 100, 4)

        Case 2:

          Given
            X.shape = (3, 100, 100, 4)

          and
            start_axis = 0
            stop_axis = -1

          We get:
            Out.shape = (3 * 100 * 100 * 4)

    Args:
        x (Tensor): A tensor of number of dimentions >= axis. A tensor with data type float16, float32,
                      float64, int8, int32, int64, uint8.
        start_axis (int): the start axis to flatten
        stop_axis (int): the stop axis to flatten
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, A tensor with the contents of the input tensor, whose input axes are flattened by indicated :attr:`start_axis` and :attr:`end_axis`, and data type is the same as input :attr:`x`.

    Examples:

        .. code-block:: python

            >>> import paddle

            >>> image_shape=(2, 3, 4, 4)

            >>> x = paddle.arange(end=image_shape[0] * image_shape[1] * image_shape[2] * image_shape[3])
            >>> img = paddle.reshape(x, image_shape)

            >>> out = paddle.flatten(img, start_axis=1, stop_axis=2)
            >>> print(out.shape)
            [2, 12, 4]

            >>> # out shares data with img in dygraph mode
            >>> img[0, 0, 0, 0] = -1
            >>> print(out[0, 0, 0])
            Tensor(shape=[], dtype=int64, place=Place(cpu), stop_gradient=True,
            -1)
    The input x should be a Tensorr   )r   rf   zYThe start_axis should be int, and should be 0 or -1 when the input tensor is a 0-D-TensorzXThe stop_axis should be int, and should be 0 or -1 when the input tensor is a 0-D-Tensorr   @The start_axis should be a int, and in range [-rank(x), rank(x))?The stop_axis should be a int, and in range [-rank(x), rank(x))-The stop_axis should be larger than stat_axisr   )	rK   rL   rM   rS   rN   r(   rO   rP   rQ   flattenZflatten_contiguous_ranger)   r   )
start_axis	stop_axisr.   N)r   )r3   r
   r5   r9   r:   rt   rs   r   r   r   r   r   r   r   r>   r?   r'   rA   )r   r   r   rB   x_dimrG   rH   r   r   r   r    r   b  sf   C


r   c                 C   s   t | ts	tdt| j}t |tr||d ks|| k r"tdt |tr2||d ks2|| k r6td|dk r>|| }|dk rF|| }||krNtdt rXt| ||S dS )z
    Inplace version of ``flatten`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_flatten`.
    r   r   r   r   r   r   N)	r3   r
   rt   rs   r   r   r   r   flatten_)r   r   r   rB   r   r   r   r    r     s4   



r   c           	      C   s8  | j }t|tkr|g}t|tkr|g}t|}|dur>tt|D ]}|| |ks2|| | k r<td| ||q#ng }t rJt	| ||S t
| dg dd tdi t }t|dttfd || j}t|tr|jd| |dd|id|id	 |S t|d
ttfd |jdd| id|i||dd	 |S )a.  
    Roll the `x` tensor along the given axis(axes). With specific 'shifts', Elements that
    roll beyond the last position are re-introduced at the first according to 'shifts'.
    If a axis is not specified,
    the tensor will be flattened before rolling and then restored to the original shape.

    Args:
        x (Tensor): The x tensor as input.
        shifts (int|list|tuple): The number of places by which the elements
                           of the `x` tensor are shifted.
        axis (int|list|tuple, optional): axis(axes) along which to roll. Default: None
        name(str, optional): The default value is None.  Normally there is no need for user to set this property.
                For more information, please refer to :ref:`api_guide_Name` .


    Returns:
        Tensor, A Tensor with same data type as `x`.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.to_tensor([[1.0, 2.0, 3.0],
            ...                       [4.0, 5.0, 6.0],
            ...                       [7.0, 8.0, 9.0]])
            >>> out_z1 = paddle.roll(x, shifts=1)
            >>> print(out_z1.numpy())
            [[9. 1. 2.]
             [3. 4. 5.]
             [6. 7. 8.]]
            >>> out_z2 = paddle.roll(x, shifts=1, axis=0)
            >>> print(out_z2.numpy())
            [[7. 8. 9.]
             [1. 2. 3.]
             [4. 5. 6.]]
            >>> out_z3 = paddle.roll(x, shifts=1, axis=1)
            >>> print(out_z3.numpy())
            [[3. 1. 2.]
             [6. 4. 5.]
             [9. 7. 8.]]
    NzEaxis is out of range, it should be in range [{}, {}), but received {}r'   )rK   rL   rQ   rM   r(   rO   r   r   rollr   )r)   ZShiftsTensorr+   r.   shiftsr)   )r   r   )r   )r   r/   r   rs   ru   rt   r   r   r   r   r   r   r>   r   r4   rr   r?   r'   r3   r
   rA   )	r   r   r   rB   Zorigin_shapeZlen_origin_shaperF   rG   rH   r   r   r    r     sX   +

r   c                 C   s@  |du rdn|}t  rt| |S t| ts:t| ts:t| tr.| j t	j
jjkr.| g} ntddddt| tdi t }|| d j}| d j t	j
jjkrt| dksdJ dt|  |jd	d
}| D ]}t|dg dd ql|jdd| d i|g|gd|ddd |S |jdd| id|id|id |S )a  
    Stacks all the input tensors ``x`` along ``axis`` dimemsion.
    All tensors must be of the same shape and same dtype.

    For example, given N tensors of shape [A, B], if ``axis == 0``, the shape of stacked
    tensor is [N, A, B]; if ``axis == 1``, the shape of stacked
    tensor is [A, N, B], etc.


    .. code-block:: text

        Case 1:

          Input:
            x[0].shape = [1, 2]
            x[0].data = [ [1.0 , 2.0 ] ]
            x[1].shape = [1, 2]
            x[1].data = [ [3.0 , 4.0 ] ]
            x[2].shape = [1, 2]
            x[2].data = [ [5.0 , 6.0 ] ]

          Attrs:
            axis = 0

          Output:
            Out.dims = [3, 1, 2]
            Out.data =[ [ [1.0, 2.0] ],
                        [ [3.0, 4.0] ],
                        [ [5.0, 6.0] ] ]


        Case 2:

          Input:
            x[0].shape = [1, 2]
            x[0].data = [ [1.0 , 2.0 ] ]
            x[1].shape = [1, 2]
            x[1].data = [ [3.0 , 4.0 ] ]
            x[2].shape = [1, 2]
            x[2].data = [ [5.0 , 6.0 ] ]


          Attrs:
            axis = 1 or axis = -2  # If axis = -2, axis = axis+ndim(x[0])+1 = -2+2+1 = 1.

          Output:
            Out.shape = [1, 3, 2]
            Out.data =[ [ [1.0, 2.0]
                          [3.0, 4.0]
                          [5.0, 6.0] ] ]

    Args:
        x (list[Tensor]|tuple[Tensor]): Input ``x`` can be a ``list`` or ``tuple`` of tensors, the Tensors in ``x``
                                     must be of the same shape and dtype. Supported data types: float32, float64, int32, int64.
        axis (int, optional): The axis along which all inputs are stacked. ``axis`` range is ``[-(R+1), R+1)``,
                              where ``R`` is the number of dimensions of the first input tensor ``x[0]``.
                              If ``axis < 0``, ``axis = axis+R+1``. The default value of axis is 0.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, The stacked tensor with same data type as input.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x1 = paddle.to_tensor([[1.0, 2.0]])
            >>> x2 = paddle.to_tensor([[3.0, 4.0]])
            >>> x3 = paddle.to_tensor([[5.0, 6.0]])

            >>> out = paddle.stack([x1, x2, x3], axis=0)
            >>> print(out.shape)
            [3, 1, 2]
            >>> print(out)
            Tensor(shape=[3, 1, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[[1., 2.]],
             [[3., 4.]],
             [[5., 6.]]])

            >>> out = paddle.stack([x1, x2, x3], axis=-2)
            >>> print(out.shape)
            [1, 3, 2]
            >>> print(out)
            Tensor(shape=[1, 3, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[[1., 2.],
              [3., 4.],
              [5., 6.]]])
    Nr   z2The type of '{}' in {} must be {}, but received {}r   r   z*list[Tensor], tuple[Tensor] or TensorArrayr   zpIf the elements of 'x' in stack are Variable(LoDTensorArray), number of the elements must be 1, but received %s.r(   r&   rK   rL   rM   r(   rO   rQ   r#   r)   r*   Tr,   r.   r   r   )r   )r   r   r   r3   r4   rr   r
   r   r/   r   rV   rW   r   r=   r   r   r>   r?   r'   rs   r   rA   )r   r   rB   rG   rH   rI   rF   r   r   r    r   t  s\   Z	
r   c                    s  | }|}t  rot|tr|d}|t|j dksJ d|dk r)|t|j n|}t|ttfrOtj	
|rNt|D ]\}}t|trM||  ||< q<nt|ts\tdt| t|trht|||S t|||S t rt|tjjr|d|_t|trt|j| dksJ d|dk rt|j| n|}|j}t|tr|dksJ dt|tr|| dkr|| | dksJ d||| f t|||S t|tr|| dkrt||| ksJ dtj	
|rtj	|}t|||S t|dg d	d
 t|dtttfd
 t|dttfd
 t|tr%t|jdddgd
 tdi t  |j}d|i}	dt|tr=|ndi}
 fdd}t|trTd|_||	d< nt|j| dksbJ d|dk rmt|| n|}||
d< t|tr|dksJ dt|tr|| dkr|| | dksJ d||| f |}n4t|tr|| dkrt||| ksJ dt|}dd |D |
d< tj	
|r|||	d<  fddt|D } jd
|	d|i|
d |S )a	  
    Split the input tensor into multiple sub-Tensors.

    Args:
        x (Tensor): A N-D Tensor. The data type is bool, bfloat16, float16, float32, float64, uint8, int8, int32 or int64.
        num_or_sections (int|list|tuple): If ``num_or_sections`` is an int, then ``num_or_sections``
            indicates the number of equal sized sub-Tensors that the ``x`` will be divided into.
            If ``num_or_sections`` is a list or tuple, the length of it indicates the number of
            sub-Tensors and the elements in it indicate the sizes of sub-Tensors'  dimension orderly.
            The length of the list must not  be larger than the ``x`` 's size of specified ``axis``.
        axis (int|Tensor, optional): The axis along which to split, it can be a integer or a ``0-D Tensor``
            with shape [] and data type  ``int32`` or ``int64``.
            If :math::`axis < 0`, the axis to split along is :math:`rank(x) + axis`. Default is 0.
        name (str, optional): The default value is None.  Normally there is no need for user to set this property.
            For more information, please refer to :ref:`api_guide_Name` .
    Returns:
        list(Tensor), The list of segmented Tensors.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> # x is a Tensor of shape [3, 9, 5]
            >>> x = paddle.rand([3, 9, 5])

            >>> out0, out1, out2 = paddle.split(x, num_or_sections=3, axis=1)
            >>> print(out0.shape)
            [3, 3, 5]
            >>> print(out1.shape)
            [3, 3, 5]
            >>> print(out2.shape)
            [3, 3, 5]

            >>> out0, out1, out2 = paddle.split(x, num_or_sections=[2, 3, 4], axis=1)
            >>> print(out0.shape)
            [3, 2, 5]
            >>> print(out1.shape)
            [3, 3, 5]
            >>> print(out2.shape)
            [3, 4, 5]

            >>> out0, out1, out2 = paddle.split(x, num_or_sections=[2, 3, -1], axis=1)
            >>> print(out0.shape)
            [3, 2, 5]
            >>> print(out1.shape)
            [3, 3, 5]
            >>> print(out2.shape)
            [3, 4, 5]

            >>> # axis is negative, the real axis is (rank(x) + axis)=1
            >>> out0, out1, out2 = paddle.split(x, num_or_sections=3, axis=-2)
            >>> print(out0.shape)
            [3, 3, 5]
            >>> print(out1.shape)
            [3, 3, 5]
            >>> print(out2.shape)
            [3, 3, 5]
    r   z(rank(x) + axis) must >= 0zfThe type of 'num_or_sections' in split must be int, list or tuple in imperative mode, but received %s.Tznum_or_sections must be than 0.zThe input's size along the split dimension must be evenly divisible by Attr(num_or_sections). But %d is not evenly divisible by %d. z<len(num_or_sections) must not be more than input.shape[dim].r"   )
rJ   Zbfloat16rK   rQ   rL   rM   r(   rO   rP   rS   splitnum_or_sectionsr~   r(   rO   r)   r   c                    s   g }d}t | D ]=\}}t|trd|_|| qt|ts!J |dkr1|dks/J d| |} d}tdgd|d|d || q|S )Nrf   TzbOnly one value of 'num_or_section' in split can be -1. But received num_or_section[%d] is also -1.r(   r   r   )r;   r3   r
   rU   r}   r   r?   r   )Zone_listZtensor_listunk_dim_idxr   r   r   rG   r   r    _get_SectionsTensorList  s,   

z&split.<locals>._get_SectionsTensorListr   r   c                 S   s   g | ]}t |trd n|qS re   )r3   r
   )r   eler   r   r    r!     s    zsplit.<locals>.<listcomp>sectionsZSectionsTensorListc                       g | ]
} j   d qS r&   r?   r@   r[   r   r   r    r!         r+   r.   N)r   )r   r3   r
   rb   rs   r   r4   rr   r5   ry   rz   r;   r   r=   r/   r   Zsplit_with_numr   r   r9   r:   rU   r{   r   r   r   r'   r   r>   ru   rA   )r   r   r   rB   r"   r~   indexrb   input_shaper0   r2   r   r   r   r   r   r    r     s   =











r   c                 C   s*   | j dk rtd| j  t| |d|dS )a[  
    Split the input tensor into multiple sub-Tensors along the vertical axis, which is equivalent to ``paddle.split`` with ``axis=0``.

    Args:
        x (Tensor): A Tensor whose dimension must be greater than 1. The data type is bool, float16, float32, float64, uint8, int8, int32 or int64.
        num_or_sections (int|list|tuple): If ``num_or_sections`` is an int, then ``num_or_sections``
            indicates the number of equal sized sub-Tensors that the ``x`` will be divided into.
            If ``num_or_sections`` is a list or tuple, the length of it indicates the number of
            sub-Tensors and the elements in it indicate the sizes of sub-Tensors'  dimension orderly.
            The length of the list must not  be larger than the ``x`` 's size of axis 0.
        name (str, optional): The default value is None.  Normally there is no need for user to set this property.
            For more information, please refer to :ref:`api_guide_Name` .
    Returns:
        list[Tensor], The list of segmented Tensors.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> # x is a Tensor of shape [8, 6, 7]
            >>> x = paddle.rand([8, 6, 7])
            >>> out0, out1 = paddle.vsplit(x, num_or_sections=2)
            >>> print(out0.shape)
            [4, 6, 7]
            >>> print(out1.shape)
            [4, 6, 7]
            >>> out0, out1, out2 = paddle.vsplit(x, num_or_sections=[1, 3, 4])
            >>> print(out0.shape)
            [1, 6, 7]
            >>> print(out1.shape)
            [3, 6, 7]
            >>> print(out2.shape)
            [4, 6, 7]
            >>> out0, out1, out2 = paddle.vsplit(x, num_or_sections=[2, 3, -1])
            >>> print(out0.shape)
            [2, 6, 7]
            >>> print(out1.shape)
            [3, 6, 7]
            >>> print(out2.shape)
            [3, 6, 7]
    r   z=The input tensor's dimension must be greater than 1, but got r   )r   rB   )r   rt   r   )r   r   rB   r   r   r    vsplit  s
   
+
r   c           	      C   st  |du rg }nt |tr|g}n	t |trt|}| }|}t r&t||S t rWt |tr1|g}t |tj	j
r<d|_nt |ttfrQtj|rQtjj|dd}t||S tdi t }t|dg dd t|dttttfd i }t |trd|_||d	< nt |ttfrtj|rtj||d	< n||d	< |j|jd
}|j|jd
}|jdd|i|||dd |S )ak
  
    Squeeze the dimension(s) of size 1 of input tensor x's shape.

    Note that the output Tensor will share data with origin Tensor and doesn't have a
    Tensor copy in ``dygraph`` mode. If you want to use the Tensor copy version,
    please use `Tensor.clone` like ``squeeze_clone_x = x.squeeze().clone()``.

    If axis is provided, it will remove the dimension(s) by given axis that of size 1.
    If the dimension of given axis is not of size 1, the dimension remain unchanged.
    If axis is not provided, all dims equal of size 1 will be removed.

    .. code-block:: text

        Case1:

          Input:
            x.shape = [1, 3, 1, 5]  # If axis is not provided, all dims equal of size 1 will be removed.
            axis = None
          Output:
            out.shape = [3, 5]

        Case2:

          Input:
            x.shape = [1, 3, 1, 5]  # If axis is provided, it will remove the dimension(s) by given axis that of size 1.
            axis = 0
          Output:
            out.shape = [3, 1, 5]

        Case4:

          Input:
            x.shape = [1, 3, 1, 5]  # If the dimension of one given axis (3) is not of size 1, the dimension remain unchanged.
            axis = [0, 2, 3]
          Output:
            out.shape = [3, 5]

        Case4:

          Input:
            x.shape = [1, 3, 1, 5]  # If axis is negative, axis = axis + ndim (number of dimensions in x).
            axis = [-2]
          Output:
            out.shape = [1, 3, 5]

    Args:
        x (Tensor): The input Tensor. Supported data type: float32, float64, bool, int8, int32, int64.
        axis (int|list|tuple, optional): An integer or list/tuple of integers, indicating the dimensions to be squeezed. Default is None.
                          The range of axis is :math:`[-ndim(x), ndim(x))`.
                          If axis is negative, :math:`axis = axis + ndim(x)`.
                          If axis is None, all the dimensions of x of size 1 will be removed.
        name (str, optional): Please refer to :ref:`api_guide_Name`, Default None.

    Returns:
        Tensor, Squeezed Tensor with the same data type as input Tensor.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.rand([5, 1, 10])
            >>> output = paddle.squeeze(x, axis=1)

            >>> print(x.shape)
            [5, 1, 10]
            >>> print(output.shape)
            [5, 10]

            >>> # output shares data with x in dygraph mode
            >>> x[0, 0, 0] = 10.
            >>> print(output[0, 0])
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            10.)

    NTrO   Zdefault_dtypesqueezer"   )
rK   rQ   rL   rM   rJ   rS   r(   rO   r   r   	axis/axesri   r&   Zsqueeze2r)   r   rq   )r   )r3   r   rr   r4   r   r   r   r   r5   r9   r:   rU   ry   rz   r{   r   r>   r   r   r
   r|   r?   r'   rA   )	r   r   rB   r"   ri   rG   r2   rH   r   r   r   r    r   	  s\   M




r   c                 C   sP   |du rg }nt |tr|g}n	t |trt|}| }|}t r&t||S dS )z
    Inplace version of ``squeeze`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_tensor_squeeze`.
    N)r3   r   rr   r4   r   r   squeeze_r   r   rB   r"   ri   r   r   r    r   	  s   

r   rO   c                 C   s  |du rg }n|g}t |}t r<t| ||||\}}}	|g}
|r'|
| |r.|
|	 t|
dkr8|
d S t|
S t| dg dd t|dt	d t|dt	d t
|d	d
dgd t|dkrkt|d dtd tdi t }||||d}|j| jdd}|j|dd}|j|dd}	|||	d}|g}
|r|
| |r|
|	 |jdd| i||d t|
dkr|
d S t|
S )a  
    Eliminates all but the first element from every consecutive group of equivalent elements.

    Note:
        This function is different from :ref:`api_paddle_unique` in the sense that this function
        only eliminates consecutive duplicate values. This semantics is similar to :ref:`api_paddle_unique` in C++.

    Args:
        x(Tensor): the input tensor, it's data type should be float32, float64, int32, int64.
        return_inverse(bool, optional): If True, also return the indices for where elements in
            the original input ended up in the returned unique consecutive tensor. Default is False.
        return_counts(bool, optional): If True, also return the counts for each unique consecutive element.
            Default is False.
        axis(int, optional): The axis to apply unique consecutive. If None, the input will be flattened.
            Default is None.
        dtype(np.dtype|str, optional): The data type `inverse` tensor: int32 or int64.
            Default: int64.
        name(str, optional): Name for the operation. For more information, please refer to
            :ref:`api_guide_Name`. Default is None.

    Returns:
        - out (Tensor), the unique consecutive tensor for x.
        - inverse (Tensor), the element of the input tensor corresponds to
            the index of the elements in the unique consecutive tensor for x.
            inverse is provided only if return_inverse is True.
        - counts (Tensor), the counts of the every unique consecutive element in the input tensor.
            counts is provided only if return_counts is True.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.to_tensor([1, 1, 2, 2, 3, 1, 1, 2])
            >>> output = paddle.unique_consecutive(x) #
            >>> print(output)
            Tensor(shape=[5], dtype=int64, place=Place(cpu), stop_gradient=True,
            [1, 2, 3, 1, 2])

            >>> _, inverse, counts = paddle.unique_consecutive(x, return_inverse=True, return_counts=True)
            >>> print(inverse)
            Tensor(shape=[8], dtype=int64, place=Place(cpu), stop_gradient=True,
            [0, 0, 1, 1, 2, 3, 3, 4])
            >>> print(counts)
            Tensor(shape=[5], dtype=int64, place=Place(cpu), stop_gradient=True,
             [2, 2, 1, 2, 1])

            >>> x = paddle.to_tensor([[2, 1, 3], [3, 0, 1], [2, 1, 3], [2, 1, 3]])
            >>> output = paddle.unique_consecutive(x, axis=0) #
            >>> print(output)
            Tensor(shape=[3, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[2, 1, 3],
             [3, 0, 1],
             [2, 1, 3]])

            >>> x = paddle.to_tensor([[2, 1, 3], [3, 0, 1], [2, 1, 3], [2, 1, 3]])
            >>> output = paddle.unique_consecutive(x, axis=0) #
            >>> print(output)
            Tensor(shape=[3, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[2, 1, 3],
             [3, 0, 1],
             [2, 1, 3]])
    Nr   r   r"   r   unique_consecutivereturn_inversereturn_countsr'   r(   rO   r   )r'   r   r   r   TrT   )r+   IndexCountsr)   rq   )r   )r   r   r   r   r}   rs   rr   r   r   rJ   r   r   r   r>   r?   r'   rA   )r   r   r   r   r'   rB   
attr_dtyperH   inversecountsr   rG   r2   r1   r   r   r    r   	  sr   H





r   c              	   C   s6  |du rg }n|g}t |}t rEt| |||||\}}	}
}|g}|r)||	 |r0||
 |r7|| t|dkrA|d S t|S t r}t| |||||d\}}	}
}|g}|ra||	 |rh||
 |ro|| t|dkry|d S t|S t| dg dd t	|dt
d t	|d	t
d t	|d
t
d t|dddgd t|dkrt	|d dtd tdi t }|||||dd}|j| jdd}|j|dd}	|j|dd}
|j|dd}||	|
|d}|g}|r||	 |r||
 |r|| |jdd| i||d t|dkr|d S t|S )a
  
    Returns the unique elements of `x` in ascending order.

    Args:
        x(Tensor): The input tensor, it's data type should be float32, float64, int32, int64.
        return_index(bool, optional): If True, also return the indices of the input tensor that
            result in the unique Tensor.
        return_inverse(bool, optional): If True, also return the indices for where elements in
            the original input ended up in the returned unique tensor.
        return_counts(bool, optional): If True, also return the counts for each unique element.
        axis(int, optional): The axis to apply unique. If None, the input will be flattened.
            Default: None.
        dtype(np.dtype|str, optional): The date type of `indices` or `inverse` tensor: int32 or int64.
            Default: int64.
        name(str, optional): Name for the operation. For more information, please refer to
            :ref:`api_guide_Name`. Default: None.

    Returns:
        tuple (out, indices, inverse, counts). `out` is the unique tensor for `x`. `indices` is \
            provided only if `return_index` is True. `inverse` is provided only if `return_inverse` \
            is True. `counts` is provided only if `return_counts` is True.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.to_tensor([2, 3, 3, 1, 5, 3])
            >>> unique = paddle.unique(x)
            >>> print(unique)
            Tensor(shape=[4], dtype=int64, place=Place(cpu), stop_gradient=True,
            [1, 2, 3, 5])

            >>> _, indices, inverse, counts = paddle.unique(x, return_index=True, return_inverse=True, return_counts=True)
            >>> print(indices)
            Tensor(shape=[4], dtype=int64, place=Place(cpu), stop_gradient=True,
            [3, 0, 1, 4])
            >>> print(inverse)
            Tensor(shape=[6], dtype=int64, place=Place(cpu), stop_gradient=True,
            [1, 2, 2, 0, 3, 2])
            >>> print(counts)
            Tensor(shape=[4], dtype=int64, place=Place(cpu), stop_gradient=True,
            [1, 1, 3, 1])

            >>> x = paddle.to_tensor([[2, 1, 3], [3, 0, 1], [2, 1, 3]])
            >>> unique = paddle.unique(x)
            >>> print(unique)
            Tensor(shape=[4], dtype=int64, place=Place(cpu), stop_gradient=True,
            [0, 1, 2, 3])

            >>> unique = paddle.unique(x, axis=0)
            >>> print(unique)
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[2, 1, 3],
             [3, 0, 1]])
    Nr   r   Tr"   )rK   rQ   rL   rM   r(   rO   uniquereturn_indexr   r   r'   r(   rO   r   )r'   r   r   r   r   Z	is_sortedrT   )r+   ZIndicesr   r   r)   rq   )r   )r   r   r   r   r}   rs   rr   r   r   r   rJ   r   r   r   r>   r?   r'   rA   )r   r   r   r   r   r'   rB   r   rH   indicesr   r   r   rG   r2   r1   r   r   r    r   @
  s   A


	





r   c           
      C   s  | }|}t  r.t|tr|g}nt|tr| }nt|ttfr(dd |D }t||S t	 r_t|tr9|g}t|t
jjrDd|_nt|ttfrYt
j|rYt
jj|dd}t||S t|dttttfd t|dg d	d tdi t }d|i}i }t|tr|g}t|trd|_||d< nt|ttfrt
j|rt
j||d< n||d< |j|jd}|j|jd}	|jd
||||	dd |S )a	  
    Insert single-dimensional entries to the shape of input Tensor ``x``. Takes one
    required argument axis, a dimension or list of dimensions that will be inserted.
    Dimension indices in axis are as seen in the output tensor.

    Note that the output Tensor will share data with origin Tensor and doesn't have a
    Tensor copy in ``dygraph`` mode. If you want to use the Tensor copy version,
    please use `Tensor.clone` like ``unsqueeze_clone_x = x.unsqueeze(-1).clone()``.

    Args:
        x (Tensor): The input Tensor to be unsqueezed. Supported data type: bfloat16, float16, float32, float64, bool, int8, int32, int64.
        axis (int|list|tuple|Tensor): Indicates the dimensions to be inserted. The data type is ``int32`` .
                                    If ``axis`` is a list or tuple, each element of it should be integer or 0-D Tensor with shape [].
                                    If ``axis`` is a Tensor, it should be an 1-D Tensor .
                                    If ``axis`` is negative, ``axis = axis + ndim(x) + 1``.
        name (str|None): Name for this layer. Please refer to :ref:`api_guide_Name`, Default None.

    Returns:
        Tensor, Unsqueezed Tensor with the same data type as input Tensor.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.rand([5, 10])
            >>> print(x.shape)
            [5, 10]

            >>> out1 = paddle.unsqueeze(x, axis=0)
            >>> print(out1.shape)
            [1, 5, 10]

            >>> out2 = paddle.unsqueeze(x, axis=[0, 2])
            >>> print(out2.shape)
            [1, 5, 1, 10]

            >>> axis = paddle.to_tensor([0, 1, 2])
            >>> out3 = paddle.unsqueeze(x, axis=axis)
            >>> print(out3.shape)
            [1, 1, 1, 5, 10]

            >>> # out1, out2, out3 share data with x in dygraph mode
            >>> x[0, 0] = 10.
            >>> print(out1[0, 0, 0])
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            10.)
            >>> print(out2[0, 0, 0, 0])
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            10.)
            >>> print(out3[0, 0, 0, 0, 0])
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            10.)

    c                 S   $   g | ]}t |tr|d n|qS r^   r3   r
   rb   rc   r   r   r    r!   '      zunsqueeze.<locals>.<listcomp>TrO   r   r   	unsqueezer"   )rQ   rK   rQ   rL   rM   rJ   rS   rN   r(   rO   r   r   
unsqueeze2r)   Z
AxesTensorZAxesTensorListri   r&   r   rq   N)r   )r   r3   r   r
   r   r4   rr   r   r   r   r5   r9   r:   rU   ry   rz   r{   r   r   r   r>   r|   r?   r'   rA   )
r   r   rB   r"   ri   rG   r0   r2   rH   r   r   r   r    r   
  sj   8







r   c                 C   sV   | }|}t |tr|g}nt |tr| }nt |ttfr%dd |D }t||S )z
    Inplace version of ``unsqueeze`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_tensor_unsqueeze`.
    c                 S   r   r^   r   rc   r   r   r    r!   v  r   zunsqueeze_.<locals>.<listcomp>)r3   r   r
   r   r4   rr   r   
unsqueeze_r   r   r   r    r   i  s   


r   c                 C   s   |du rd}t  rt| ||S t| dg dd t|dddgd t|tr0t|d	ddgd tdi t }|d}|	|}t|tsZ|j
d| |d
|ddd|id |S |j
d| ||dddid|id |S )a  
    Output is obtained by gathering entries of ``axis``
    of ``x`` indexed by ``index`` and concatenate them together.

    .. code-block:: text


                Given:

                x = [[1, 2],
                     [3, 4],
                     [5, 6]]

                index = [1, 2]
                axis=[0]

                Then:

                out = [[3, 4],
                       [5, 6]]

    Args:
        x (Tensor): The source input tensor with rank>=1. Supported data type is
            int32, int64, float32, float64 and uint8 (only for CPU),
            float16 (only for GPU).
        index (Tensor): The index input tensor with rank=0 or rank=1. Data type is int32 or int64.
        axis (Tensor|int, optional): The axis of input to be gathered, it's can be int or a Tensor with data type is int32 or int64. The default value is None, if None, the ``axis`` is 0.
        name (str, optional): The default value is None.  Normally there is no need for user to set this property.
            For more information, please refer to :ref:`api_guide_Name` .

    Returns:
        output (Tensor), If the index is a 1-D tensor, the output is a tensor with the same shape as ``x``. If the index is a 0-D tensor, the output will reduce the dimension where the axis pointing.

    Examples:

        .. code-block:: python

            >>> import paddle

            >>> input = paddle.to_tensor([[1,2],[3,4],[5,6]])
            >>> index = paddle.to_tensor([0,1])
            >>> output = paddle.gather(input, index, axis=0)
            >>> print(output)
            Tensor(shape=[2, 2], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[1, 2],
             [3, 4]])
    Nr   r   )rK   rL   rM   rN   r(   rO   rP   rQ   gatherr   r(   rO   r   r)   r   F)r   	overwriter+   rq   )r)   r   Axisr   )r   )r   r   r   r   r3   r
   r   r>   r@   r?   rA   )r   r   r   rB   rG   r'   rH   r   r   r    r   }  s>   0





r   c                    s  t |tstdt| |t| j | jvr%td| j  d| j dt r.t	| |S t |t
jr9t
|}| j}|dkrB|nt|| }|| }tdi t  t| dtd   }t|dg dd  fd	d
t|D } jdd| id|id|id |S )aY  

    Removes a tensor dimension, then split the input tensor into multiple sub-Tensors.

    Args:
        input (Tensor): The input variable which is an N-D Tensor, data type being bool, float16, float32, float64, int32, int64, complex64 or complex128.
        axis (int32|int64, optional): A scalar with type ``int32|int64`` shape [1]. The dimension along which to unbind.
            If :math:`axis < 0`, the dimension to unbind along is :math:`rank(input) + axis`. Default is 0.
    Returns:
        list(Tensor), The list of segmented Tensor variables.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> # input is a Tensor which shape is [3, 4, 5]
            >>> input = paddle.rand([3, 4, 5])

            >>> [x0, x1, x2] = paddle.unbind(input, axis=0)
            >>> # x0.shape [4, 5]
            >>> # x1.shape [4, 5]
            >>> # x2.shape [4, 5]

            >>> [x0, x1, x2, x3] = paddle.unbind(input, axis=1)
            >>> # x0.shape [3, 5]
            >>> # x1.shape [3, 5]
            >>> # x2.shape [3, 5]
            >>> # x3.shape [3, 5]
    z1The type of 'axis'  must be int, but received %s.zThe axis must in range(r   z).r   unbindr"   )	rJ   rK   rQ   rL   rM   r(   rO   r   r   c                    r   r   r   r[   r   r   r    r!      r   zunbind.<locals>.<listcomp>r)   r+   r   r.   N)r  )r3   r   r=   r/   ru   r   rt   r   r   r  r7   ZgenericZasscalarr   rs   r   r>   r   r
   r@   r   rA   )r"   r   r   Zaxis_r   r'   r   r   r   r    r    sD   



r  Tc                 C   sx   t  rt| |||S t| dg dd t|dtd td	i t }|| j	}|j
d| ||dd|id|id |S )
a  
    **Scatter Layer**
    Output is obtained by updating the input on selected indices based on updates.

    .. code-block:: python

        >>> import paddle
        >>> #input:
        >>> x = paddle.to_tensor([[1, 1], [2, 2], [3, 3]], dtype='float32')
        >>> index = paddle.to_tensor([2, 1, 0, 1], dtype='int64')
        >>> # shape of updates should be the same as x
        >>> # shape of updates with dim > 1 should be the same as input
        >>> updates = paddle.to_tensor([[1, 1], [2, 2], [3, 3], [4, 4]], dtype='float32')
        >>> overwrite = False
        >>> # calculation:
        >>> if not overwrite:
        ...     for i in range(len(index)):
        ...         x[index[i]] = paddle.zeros([2])
        >>> for i in range(len(index)):
        ...     if (overwrite):
        ...         x[index[i]] = updates[i]
        ...     else:
        ...         x[index[i]] += updates[i]
        >>> # output:
        >>> out = paddle.to_tensor([[3, 3], [6, 6], [1, 1]])
        >>> print(out.shape)
        [3, 2]

    **NOTICE**: The order in which updates are applied is nondeterministic,
    so the output will be nondeterministic if index contains duplicates.

    Args:
        x (Tensor): The input N-D Tensor with ndim>=1. Data type can be float32, float64.
        index (Tensor): The index is a 1-D or 0-D Tensor. Data type can be int32, int64. The length of index cannot exceed updates's length, and the value in index cannot exceed input's length.
        updates (Tensor): Update input with updates parameter based on index. When the index is a 1-D tensor, the updates shape should be the same as input, and dim value with dim > 1 should be the same as input. When the index is a 0-D tensor, the updates should be a (N-1)-D tensor, the ith dim of the updates should be queal with the (i+1)th dim of the input.
        overwrite (bool, optional): The mode that updating the output when there are same indices.If True, use the overwrite mode to update the output of the same index,if False, use the accumulate mode to update the output of the same index. Default value is True.
        name(str, optional): The default value is None. Normally there is no need for user to set this property.  For more information, please refer to :ref:`api_guide_Name` .

    Returns:
        Tensor, The output is a Tensor with the same shape as x.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.to_tensor([[1, 1], [2, 2], [3, 3]], dtype='float32')
            >>> index = paddle.to_tensor([2, 1, 0, 1], dtype='int64')
            >>> updates = paddle.to_tensor([[1, 1], [2, 2], [3, 3], [4, 4]], dtype='float32')

            >>> output1 = paddle.scatter(x, index, updates, overwrite=False)
            >>> print(output1)
            Tensor(shape=[3, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[3., 3.],
             [6., 6.],
             [1., 1.]])

            >>> output2 = paddle.scatter(x, index, updates, overwrite=True)
            >>> # CPU device:
            >>> # [[3., 3.],
            >>> #  [4., 4.],
            >>> #  [1., 1.]]
            >>> # GPU device maybe have two results because of the repeated numbers in index
            >>> # result 1:
            >>> # [[3., 3.],
            >>> #  [4., 4.],
            >>> #  [1., 1.]]
            >>> # result 2:
            >>> # [[3., 3.],
            >>> #  [2., 2.],
            >>> #  [1., 1.]]
    r'   )rL   rM   rK   r(   rO   rQ   scatterr   )r)   ZIdsUpdatesr+   rq   N)r  )r   r   r  r   r   rJ   r   r>   r?   r'   rA   )r   r   updatesr   rB   rG   rH   r   r   r    r  /  s$   I
r  c                 C      t | |||S )z
    Inplace version of ``scatter`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_tensor_scatter`.
    )r   scatter_)r   r   r  r   rB   r   r   r    r    s   r  c                 C   sn   t  r
t| ||S | j|jkrtdtd	i t }|jdd}||}|j	d| ||dd|id |S )
ak	  

    Output is obtained by applying sparse addition to a single value
    or slice in a Tensor.

    :attr:`x` is a Tensor with ndim :math:`R`
    and :attr:`index` is a Tensor with ndim :math:`K` . Thus, :attr:`index`
    has shape :math:`[i_0, i_1, ..., i_{K-2}, Q]` where :math:`Q \leq R` . :attr:`updates`
    is a Tensor with ndim :math:`K - 1 + R - Q` and its
    shape is :math:`index.shape[:-1] + x.shape[index.shape[-1]:]` .

    According to the :math:`[i_0, i_1, ..., i_{K-2}]` of :attr:`index` ,
    add the corresponding :attr:`updates` slice to the :attr:`x` slice
    which is obtained by the last one dimension of :attr:`index` .

    .. code-block:: text

        Given:

        * Case 1:
            x = [0, 1, 2, 3, 4, 5]
            index = [[1], [2], [3], [1]]
            updates = [9, 10, 11, 12]

          we get:

            output = [0, 22, 12, 14, 4, 5]

        * Case 2:
            x = [[65, 17], [-14, -25]]
            index = [[], []]
            updates = [[[-1, -2], [1, 2]],
                       [[3, 4], [-3, -4]]]
            x.shape = (2, 2)
            index.shape = (2, 0)
            updates.shape = (2, 2, 2)

          we get:

            output = [[67, 19], [-16, -27]]

    Args:
        x (Tensor): The x input. Its dtype should be int32, int64, float32, float64.
        index (Tensor): The index input with ndim > 1 and index.shape[-1] <= x.ndim.
                          Its dtype should be int32 or int64 as it is used as indexes.
        updates (Tensor): The updated value of scatter_nd_add op, and it must have the same dtype
                            as x. It must have the shape index.shape[:-1] + x.shape[index.shape[-1]:].
        name (str|None): The output tensor name. If set None, the layer will be named automatically.

    Returns:
        output (Tensor), The output is a tensor with the same shape and dtype as x.

    Examples:

        .. code-block:: python

            >>> import paddle

            >>> x = paddle.rand(shape=[3, 5, 9, 10], dtype='float32')
            >>> updates = paddle.rand(shape=[3, 9, 10], dtype='float32')
            >>> index = paddle.to_tensor([[1, 1],
            ...                           [0, 1],
            ...                           [1, 3]], dtype='int64')

            >>> output = paddle.scatter_nd_add(x, index, updates)
            >>> print(output.shape)
            [3, 5, 9, 10]
    z'x and updates must have same data type.scatter_nd_addr   Zinput_param_name)r)   r   r  r+   r/   r0   r1   N)r  )
r   r   r  r'   rt   r   r>   r@   r?   rA   )r   r   r  rB   rG   r'   outputr   r   r    r    s   E

r  c                 C   s   t t||j| ||S )a  
    **Scatter_nd Layer**

    Output is obtained by scattering the :attr:`updates` in a new tensor according
    to :attr:`index` . This op is similar to :code:`scatter_nd_add`, except the
    tensor of :attr:`shape` is zero-initialized. Correspondingly, :code:`scatter_nd(index, updates, shape)`
    is equal to :code:`scatter_nd_add(paddle.zeros(shape, updates.dtype), index, updates)` .
    If :attr:`index` has repeated elements, then the corresponding updates are accumulated.
    Because of the numerical approximation issues, the different order of repeated elements
    in :attr:`index` may cause different results. The specific calculation method can be
    seen :code:`scatter_nd_add` . This op is the inverse of the :code:`gather_nd` op.

    Args:
        index (Tensor): The index input with ndim >= 1 and index.shape[-1] <= len(shape).
                          Its dtype should be int32 or int64 as it is used as indexes.
        updates (Tensor): The updated value of scatter_nd op. Its dtype should be float32, float64.
                            It must have the shape index.shape[:-1] + shape[index.shape[-1]:]
        shape(tuple|list): Shape of output tensor.
        name (str|None): The output Tensor name. If set None, the layer will be named automatically.

    Returns:
        output (Tensor), The output is a tensor with the same type as :attr:`updates` .

    Examples:

        .. code-block:: python

            >>> import paddle

            >>> index = paddle.to_tensor([[1, 1],
            ...                           [0, 1],
            ...                           [1, 3]], dtype="int64")
            >>> updates = paddle.rand(shape=[3, 9, 10], dtype='float32')
            >>> shape = [3, 5, 9, 10]

            >>> output = paddle.scatter_nd(index, updates, shape)
    )r  r   r'   )r   r  r   rB   r   r   r    
scatter_nd  s   &r  c                 C   s   t |dtd t| |||dS )ag  
    Split the input tensor into multiple sub-Tensors.

    Args:
        x (Tensor): A N-D Tensor. The data type is bool, float16, float32, float64, int32 or int64.
        chunks(int): The number of tensor to be split along the certain axis.
        axis (int|Tensor, optional): The axis along which to split, it can be a integer or a ``0-D Tensor``
            with shape [] and data type  ``int32`` or ``int64``.
            If :math::`axis < 0`, the axis to split along is :math:`rank(x) + axis`. Default is 0.
        name (str, optional): The default value is None.  Normally there is no need for user to set this property.
            For more information, please refer to :ref:`api_guide_Name` .
    Returns:
        list(Tensor), The list of segmented Tensors.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.rand([3, 9, 5])

            >>> out0, out1, out2 = paddle.chunk(x, chunks=3, axis=1)
            >>> # out0.shape [3, 3, 5]
            >>> # out1.shape [3, 3, 5]
            >>> # out2.shape [3, 3, 5]


            >>> # axis is negative, the real axis is (rank(x) + axis) which real
            >>> # value is 1.
            >>> out0, out1, out2 = paddle.chunk(x, chunks=3, axis=-2)
            >>> # out0.shape [3, 3, 5]
            >>> # out1.shape [3, 3, 5]
            >>> # out2.shape [3, 3, 5]
    chunkschunk)r   r   rB   )r   r   r   )r   r  r   rB   r   r   r    r    s   #r  c           
      C   s>  dd }t  r!t|tjjr|jdksJ d| }t| |S t	 rB|| | t|t
tfr<tj|r<tj|}t| |S || | dd }tdi t }d| gi}i }t|trld	|_||d
< dg|d< nt|t
tfr|||d< tj|rtj||d< |jdd}||}	|jd|d|	i|d |	S )at  

    Construct a new Tensor by repeating ``x`` the number of times given by ``repeat_times``.
    After tiling, the value of the i'th dimension of the output is equal to ``x.shape[i]*repeat_times[i]``.

    Both the number of dimensions of ``x`` and the number of elements in ``repeat_times`` should be less than or equal to 6.

    Args:
        x (Tensor): The input tensor, its data type should be bool, float16, float32, float64, int32 or int64.
        repeat_times (list|tuple|Tensor): The number of repeating times. If repeat_times is a list or tuple, all its elements
            should be integers or 1-D Tensors with the data type int32. If repeat_times is a Tensor, it should be an 1-D Tensor with the data type int32.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        N-D Tensor. The data type is the same as ``x``. The size of the i-th dimension is equal to ``x[i] * repeat_times[i]``.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> data = paddle.to_tensor([1, 2, 3], dtype='int32')
            >>> out = paddle.tile(data, repeat_times=[2, 1])
            >>> print(out)
            Tensor(shape=[2, 3], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[1, 2, 3],
             [1, 2, 3]])

            >>> out = paddle.tile(data, repeat_times=(2, 2))
            >>> print(out)
            Tensor(shape=[2, 6], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[1, 2, 3, 1, 2, 3],
             [1, 2, 3, 1, 2, 3]])

            >>> repeat_times = paddle.to_tensor([1, 2], dtype='int32')
            >>> out = paddle.tile(data, repeat_times=repeat_times)
            >>> print(out)
            Tensor(shape=[1, 6], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[1, 2, 3, 1, 2, 3]])
    c                 S   s   t |dttttjjfd t|ttjjfr"t|j	dks!J dn)|D ]&}t|ttjjfr:|
 dks9J dq$ttjtjf}t||sJJ dq$t| dg dd t| jdkrb| jsdtd	d S d S )
Nrepeat_timestiler   z-repeat_times must be a Tensor with ndim == 1.zEElements in repeat_times must be Tensor with one element or integers.r   rJ   rK   rQ   rL   rM   r(   rO   rJ   zWhen the date type is bool for the input 'x' of tile op, you must set its stop_gradient to be True by some_var.stop_gradient == True supporting some_var is the input.)r   r4   rr   r
   r5   r9   r:   r3   rs   r   numelr   r7   r(   rO   r   r	   r'   rU   rt   )r   r  elem
type_tupler   r   r    check_inputf  s@   	ztile.<locals>.check_inputr   z6Only support ndim == 1 while repeat_times is a Tensor.c                 S   sJ   g }t | D ]\}}t|tr|d q|| |dks"J dq|S )Nrf   r   z7All elements in repeat_times must be positive for tile.r;   r3   r
   r}   )Zlist_repeat_timesZattrs_repeat_timesr   timesr   r   r    get_attr_repeat_times  s   


z#tile.<locals>.get_attr_repeat_timesr  r)   TZRepeatTimesrf   r  Zrepeat_times_tensorr   r	  r+   r.   N)r  )r   r3   r   r`   ra   r   r   r   r  r   r4   rr   r5   ry   rz   r|   r   r>   r
   rU   r@   r?   rA   )
r   r  rB   r  r  rG   r0   r2   r'   rH   r   r   r    r  <  sL   *,





r  c                 C   s   t  rt| d|jS t| dg dd t|dtd t| jdkr)| j	s)t
d| g|gd}tdi t }|jdd	}||}|jd
|d|jid|id |S )a  

    Expand the input tensor ``x`` to the same shape as the input tensor ``y``.

    Both the number of dimensions of ``x`` and ``y`` must be less than or equal to 6, and the number of dimensions of ``y`` must be greather than or equal to that of ``x``. The dimension to expand must have a value of 0.

    Args:
        x (Tensor): The input tensor, its data type is bool, float32, float64, int32 or int64.
        y (Tensor): The input tensor that gives the shape to expand to.
        name (str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        N-D Tensor, A Tensor with the same shape as ``y``. The data type is the same as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> data_x = paddle.to_tensor([1, 2, 3], 'int32')
            >>> data_y = paddle.to_tensor([[1, 2, 3], [4, 5, 6]], 'int32')
            >>> out = paddle.expand_as(data_x, data_y)
            >>> print(out)
            Tensor(shape=[2, 3], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[1, 2, 3],
             [1, 2, 3]])
    Nr   )rJ   rL   rM   r(   rO   rK   rQ   	expand_asr   rJ   zWhen the data type of input 'x' for expand_as is bool, you must set its stop_gradient to be False by some_var.stop_gradient = True, supporting some_var as the input 'x'.r   r	  Zexpand_as_v2Ztarget_shaper+   rq   )r  )r   r   r  r   r   r   r
   r	   r'   rU   rt   r   r>   r@   r?   rA   )r   r   rB   r0   rG   r'   rH   r   r   r    r    s0   	
r  c                 C   s  t  r	t| |S t r9t }t|ttfr$tj	
|r#tj	||}nt|tjjr/d|_ntd t| |S t|trJt|jdksIJ dn&ttjtjf}|D ]}t|trft|jdkseJ dqSt||soJ dqSt| dg dd t|d	tttfd t| jd
kr| jstdd| gi}i }tdi t }dd }	t|trd|_||d< nt|ttfr|	||d	< tj	
|rtj	||d< |jdd}
| |
}|j!d|d|i|d |S )a5  

    Broadcast the input tensor to a given shape.

    Both the number of dimensions of ``x`` and the number of elements in ``shape`` should be less than or equal to 6. The dimension to broadcast to must have a value 0.


    Args:
        x (Tensor): The input tensor, its data type is bool, float16, float32, float64, int32 or int64.
        shape (list|tuple|Tensor): The result shape after broadcasting. The data type is int32. If shape is a list or tuple, all its elements
            should be integers or 0-D or 1-D Tensors with the data type int32. If shape is a Tensor, it should be an 1-D Tensor with the data type int32.
            The value -1 in shape means keeping the corresponding dimension unchanged.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
    Returns:
        N-D Tensor, A Tensor with the given shape. The data type is the same as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> data = paddle.to_tensor([1, 2, 3], dtype='int32')
            >>> out = paddle.broadcast_to(data, shape=[2, 3])
            >>> print(out)
            Tensor(shape=[2, 3], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[1, 2, 3],
             [1, 2, 3]])
    T0Shape only supports OpReslut, or list, or tuple.r   zshape must be an 1-D Tensor.z2Elements in shape must be 1-D Tensors or integers.r   )rJ   rQ   rK   rL   rM   r(   rO   broadcast_tor   rJ   zWhen the data type of input 'x' for broadcast_to is bool, you must set its stop_gradient to be False by some_var.stop_gradient = True, supporting some_var as the input.r)   expandc                 S   sR   g }t | D ] \}}t|tr|d q|| |dks&|dks&J dq|S )Nrf   r   z=All elements in shape of broadcast_to must be positive or -1.r  Zlist_expand_shapeZattrs_expand_shaper   r   r   r   r    get_attr_expand_shapea     

z+broadcast_to.<locals>.get_attr_expand_shaper   expand_shapes_tensorr	  	expand_v2r+   r.   Nr  )"r   r   r  r   r   r3   r4   rr   r5   ry   rz   r{   r9   r:   rU   r=   r
   rs   r   r   r7   r(   rO   r   r   r	   r'   rt   r   r>   r|   r@   r?   rA   )r   r   rB   Zplacer  r  r0   r2   rG   r  r'   rH   r   r   r    r    sp   

	




r  c                 C   s  t  r	t| |S t rCt| jdkr| jstdt|t	j
jr%d|_nt|ttfr9t	j|r8t	j|}ntd t| |S t|trS| dksRJ dn%|D ]"}t|trg| dksfJ dqUttjtjf}t||swJ dqUt| dg d	d
 t|dtttfd
 t| jdkr| jstdd| gi}i }tdi t }dd }t|trd|_||d< nt|ttfr|||d< t	j|rt	j||d< |jdd}	||	}
|jd|d|
i|d |
S )a  

    Expand the input tensor to a given shape.

    Both the number of dimensions of ``x`` and the number of elements in ``shape`` should be less than or equal to 6. And the number of dimensions of ``x`` should be less than the number of elements in ``shape``. The dimension to expand must have a value 0.

    Args:
        x (Tensor): The input Tensor, its data type is bool, float32, float64, int32 or int64.
        shape (list|tuple|Tensor): The result shape after expanding. The data type is int32. If shape is a list or tuple, all its elements
            should be integers or 0-D or 1-D Tensors with the data type int32. If shape is a Tensor, it should be an 1-D Tensor with the data type int32.
            The value -1 in shape means keeping the corresponding dimension unchanged.
        name (str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name` .

    Returns:
        N-D Tensor, A Tensor with the given shape. The data type is the same as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> data = paddle.to_tensor([1, 2, 3], dtype='int32')
            >>> out = paddle.expand(data, shape=[2, 3])
            >>> print(out)
            Tensor(shape=[2, 3], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[1, 2, 3],
             [1, 2, 3]])
    rJ   zWhen the data type of input 'x' for expand is bool, you must set its stop_gradient to be False by some_var.stop_gradient = True, supporting some_var as the input.Tr  r   z'shape must be a Tensor with one elementz>Elements in shape must be Tensor with one element or integers.r   )rJ   rK   rL   rM   r(   rO   rQ   r  r   r)   c                 S   sR   g }t | D ] \}}t|tr|d q|| |dks&|dks&J dq|S )Nr   rf   z7All elements in shape of expand must be positive or -1.r  r  r   r   r    r    r  z%expand.<locals>.get_attr_expand_shaper   r   r	  r!  r+   r.   Nr"  ) r   r   r  r   r	   r'   rU   rt   r3   r5   r9   r:   r4   rr   ry   rz   r{   r=   r
   r  r   r7   r(   rO   r   r   r   r>   r|   r@   r?   rA   )r   r   rB   r  r  r0   r2   rG   r  r'   rH   r   r   r    r    sv   

	




r  c                    s"   fdd}t  rXt|ttfr<g }|D ]}t|tjjr%||  q|| q| j	kr4 }|S t
 |}|S t|tjjrNd|_t
 |}|S tdt| dt rt dg dd t|d	tttjjfd t|ttfrtj|rtj|}n||}t
 |}|S t|tjjrd|_t
 |}|S td
t| dt dg dd t|d	tttfd d i}i }t|trd|_||d< nt|ttfr|||d	< tj|rtj||d< tdi t }	|	j jd}|	j jd}
|	jd||||
dd |S )a  
    Changes the shape of ``x`` without changing its data.

    Note that the output Tensor will share data with origin Tensor and doesn't
    have a Tensor copy in ``dygraph`` mode.
    If you want to use the Tensor copy version, please use `Tensor.clone` like
    ``reshape_clone_x = x.reshape([-1]).clone()``.

    Some tricks exist when specifying the target shape.

        - 1. -1 means the value of this dimension is inferred from the total element number of x and remaining dimensions. Thus one and only one dimension can be set -1.

        - 2. 0 means the actual dimension value is going to be copied from the corresponding dimension of x. The index of 0s in shape can not exceed the dimension of x.

    Here are some examples to explain it.

        - 1. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape is [6, 8], the reshape operator will transform x into a 2-D tensor with shape [6, 8] and leaving x's data unchanged.

        - 2. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape specified is [2, 3, -1, 2], the reshape operator will transform x into a 4-D tensor with shape [2, 3, 4, 2] and leaving x's data unchanged. In this case, one dimension of the target shape is set to -1, the value of this dimension is inferred from the total element number of x and remaining dimensions.

        - 3. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape is [-1, 0, 3, 2], the reshape operator will transform x into a 4-D tensor with shape [2, 4, 3, 2] and leaving x's data unchanged. In this case, besides -1, 0 means the actual dimension value is going to be copied from the corresponding dimension of x.

    Args:
        x (Tensor): An N-D Tensor. The data type is ``float16``, ``float32``, ``float64``, ``int16``, ``int32``, ``int64``, ``int8``, ``uint8``, ``complex64``, ``complex128``, ``bfloat16`` or ``bool``.
        shape (list|tuple|Tensor): Define the target shape. At most one dimension of the target shape can be -1.
                        The data type is ``int32`` . If ``shape`` is a list or tuple, each element of it should be integer or Tensor with shape [].
                        If ``shape`` is an Tensor, it should be an 1-D Tensor .
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, A reshaped Tensor with the same data type as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.rand([2, 4, 6], dtype="float32")
            >>> positive_four = paddle.full([1], 4, "int32")

            >>> out = paddle.reshape(x, [-1, 0, 3, 2])
            >>> print(out.shape)
            [2, 4, 3, 2]

            >>> out = paddle.reshape(x, shape=[positive_four, 12])
            >>> print(out.shape)
            [4, 12]

            >>> shape_tensor = paddle.to_tensor([8, 6], dtype=paddle.int32)
            >>> out = paddle.reshape(x, shape=shape_tensor)
            >>> print(out.shape)
            [8, 6]
            >>> # out shares data with x in dygraph mode
            >>> x[0, 0, 0] = 10.
            >>> print(out[0, 0])
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            10.)

    c                    s   d}g }t | D ]N\}}t|ttjjfr|d q|| |dkr1|dks.J d| |}q|dkrH|t jk sGJ d|t jf q|dksVJ d|t	|f q|S )Nrf   a  Only one dimension value of 'shape' in reshape can be -1. But received shape[%d] is also -1.

	# N = x.shape()[2]		# N is an int. (NOT recommend under @to_static)
	N = paddle.shape(x)[2]		# N is a Tensor. (Recommend)
	z = paddle.reshape([N, -1, 4])	# z.shape is [-1, -1, 4]

    If your target shape in Reshape represents dynamic shape, please turn it into a Tensor under @to_static. See above example for details.r   z}The index of 0 in `shape` must be less than the input tensor X's dimensions. But received shape[%d] = 0, X's dimensions = %d.zzEach dimension value of 'shape' in reshape must not be negative except one unknown dimension. But received shape[%d] = %s.)
r;   r3   r
   r5   r9   r:   r}   rs   r   r<   )Z
list_shaper   Zattrs_shapeZdim_idxr   r   r   r    get_attr_shape4  s2   



zreshape.<locals>.get_attr_shapeTz>shape must be an instance of `list`, `tuple` `Variable`, got '.'r   )rK   rL   rM   rS   rP   rN   r(   rO   rJ   rQ   r   r   r   r   zKshape must be an instance of `list`, `tuple` `OpResult(in pir mode)`, got ')rK   rL   rM   rN   r(   rO   rJ   rQ   rS   rP   r   r   r)   r   r   reshape2r&   r   rq   N)r&  )r   r3   r4   rr   r   r`   ra   r}   rb   r   r   r   rU   rt   r/   r   r   r   r5   r9   r:   ry   rz   r{   r
   r|   r   r>   r?   r'   rA   )r   r   rB   r$  	new_shaper   rH   r0   r2   rG   r   r   r   r    r     s   =%
	


r   c                    s   t  rBtjj t|ttfr( fdd|D }|| jkr | }|S t	| |}|S t| r8d|_
t	| |}|S tdt| ddS )z
    Inplace version of ``reshape`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_tensor_reshape`.
    c                    s$   g | ]}t | r|d n|qS r^   )r3   rb   rc   Ztmp_tensor_typer   r    r!     r   zreshape_.<locals>.<listcomp>TzAshape must be an instance of `list`, `tuple` or `Variable`, got 'r%  N)r   r   r`   ra   r3   r4   rr   r   r   reshape_rU   rt   r/   )r   r   rB   rH   r   r(  r    r)    s*   



r)  )rB   c                 G   s|   g }|D ]-}t |tjtjjjtjjjjfst	|}n|}|
 dkr*|d}n|}|| qt|dkr<|d S |S )aJ  
    Convert inputs to tensors and return the view with at least 1-dimension. Scalar inputs are converted,
    one or high-dimensional inputs are preserved.

    Args:
        inputs (Tensor|list(Tensor)): One or more tensors. The data type is ``float16``, ``float32``, ``float64``, ``int16``, ``int32``, ``int64``, ``int8``, ``uint8``, ``complex64``, ``complex128``, ``bfloat16`` or ``bool``.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        One Tensor, if there is only one input.
        List of Tensors, if there are more than one inputs.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> # one input
            >>> x = paddle.to_tensor(123, dtype='int32')
            >>> out = paddle.atleast_1d(x)
            >>> print(out)
            Tensor(shape=[1], dtype=int32, place=Place(cpu), stop_gradient=True,
            [123])

            >>> # more than one inputs
            >>> x = paddle.to_tensor(123, dtype='int32')
            >>> y = paddle.to_tensor([1.23], dtype='float32')
            >>> out = paddle.atleast_1d(x, y)
            >>> print(out)
            [Tensor(shape=[1], dtype=int32, place=Place(cpu), stop_gradient=True,
            [123]), Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
            [1.23000002])]

            >>> # more than 1-D input
            >>> x = paddle.to_tensor(123, dtype='int32')
            >>> y = paddle.to_tensor([[1.23]], dtype='float32')
            >>> out = paddle.atleast_1d(x, y)
            >>> print(out)
            [Tensor(shape=[1], dtype=int32, place=Place(cpu), stop_gradient=True,
            [123]), Tensor(shape=[1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[1.23000002]])]
    r   rZ   r   )r3   r5   ra   base	frameworkr
   	libpaddler9   r:   r6   r~   r   r}   rs   rB   r0   rH   r"   r   resultr   r   r    
atleast_1d  s$   +
r/  c                 G   s   g }|D ];}t |tjtjjjtjjjjfst	|}n|}|
 dkr*|d}n|
 dkr8tj|dd}n|}|| qt|dkrJ|d S |S )aD  
    Convert inputs to tensors and return the view with at least 2-dimension. Two or high-dimensional inputs are preserved.

    Args:
        inputs (Tensor|list(Tensor)): One or more tensors. The data type is ``float16``, ``float32``, ``float64``, ``int16``, ``int32``, ``int64``, ``int8``, ``uint8``, ``complex64``, ``complex128``, ``bfloat16`` or ``bool``.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        One Tensor, if there is only one input.
        List of Tensors, if there are more than one inputs.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> # one input
            >>> x = paddle.to_tensor(123, dtype='int32')
            >>> out = paddle.atleast_2d(x)
            >>> print(out)
            Tensor(shape=[1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[123]])

            >>> # more than one inputs
            >>> x = paddle.to_tensor(123, dtype='int32')
            >>> y = paddle.to_tensor([1.23], dtype='float32')
            >>> out = paddle.atleast_2d(x, y)
            >>> print(out)
            [Tensor(shape=[1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[123]]), Tensor(shape=[1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[1.23000002]])]

            >>> # more than 2-D input
            >>> x = paddle.to_tensor(123, dtype='int32')
            >>> y = paddle.to_tensor([[[1.23]]], dtype='float32')
            >>> out = paddle.atleast_2d(x, y)
            >>> print(out)
            [Tensor(shape=[1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[123]]), Tensor(shape=[1, 1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[[1.23000002]]])]
    r   )r   r   r   r   r3   r5   ra   r*  r+  r
   r,  r9   r:   r6   r~   r   r   r}   rs   r-  r   r   r    
atleast_2d&  s(   *
r1  c                 G   s   g }|D ]K}t |tjtjjjtjjjjfst	|}n|}|
 dkr*|d}n |
 dkr:tj|ddgd}n|
 dkrHtj|dd}n|}|| qt|dkrZ|d S |S )aa  
    Convert inputs to tensors and return the view with at least 3-dimension. Three or high-dimensional inputs are preserved.

    Args:
        inputs (Tensor|list(Tensor)): One or more tensors. The data type is ``float16``, ``float32``, ``float64``, ``int16``, ``int32``, ``int64``, ``int8``, ``uint8``, ``complex64``, ``complex128``, ``bfloat16`` or ``bool``.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        One Tensor, if there is only one input.
        List of Tensors, if there are more than one inputs.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> # one input
            >>> x = paddle.to_tensor(123, dtype='int32')
            >>> out = paddle.atleast_3d(x)
            >>> print(out)
            Tensor(shape=[1, 1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[[123]]])

            >>> # more than one inputs
            >>> x = paddle.to_tensor(123, dtype='int32')
            >>> y = paddle.to_tensor([1.23], dtype='float32')
            >>> out = paddle.atleast_3d(x, y)
            >>> print(out)
            [Tensor(shape=[1, 1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[[123]]]), Tensor(shape=[1, 1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[[1.23000002]]])]

            >>> # more than 3-D input
            >>> x = paddle.to_tensor(123, dtype='int32')
            >>> y = paddle.to_tensor([[[[1.23]]]], dtype='float32')
            >>> out = paddle.atleast_3d(x, y)
            >>> print(out)
            [Tensor(shape=[1, 1, 1], dtype=int32, place=Place(cpu), stop_gradient=True,
            [[[123]]]), Tensor(shape=[1, 1, 1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[[[1.23000002]]]])]
    r   )r   r   r   r   r   r   r0  r-  r   r   r    
atleast_3dl  s,   *
r2  c                 C   sv   t  r	t| |S t| dg dd t|dddgd tdi t }| }||}|jd| |dd	|id
 |S )a	  

    This function is actually a high-dimensional extension of :code:`gather`
    and supports for simultaneous indexing by multiple axes. :attr:`index` is a
    K-dimensional integer tensor, which is regarded as a (K-1)-dimensional
    tensor of :attr:`index` into :attr:`input`, where each element defines
    a slice of params:

    .. math::

        output[(i_0, ..., i_{K-2})] = input[index[(i_0, ..., i_{K-2})]]

    Obviously, :code:`index.shape[-1] <= input.rank` . And, the output tensor has
    shape :code:`index.shape[:-1] + input.shape[index.shape[-1]:]` .

    .. code-block:: text

            Given:
                x =  [[[ 0,  1,  2,  3],
                       [ 4,  5,  6,  7],
                       [ 8,  9, 10, 11]],
                      [[12, 13, 14, 15],
                       [16, 17, 18, 19],
                       [20, 21, 22, 23]]]
                x.shape = (2, 3, 4)

            * Case 1:
                index = [[1]]

                gather_nd(x, index)
                         = [x[1, :, :]]
                         = [[12, 13, 14, 15],
                            [16, 17, 18, 19],
                            [20, 21, 22, 23]]

            * Case 2:
                index = [[0,2]]

                gather_nd(x, index)
                         = [x[0, 2, :]]
                         = [8, 9, 10, 11]

            * Case 3:
                index = [[1, 2, 3]]

                gather_nd(x, index)
                         = [x[1, 2, 3]]
                         = [23]

    Args:
        x (Tensor): The input Tensor which it's data type should be bool, float16, float32, float64, int32, int64.
        index (Tensor): The index input with rank > 1, index.shape[-1] <= input.rank.
                        Its dtype should be int32, int64.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        output (Tensor), A tensor with the shape index.shape[:-1] + input.shape[index.shape[-1]:]

    Examples:

        .. code-block:: python

            >>> import paddle

            >>> x = paddle.to_tensor([[[1, 2], [3, 4], [5, 6]],
            ...                       [[7, 8], [9, 10], [11, 12]]])
            >>> index = paddle.to_tensor([[0, 1]])

            >>> output = paddle.gather_nd(x, index)
            >>> print(output)
            Tensor(shape=[1, 2], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[3, 4]])

    r   )rJ   rK   rQ   rL   rM   rN   r(   rO   Z	gather_npr   r(   rO   	gather_ndr   r+   r
  N)r3  )	r   r   r3  r   r   r>   r@   r?   rA   )r   r   rB   rG   r'   r  r   r   r    r3    s(   K

r3  c                    s  t  rt| ||||S tdi t  t| dg dd t|dttfd t|dttt	fd t|dttt	fd t|dttt	fd dd	 }||d ||d ||d ||d  fd
d}d| i}d|i}	dd t
t|D }
t|t	rd|_||d< n=t|ttfrg |	d< tj|r|||d< t|D ]\}}t|t	r|	d d d|
|< q|	d | qn||	d< t|t	rd|_||d< n?t|ttfrg |	d< tj|r|||d< t|D ]\}}t|t	r|	d d d|
|< q|	d | qn||	d< t|t	rd|_||d< nBt|ttfr[g |	d< tj|rW|||d< t|D ]\}}t|t	rM|	d d d|
|< q6|	d | q6n||	d< |
|	d<  j dd} jd||	d|id |S )a5  
    This operator produces a slice of ``x`` along multiple axes. Similar to numpy:
    https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
    Slice uses ``axes``, ``starts`` and ``ends`` attributes to specify the start and
    end dimension for each axis in the list of axes and Slice uses this information
    to slice the input data tensor. If a negative value is passed to
    ``starts`` or ``ends`` such as :math:`-i`,  it represents the reverse position of the
    axis :math:`i-1` th(here 0 is the initial position). The ``strides`` represents steps of
    slicing and if the ``strides`` is negative, slice operation is in the opposite direction.
    If the value passed to ``starts`` or ``ends`` is greater than n
    (the number of elements in this dimension), it represents n.
    For slicing to the end of a dimension with unknown size, it is recommended
    to pass in INT_MAX. The size of ``axes`` must be equal to ``starts`` , ``ends`` and ``strides``.
    Following examples will explain how strided_slice works:

    .. code-block:: text

        Case1:
            Given:
                data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
                axes = [0, 1]
                starts = [1, 0]
                ends = [2, 3]
                strides = [1, 1]
            Then:
                result = [ [5, 6, 7], ]

        Case2:
            Given:
                data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
                axes = [0, 1]
                starts = [0, 1]
                ends = [2, 0]
                strides = [1, -1]
            Then:
                result = [ [8, 7, 6], ]
        Case3:
            Given:
                data = [ [1, 2, 3, 4], [5, 6, 7, 8], ]
                axes = [0, 1]
                starts = [0, 1]
                ends = [-1, 1000]
                strides = [1, 3]
            Then:
                result = [ [2], ]

    Args:
        x (Tensor): An N-D ``Tensor``. The data type is ``bool``, ``float16``, ``float32``, ``float64``, ``int32`` or ``int64``.
        axes (list|tuple): The data type is ``int32`` . Axes that `starts` and `ends` apply to.
                            It's optional. If it is not provides, it will be treated as :math:`[0,1,...,len(starts)-1]`.
        starts (list|tuple|Tensor): The data type is ``int32`` . If ``starts`` is a list or tuple, the elements of it should be
            integers or Tensors with shape []. If ``starts`` is an Tensor, it should be an 1-D Tensor.
            It represents starting indices of corresponding axis in ``axes``.
        ends (list|tuple|Tensor): The data type is ``int32`` . If ``ends`` is a list or tuple, the elements of it should be
            integers or Tensors with shape []. If ``ends`` is an Tensor, it should be an 1-D Tensor.
            It represents ending indices of corresponding axis in ``axes``.
        strides (list|tuple|Tensor): The data type is ``int32`` . If ``strides`` is a list or tuple, the elements of it should be
            integers or Tensors with shape []. If ``strides`` is an Tensor, it should be an 1-D Tensor.
            It represents slice step of corresponding axis in ``axes``.
        name(str, optional): The default value is None.  Normally there is no need for user to set this property.
                        For more information, please refer to :ref:`api_guide_Name` .

    Returns:
        Tensor, A ``Tensor`` with the same dimension as ``x``. The data type is same as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> x = paddle.zeros(shape=[3,4,5,6], dtype="float32")
            >>> # example 1:
            >>> # attr starts is a list which doesn't contain Tensor.
            >>> axes = [1, 2, 3]
            >>> starts = [-3, 0, 2]
            >>> ends = [3, 2, 4]
            >>> strides_1 = [1, 1, 1]
            >>> strides_2 = [1, 1, 2]
            >>> sliced_1 = paddle.strided_slice(x, axes=axes, starts=starts, ends=ends, strides=strides_1)
            >>> # sliced_1 is x[:, 1:3:1, 0:2:1, 2:4:1].
            >>> # example 2:
            >>> # attr starts is a list which contain tensor Tensor.
            >>> minus_3 = paddle.full(shape=[1], fill_value=-3, dtype='int32')
            >>> sliced_2 = paddle.strided_slice(x, axes=axes, starts=[minus_3, 0, 2], ends=ends, strides=strides_2)
            >>> # sliced_2 is x[:, 1:3:1, 0:2:1, 2:4:2].
    strided_slicer   r  ri   rk   rn   stridesc                 S   sh   t | trt| j|ddgd d S t| D ]\}}|d t| d }t |tr1t|j|dgd qd S )Nr(   rO   r4  [r%   )r3   r
   r   r'   r;   r<   )Z
list_inputZ
input_namerF   varvar_namer   r   r    check_list_elements_dtype  s   

z0strided_slice.<locals>.check_list_elements_dtypec                    sd   g }| D ]+}t |trd|_|| qt |tsJ  d}tdgd|d|d || q|S )NTr(   r   r   )r3   r
   rU   r}   r   r?   r   )Zold_listZnew_list_tensorr~   r   r   r   r    get_new_list_tensor  s   
z*strided_slice.<locals>.get_new_list_tensorrh   c                 S   rY   rZ   r   r[   r   r   r    r!     r\   z!strided_slice.<locals>.<listcomp>Trj   rl   rf   rm   ro   ZStridesTensorZStridesTensorListrp   r&   r+   rq   N)r4  )r   r   r4  r   r>   r   r   r4   rr   r
   ru   rs   r3   rU   r5   ry   rz   r;   r}   r?   r@   rA   )r   ri   rk   rn   r5  rB   r9  r:  r0   r2   rp   rF   r~   rH   r   r   r    r4    s   V	












r4  c                    sZ  d g d}t | d|  t |d|  t|dttttf   fdd}g }g }tt|tj	rP|dksBJ d	  d
| d t
| j| | j}t
|}n9t|trY||}|rftt|d tj	ri|}n |d }t|dkrw|d }t|tr||}t|tr||}t|t|}}t|t|}}	||	k r|||d  n|	|k r|||	d  t| jt|j}
}tj| jtd}tj|jtd}d}t
t|D ]_}|| || }}|
| || }}|dkrd||< |||}n,|dkrd|
|< | ||
} n||ks*J d  d| d| d| d| d	 d||< d||< ||
| 9 }qg }g }g }d}d}t
| jD ]}|| sa|| ||
|  ||
| 9 }qH|| || t
|jD ]}|| s|| |||  ||| 9 }qr| j|d||g} |j|d||g}| ||}|S )a  
    This function computes a contraction, which sum the product of elements from two tensors along the given axes.

    Args:
        x (Tensor): The left tensor for contraction with data type ``float16`` or ``float32`` or ``float64``.
        y (Tensor): The right tensor for contraction with the same data type as ``x``.
        axes (int|tuple|list|Tensor, optional):  The axes to contract for ``x`` and ``y``, defaulted to integer ``2``.

            1. It could be a non-negative integer ``n``,
               in which the function will sum over the last ``n`` axes of ``x`` and the first ``n`` axes of ``y`` in order.

            2. It could be a 1-d tuple or list with data type ``int``, in which ``x`` and ``y`` will be contracted along the same given axes.
               For example, ``axes`` =[0, 1] applies contraction along the first two axes for ``x`` and the first two axes for ``y``.

            3. It could be a tuple or list containing one or two 1-d tuple|list|Tensor with data type ``int``.
               When containing one tuple|list|Tensor, the data in tuple|list|Tensor specified the same axes for ``x`` and ``y`` to contract.
               When containing two tuple|list|Tensor, the first will be applied to ``x`` and the second to ``y``.
               When containing more than two tuple|list|Tensor, only the first two axis sequences will be used while the others will be ignored.

            4. It could be a tensor, in which the ``axes`` tensor will be translated to a python list
               and applied the same rules described above to determine the contraction axes.
               Note that the ``axes`` with Tensor type is ONLY available in Dygraph mode.
        name(str, optional): The default value is None.  Normally there is no need for user to set this property.
                             For more information, please refer to :ref:`api_guide_Name` .

    Return:
        Output (Tensor), The contraction result with the same data type as ``x`` and ``y``.
        In general, :math:`output.ndim = x.ndim + y.ndim - 2 \times n_{axes}`, where :math:`n_{axes}` denotes the number of axes to be contracted.

    NOTES:
        1. This function supports tensor broadcast,
           the size in the corresponding dimensions of ``x`` and ``y`` should be equal, or applies to the broadcast rules.
        2. This function also supports axes expansion,
           when the two given axis sequences for ``x`` and ``y`` are of different lengths,
           the shorter sequence will expand the same axes as the longer one at the end.
           For example, if ``axes`` =[[0, 1, 2, 3], [1, 0]],
           the axis sequence for ``x`` is [0, 1, 2, 3],
           while the corresponding axis sequences for ``y`` will be expanded from [1, 0] to [1, 0, 2, 3].

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> data_type = 'float64'

            >>> # For two 2-d tensor x and y, the case axes=0 is equivalent to outer product.
            >>> # Note that tensordot supports empty axis sequence, so all the axes=0, axes=[], axes=[[]], and axes=[[],[]] are equivalent cases.
            >>> x = paddle.arange(4, dtype=data_type).reshape([2, 2])
            >>> y = paddle.arange(4, dtype=data_type).reshape([2, 2])
            >>> z = paddle.tensordot(x, y, axes=0)
            >>> print(z)
            Tensor(shape=[2, 2, 2, 2], dtype=float64, place=Place(cpu), stop_gradient=True,
             [[[[0., 0.],
                [0., 0.]],
               [[0., 1.],
                [2., 3.]]],
              [[[0., 2.],
                [4., 6.]],
               [[0., 3.],
                [6., 9.]]]])

            >>> # For two 1-d tensor x and y, the case axes=1 is equivalent to inner product.
            >>> x = paddle.arange(10, dtype=data_type)
            >>> y = paddle.arange(10, dtype=data_type)
            >>> z1 = paddle.tensordot(x, y, axes=1)
            >>> z2 = paddle.dot(x, y)
            >>> print(z1)
            Tensor(shape=[], dtype=float64, place=Place(cpu), stop_gradient=True,
            285.)
            >>> print(z2)
            Tensor(shape=[], dtype=float64, place=Place(cpu), stop_gradient=True,
            285.)


            >>> # For two 2-d tensor x and y, the case axes=1 is equivalent to matrix multiplication.
            >>> x = paddle.arange(6, dtype=data_type).reshape([2, 3])
            >>> y = paddle.arange(12, dtype=data_type).reshape([3, 4])
            >>> z1 = paddle.tensordot(x, y, axes=1)
            >>> z2 = paddle.matmul(x, y)
            >>> print(z1)
            Tensor(shape=[2, 4], dtype=float64, place=Place(cpu), stop_gradient=True,
            [[20., 23., 26., 29.],
             [56., 68., 80., 92.]])
            >>> print(z2)
            Tensor(shape=[2, 4], dtype=float64, place=Place(cpu), stop_gradient=True,
            [[20., 23., 26., 29.],
             [56., 68., 80., 92.]])

            >>> # When axes is a 1-d int list, x and y will be contracted along the same given axes.
            >>> # Note that axes=[1, 2] is equivalent to axes=[[1, 2]], axes=[[1, 2], []], axes=[[1, 2], [1]], and axes=[[1, 2], [1, 2]].
            >>> x = paddle.arange(24, dtype=data_type).reshape([2, 3, 4])
            >>> y = paddle.arange(36, dtype=data_type).reshape([3, 3, 4])
            >>> z = paddle.tensordot(x, y, axes=[1, 2])
            >>> print(z)
            Tensor(shape=[2, 3], dtype=float64, place=Place(cpu), stop_gradient=True,
            [[506. , 1298., 2090.],
             [1298., 3818., 6338.]])

            >>> # When axes is a list containing two 1-d int list, the first will be applied to x and the second to y.
            >>> x = paddle.arange(60, dtype=data_type).reshape([3, 4, 5])
            >>> y = paddle.arange(24, dtype=data_type).reshape([4, 3, 2])
            >>> z = paddle.tensordot(x, y, axes=([1, 0], [0, 1]))
            >>> print(z)
            Tensor(shape=[5, 2], dtype=float64, place=Place(cpu), stop_gradient=True,
            [[4400., 4730.],
             [4532., 4874.],
             [4664., 5018.],
             [4796., 5162.],
             [4928., 5306.]])

            >>> # Thanks to the support of axes expansion, axes=[[0, 1, 3, 4], [1, 0, 3, 4]] can be abbreviated as axes= [[0, 1, 3, 4], [1, 0]].
            >>> x = paddle.arange(720, dtype=data_type).reshape([2, 3, 4, 5, 6])
            >>> y = paddle.arange(720, dtype=data_type).reshape([3, 2, 4, 5, 6])
            >>> z = paddle.tensordot(x, y, axes=[[0, 1, 3, 4], [1, 0]])
            >>> print(z)
            Tensor(shape=[4, 4], dtype=float64, place=Place(cpu), stop_gradient=True,
            [[23217330., 24915630., 26613930., 28312230.],
             [24915630., 26775930., 28636230., 30496530.],
             [26613930., 28636230., 30658530., 32680830.],
             [28312230., 30496530., 32680830., 34865130.]])
    	tensordot)rK   rL   rM   r   r   ri   c                    s   t  rt| S td  d )Nz!The 'axes' with type 'Tensor' in zm is not available in static graph mode, please convert its type to int|Tuple|List, or use dynamic graph mode.)r   r   r=   )r7  r   r   r    _var_to_listx  s   ztensordot.<locals>._var_to_listr   zThe 'axes' in z+ should not be negative, but received axes=r   r   Nr&   z(The dimensional size for 'x' and 'y' in z+ should match each other, but 'x' has size z in dim z while 'y' has size T)r   )r   r   r   rr   r4   r
   r7   Z
issubdtyper/   integerru   r   r3   rs   extendr   r   rJ   sumr   r}   r   matmul)r   r   ri   rB   r@   r=  Zaxes_xZaxes_yZ
len_axes_xZ
len_axes_yZshape_xZshape_yZneed_contracted_dim_xZneed_contracted_dim_yZcontraction_sizerF   Zdim_xZdim_ysxZsyZperm_xZperm_yZ	shape_outZnot_contraction_size_xZnot_contraction_size_yrH   r   r<  r    r;    s   {













r;  c                 C   st   t  rt| S t| dddgd d}t|fi t }d| i}|jt| jd}d|i}i }|j	||||d |S )	a  Transform a real tensor to a complex tensor.

    The data type of the input tensor is 'float32' or 'float64', and the data
    type of the returned tensor is 'complex64' or 'complex128', respectively.

    The shape of the input tensor is ``(* ,2)``, (``*`` means arbitary shape), i.e.
    the size of the last axis shoule be 2, which represent the real and imag part
    of a complex number. The shape of the returned tensor is ``(*,)``.

    Args:
        x (Tensor): The input tensor. Data type is 'float32' or 'float64'.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, The output. Data type is 'complex64' or 'complex128', with the same precision as the input.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> x = paddle.arange(12, dtype=paddle.float32).reshape([2, 3, 2])
            >>> y = paddle.as_complex(x)
            >>> print(y)
            Tensor(shape=[2, 3], dtype=complex64, place=Place(cpu), stop_gradient=True,
            [[1j      , (2+3j)  , (4+5j)  ],
             [(6+7j)  , (8+9j)  , (10+11j)]])
    r   rL   rM   
as_complexr)   r&   r+   rq   )
r   r   rC  r   r   r>   r?   r   r'   rA   )r   rB   r   rG   r0   rH   r1   r2   r   r   r    rC    s   
rC  c                 C   sn   t  rt| S t| dddgd d}t|fi t }d| i}|jt| jd}d|i}|j	|||d |S )	a  Transform a complex tensor to a real tensor.

    The data type of the input tensor is 'complex64' or 'complex128', and the data
    type of the returned tensor is 'float32' or 'float64', respectively.

    When the shape of the input tensor is ``(*, )``, (``*`` means arbitary shape),
    the shape of the output tensor is ``(*, 2)``, i.e. the shape of the output is
    the shape of the input appended by an extra ``2``.

    Args:
        x (Tensor): The input tensor. Data type is 'complex64' or 'complex128'.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, The output. Data type is 'float32' or 'float64', with the same precision as the input.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> x = paddle.arange(12, dtype=paddle.float32).reshape([2, 3, 2])
            >>> y = paddle.as_complex(x)
            >>> z = paddle.as_real(y)
            >>> print(z)
            Tensor(shape=[2, 3, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[[0. , 1. ],
             [2. , 3. ],
             [4. , 5. ]],
            [[6. , 7. ],
             [8. , 9. ],
             [10., 11.]]])
    r   r   r   as_realr)   r&   r+   r
  )
r   r   rD  r   r   r>   r?   r   r'   rA   )r   rB   r   rG   r0   rH   r1   r   r   r    rD    s   !
rD  c                 C   s   t |ttjjfr|jst|dg}|du rt| } d}t r8t |ttjjfr1t	
| ||S t	| ||S tdi t }t| dg dd || j}|jd| t |trZ|nddd	|i|t |trh|ndd
d |S )a  

    Returns a new tensor which repeats the ``x`` tensor along dimension ``axis`` using
    the entries in ``repeats`` which is a int or a Tensor.

    Args:
        x (Tensor): The input Tensor to be operated. The data of ``x`` can be one of float32, float64, int32, int64.
        repeats (Tensor or int): The number of repetitions for each element. repeats is broadcasted to fit the shape of the given axis.
        axis (int, optional): The dimension in which we manipulate. Default: None, the output tensor is flatten.
        name(str, optional): The default value is None. Normally there is no
            need for user to set this property. For more information, please
            refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, A Tensor with same data type as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.to_tensor([[1, 2, 3], [4, 5, 6]])
            >>> repeats = paddle.to_tensor([3, 2, 1], dtype='int32')

            >>> out = paddle.repeat_interleave(x, repeats, 1)
            >>> print(out)
            Tensor(shape=[2, 6], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[1, 1, 1, 2, 2, 3],
             [4, 4, 4, 5, 5, 6]])

            >>> out = paddle.repeat_interleave(x, 2, 0)
            >>> print(out)
            Tensor(shape=[4, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[1, 2, 3],
             [1, 2, 3],
             [4, 5, 6],
             [4, 5, 6]])

            >>> out = paddle.repeat_interleave(x, 2, None)
            >>> print(out)
            Tensor(shape=[12], dtype=int64, place=Place(cpu), stop_gradient=True,
            [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6])
    r   Nr   repeat_interleaver   r   z,paddle.tensor.manipulation.repeat_interleave)r)   ZRepeatsTensorr+   )r~   ZRepeatsr.   )rE  )r3   r
   r5   r9   r   r   r   r   r   r   Z#repeat_interleave_with_tensor_indexrE  r   r>   r   r?   r'   rA   r   )r   Zrepeatsr   rB   rG   rH   r   r   r    rE  5  s8   ,
rE  c                 C   s|  t |tr|gn|}t |tr|gn|}t|t|ks J dt|tt|kr.tdt|tt|kr<tdt| j}tt|}tt|}tt|}	tt	||D ]\}
}t |d tsiJ d|d dk r|d | ksJ d| d| d||
  |7  < n|d |k sJ d| d| dt |d	 tsJ d|d	 dk r|d	 | ksJ d| d| d||
  |7  < n|d	 |k sJ d| d| d||
 |||
 < |
||
  |	
||
  qZtt|D ]
}
||
 ||	|
 < qt rt| |}|S t| d
g dd tdi t }|| j}|| j}|jdd| gi|g|gdd|id |S )a  
    Move the axis of tensor from ``source`` position to ``destination`` position.

    Other axis that have not been moved remain their original order.

    Args:
        x (Tensor): The input Tensor. It is a N-D Tensor of data types bool, int32, int64, float32, float64, complex64, complex128.
        source(int|tuple|list): ``source`` position of axis that will be moved. Each element must be unique and integer.
        destination(int|tuple|list(int)): ``destination`` position of axis that has been moved. Each element must be unique and integer.
        name(str, optional): The default value is None.  Normally there is no need for user to set this
            property. For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, A new tensor whose axis have been moved.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.ones([3, 2, 4])
            >>> outshape = paddle.moveaxis(x, [0, 1], [1, 2]).shape
            >>> print(outshape)
            [4, 3, 2]

            >>> x = paddle.ones([2, 3])
            >>> outshape = paddle.moveaxis(x, 0, 1).shape # equivalent to paddle.t(x)
            >>> print(outshape)
            [3, 2]
    z5'source' must have the same number with 'destination'z)Each elemment of 'source' must be unique!z.Each elemment of 'destination' must be unique!r   z*Each elemment of 'source' must be integer.z#'source' must be in the range of [-r   r   r   r   )rJ   rK   rL   rM   r(   rO   r   r   moveaxisr   r)   r   r   r.   N)rF  )r3   r   rs   setrt   r   r4   ru   r;   zipremover   r   r   r   r   r>   r?   r'   rA   )r   sourceZdestinationrB   srcdstr   r   Zsrc_dimsZdst_dimsrF   r   rH   rG   r   r   r   r    rF    s   

rF  c                 C   6   t |rtg || j}t|}t|| |}|S )a  
    Fills elements of self tensor with value where mask is True. The shape of mask must be broadcastable with the shape of the underlying tensor.

    Args:
        x (Tensor) : The Destination Tensor. Supported data types are float,
            double, int, int64_t,float16 and bfloat16.
        mask (Tensor): The boolean tensor indicate the position to be filled.
            The data type of mask must be bool.
        value (Scalar or 0-D Tensor): The value used to fill the target tensor.
            Supported data types are float, double, int, int64_t,float16 and bfloat16.
        name(str, optional): The default value is None. Normally there is no
            need for user to set this property. For more information, please
            refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, same dimention and dtype with x.
    Examples:
        .. code-block:: python

            >>> # doctest: +REQUIRES(env:GPU)
            >>> import paddle
            >>> x = paddle.ones((3, 3), dtype="float32")
            >>> mask = paddle.to_tensor([[True, True, False]])
            >>> print(mask)
            Tensor(shape=[1, 3], dtype=bool, place=Place(gpu:0), stop_gradient=True,
                   [[True , True , False]])
            >>> out = paddle.masked_fill(x, mask, 2)
            >>> print(out)
            Tensor(shape=[3, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
                   [[2., 2., 1.],
                    [2., 2., 1.],
                    [2., 2., 1.]])
    )r7   isscalarr5   fullr'   logical_notwherer   maskr   rB   rH   r   r   r    masked_fill  s
   
"
rT  c                 C   rM  )a  
    Inplace version of ``masked_fill`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_masked_fill`.

    Examples:
        .. code-block:: python

            >>> # doctest: +REQUIRES(env:GPU)
            >>> import paddle
            >>> x = paddle.ones((3, 3), dtype="float32")
            >>> mask = paddle.to_tensor([[True, False, False]])
            >>> out = paddle.masked_fill_(x, mask, 2)
            >>> print(out)
            Tensor(shape=[3, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
                   [[2., 1., 1.],
                    [2., 1., 1.],
                    [2., 1., 1.]])
    )r7   rN  r5   rO  r'   rP  Zwhere_rR  r   r   r    masked_fill_!  s
   

rU  c                 C   s`   t | j}|dkr||k sJ d| d| d|S || ks*J d| d| d||7 }|S )Nr   z"'axis'  must be in the range of [-r   r   )rs   r   )arrr   r   r   r   r    non_negative_axis=  s   
rW  c                 C   sV   t | j}t |j| ||< t|}tt| jD ]}| j| |j| k r( d S q|S N)r4   r   rr   ru   rs   )rV  r   r   broadcast_shape_listbroadcast_shaperF   r   r   r    infer_broadcast_shapeJ  s   
r[  c                 C   sh  t | jt |jkrtdt| |}|r>t| ||}|s |j}t||}t|}t| j| ||< t|}t| |} n7t	t | jD ]}||kra| j| |j| k rat
d||j| j|qE| j| }||k  sut
d||t rt| ||S t| dg dd t|ddd	gd tdi t }| }	||	}
|jd| |d
d|id|
id |
S )a  
    Take values from the input array by given indices matrix along the designated axis.

    Args:
        arr (Tensor) : The input Tensor. Supported data types are float32 and float64.
        indices (Tensor) : Indices to take along each 1d slice of arr. This must match the dimension of arr,
            and need to broadcast against arr. Supported data type are int and int64.
        axis (int) : The axis to take 1d slices along.
        broadcast (bool, optional): whether the indices broadcast.

    Returns:
        Tensor, The indexed element, same dtype with arr

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.to_tensor([[1, 2, 3], [4, 5, 6], [7,8,9]])
            >>> index = paddle.to_tensor([[0]])
            >>> axis = 0
            >>> result = paddle.take_along_axis(x, index, axis)
            >>> print(result)
            Tensor(shape=[1, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[1, 2, 3]])
    <`indices` and `arr` must have the same number of dimensions!zhSize does not match at dimension {} expected index {} to be smaller than self {} apart from dimension {}Hone of element of indices is out of bounds for dimension {} with size {}r   rK   rL   rM   r(   rO   rP   rQ   take_along_axisr   r(   rO   )rh   r   r  Resultrq   N)r_  )rs   r   rt   rW  r[  r5   r  r4   rr   ru   RuntimeErrorr   allr   r   r_  r   r   r>   r@   r?   rA   )rV  r   r   	broadcastrZ  rY  rF   axis_max_sizerG   r'   r.  r   r   r    r_  V  sd   

	
r_  assignc              	   C   s4  t | jt |jkrtdt| |}|r?t| ||}t r/t|tjtj	j
fs-t|n|}|r7t||}t||j}n|t|tjtj	j
frt |jt |jkrWtdtt | jD ](}||krn| j| |j| k sx|j| |j| krtd||j| j||jq^n t|| j}d}	|jD ]}
|	|
9 }	q|	dkrt||j}| j| }||k  std||t rt|jdvrtdtt|jt| |||||S t| dg d	d
 t|dddgd
 t|dtd
 tdi t }| }||}|jd
| ||d|||dd|id |S )aA  
    Put values into the destination array by given indices matrix along the designated axis.

    Args:
        arr (Tensor) : The Destination Tensor. Supported data types are float32 and float64.
        indices (Tensor) : Indices to put along each 1d slice of arr. This must match the dimension of arr,
            and need to broadcast against arr if broadcast is 'True'. Supported data type are int and int64.
        values (Tensor) : The value element(s) to put. The data types should be same as arr.
        axis (int) : The axis to put 1d slices along.
        reduce (str, optional): The reduce operation, default is 'assign', support 'add', 'assign', 'mul', 'multiply', "mean", "amin" and "amax".
        include_self (bool, optional): whether to reduce with the elements of arr, default is 'True'.
        broadcast (bool, optional): whether to broadcast indices, default is 'True'.

    Returns:
        Tensor, The indexed element, same dtype with arr

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.to_tensor([[10, 30, 20], [60, 40, 50]])
            >>> index = paddle.to_tensor([[0]])
            >>> value = 99
            >>> axis = 0
            >>> result = paddle.put_along_axis(x, index, value, axis)
            >>> print(result)
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[99, 99, 99],
             [60, 40, 50]])

            >>> index = paddle.zeros((2,2)).astype("int32")
            >>> value=paddle.to_tensor([[1,2],[3,4]]).astype(x.dtype)
            >>> result = paddle.put_along_axis(x, index, value, 0, "add", True, False)
            >>> print(result)
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[14, 36, 20],
             [60, 40, 50]])

            >>> result = paddle.put_along_axis(x, index, value, 0, "mul", True, False)
            >>> print(result)
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[30 , 240, 20 ],
             [60 , 40 , 50 ]])

            >>> result = paddle.put_along_axis(x, index, value, 0, "mean", True, False)
            >>> print(result)
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[4 , 12, 20],
             [60, 40, 50]])

            >>> result = paddle.put_along_axis(x, index, value, 0, "amin", True, False)
            >>> print(result)
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[1 , 2 , 20],
             [60, 40, 50]])

            >>> result = paddle.put_along_axis(x, index, value, 0, "amax", True, False)
            >>> print(result)
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[10, 30, 20],
             [60, 40, 50]])

            >>> result = paddle.put_along_axis(x, index, value, 0, "add", False, False)
            >>> print(result)
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[4 , 6 , 20],
             [60, 40, 50]])

    r\  z?`indices` and `values` must have the same number of dimensions!zSize does not match at dimension {} expected index {} to be smaller than self {} apart from dimension {} and to be smaller size than values {}r   r]  )r(   rO   zHThe data type of indices should be one of ['int32', 'int64'], but got {}r   r^  put_along_axisr   r(   rO   include_self)rh   r   r   )r  ZReduceZInclude_selfr`  rq   N)rf  ) rs   r   rt   rW  r[  r   r3   r5   ra   r9   r:   r6   r  ru   ra  r   astyper'   rb  r	   r=   r<   r   rf  r   r   rJ   r   r>   r@   r?   rA   )rV  r   valuesr   reducerg  rc  rZ  rF   elementsr   rd  rG   r'   r.  r   r   r    rf    s   O




	


rf  c                 C   s~   t | jt |jkrtdt| |}t| ||}t|tjs$t|n|}|r.t	||}t	||j}t
| |||||S )z
    Inplace version of ``put_along_axis`` API, the output Tensor will be inplaced with input ``arr``.
    Please refer to :ref:`api_paddle_put_along_axis`.
    r\  )rs   r   rt   rW  r[  r3   r5   ra   r6   r  r   put_along_axis_)rV  r   ri  r   rj  rg  rZ  r   r   r    rl  Y  s    

rl  c                 C   s   t  rt| |||S tdi t }t| dg dd t|dddgd t|dg dd || j}|jd| ||d	d
|id|id |S )as  
    Adds the elements of the input tensor with value tensor by selecting the indices in the order given in index.

    Args:
        x (Tensor) : The Destination Tensor. Supported data types are int32, int64, float16, float32, float64.
        index (Tensor): The 1-D Tensor containing the indices to index.
            The data type of ``index`` must be int32 or int64.
        axis (int): The dimension in which we index.
        value (Tensor): The tensor used to add the elements along the target axis.
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.

    Returns:
        Tensor, same dimention and dtype with x.

    Examples:
        .. code-block:: python

            >>> # doctest: +REQUIRES(env:GPU)
            >>> import paddle
            >>> paddle.device.set_device('gpu')

            >>> input_tensor = paddle.to_tensor(paddle.ones((3, 3)), dtype="float32")
            >>> index = paddle.to_tensor([0, 2], dtype="int32")
            >>> value = paddle.to_tensor([[1, 1, 1], [1, 1, 1]], dtype="float32")
            >>> outplace_res = paddle.index_add(input_tensor, index, 0, value)
            >>> print(outplace_res)
            Tensor(shape=[3, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
            [[2., 2., 2.],
             [1., 1., 1.],
             [2., 2., 2.]])
    	index_addr   r   z$paddle.tensor.manipulation.index_addr   r(   rO   Z	add_value)r)   r   ZAddValuer+   r   r.   N)rm  )	r   r   rm  r   r>   r   r?   r'   rA   )r   r   r   r   rB   rG   rH   r   r   r    rm  t  s@    
rm  c                 C   s   t | |||S )aG  
    Inplace version of ``index_add`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_index_add`.

    Examples:
        .. code-block:: python

            >>> # doctest: +REQUIRES(env:GPU)
            >>> import paddle
            >>> paddle.device.set_device('gpu')

            >>> input_tensor = paddle.to_tensor(paddle.ones((3, 3)), dtype="float32")
            >>> index = paddle.to_tensor([0, 2], dtype="int32")
            >>> value = paddle.to_tensor([[1, 1], [1, 1], [1, 1]], dtype="float32")
            >>> inplace_res = paddle.index_add_(input_tensor, index, 1, value)
            >>> print(inplace_res)
            Tensor(shape=[3, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
            [[2., 1., 2.],
             [2., 1., 2.],
             [2., 1., 2.]])
    )r   
index_add_r   r   r   r   rB   r   r   r    rn    s   rn  c                 C   r  )a  
    Puts values from the tensor values into the tensor x using the indices specified in indices (which is a tuple of Tensors).
    The expression paddle.index_put_(x, indices, values) is equivalent to tensor[indices] = values. Returns x.
    If accumulate is True, the elements in values are added to x. If accumulate is False, the behavior is undefined if indices contain duplicate elements.

    Args:
        x (Tensor) : The Source Tensor. Supported data types are int32, int64, float16, float32, float64, bool.
        indices (Tuple of Tensor): The tuple of Tensor containing the indices to index.
            The data type of ``tensor in indices`` must be int32, int64 or bool.
        value (Tensor): The tensor used to be assigned to x.
        accummulate (Bool, optional): Whether the elements in values are added to x. Default: False.
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.

    Returns:
        Tensor, same dimention and dtype with x.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.zeros([3, 3])
            >>> value = paddle.ones([3])
            >>> ix1 = paddle.to_tensor([0,1,2])
            >>> ix2 = paddle.to_tensor([1,2,1])
            >>> indices=(ix1,ix2)

            >>> out = paddle.index_put_(x,indices,value)
            >>> print(x)
            Tensor(shape=[3, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[0., 1., 0.],
             [0., 0., 1.],
             [0., 1., 0.]])
            >>> print(out)
            Tensor(shape=[3, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[0., 1., 0.],
             [0., 0., 1.],
             [0., 1., 0.]])
    )r   
index_put_)r   r   r   
accumulaterB   r   r   r    rp    s   )rp  c                 C   s|   t  rt| |||S tdi t }t| dg dd t|dg dd || j}|jd| ||dd|id|id	 |S )av  
    Outplace version of ``index_put_`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_index_put`.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.zeros([3, 3])
            >>> value = paddle.ones([3])
            >>> ix1 = paddle.to_tensor([0,1,2])
            >>> ix2 = paddle.to_tensor([1,2,1])
            >>> indices=(ix1,ix2)

            >>> out = paddle.index_put(x,indices,value)
            >>> print(x)
            Tensor(shape=[3, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[0., 0., 0.],
             [0., 0., 0.],
             [0., 0., 0.]])
            >>> print(out)
            Tensor(shape=[3, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[0., 1., 0.],
             [0., 0., 1.],
             [0., 1., 0.]])
    	index_putr   r   z$paddle.tensor.manipulation.index_putr   )r   r   r   rH   rq  r.   N)rr  )	r   r   rr  r   r>   r   r?   r'   rA   )r   r   r   rq  rB   rG   rH   r   r   r    rr     s4   
rr  c                 C   s   t | |}t|ttfr%t| jd| t| t| j|d d  }n/t|ttjjfrKt	t| d| t
|dt| |d d g}n	tdt|| |} | S )a  
    Expand a certain dimension of the input x Tensor into a desired shape.

    Args:
        x (Tensor) : An N-D Tensor. The data type is float16, float32, float64, int16, int32, int64, bool, uint16.
        axis (int): :attr:`axis` to be unflattened, specified as an index into `x.shape`.
        shape (list|tuple|Tensor): Unflatten :attr:`shape` on the specified :attr:`axis`. At most one dimension of the target :attr:`shape` can be -1.
            If the input :attr:`shape` does not contain -1 , the product of all elements in ``shape`` should be equal to ``x.shape[axis]``.
            The data type is `int` . If :attr:`shape` is a list or tuple, the elements of it should be integers or Tensors with shape [].
            If :attr:`shape` is an Tensor, it should be an 1-D Tensor.
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.

    Returns:
        Tensor, return the unflatten tensor of :attr:`x`.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.randn(shape=[4, 6, 8])
            >>> shape = [2, 3]
            >>> axis = 1
            >>> res = paddle.unflatten(x, axis, shape)
            >>> print(res.shape)
            [4, 2, 3, 8]

            >>> x = paddle.randn(shape=[4, 6, 8])
            >>> shape = (-1, 2)
            >>> axis = -1
            >>> res = paddle.unflatten(x, axis, shape)
            >>> print(res.shape)
            [4, 6, 4, 2]

            >>> x = paddle.randn(shape=[4, 6, 8])
            >>> shape = paddle.to_tensor([2, 2])
            >>> axis = 0
            >>> res = paddle.unflatten(x, axis, shape)
            >>> print(res.shape)
            [2, 2, 6, 8]
    Nr   r(   zKThe data type of x should be one of ['List', 'Tuple', 'Tensor'], but got {})rW  r3   r4   rr   r   r
   r5   r9   r   r   rR   r=   r   r/   r   )r   r   r   rB   r'  r   r   r    	unflatten<  s$   
,.

rs  c                 C   r  )a  
    View x with specified shape, stride and offset.

    Note that the output Tensor will share data with origin Tensor and doesn't
    have a Tensor copy in ``dygraph`` mode.

    Args:
        x (Tensor): An N-D Tensor. The data type is ``float32``, ``float64``, ``int32``, ``int64`` or ``bool``
        shape (list|tuple): Define the target shape. Each element of it should be integer.
        stride (list|tuple): Define the target stride. Each element of it should be integer.
        offset (int): Define the target Tensor's offset from x's holder. Default: 0.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, A as_strided Tensor with the same data type as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})

            >>> x = paddle.rand([2, 4, 6], dtype="float32")

            >>> out = paddle.as_strided(x, [8, 6], [6, 1])
            >>> print(out.shape)
            [8, 6]
            >>> # the stride is [6, 1].
    )r   
as_strided)r   r   Zstrider   rB   r   r   r    rt    s   rt  c                 C   s<   t |ttfrt| |S t |tjjst|}t	| |S )a|  
    View x with specified shape or dtype.

    Note that the output Tensor will share data with origin Tensor and doesn't
    have a Tensor copy in ``dygraph`` mode.

    Args:
        x (Tensor): An N-D Tensor. The data type is ``float32``, ``float64``, ``int32``, ``int64`` or ``bool``
        shape_or_dtype (list|tuple|np.dtype|str|VarType): Define the target shape or dtype. If list or tuple, shape_or_dtype represents shape, each element of it should be integer. If np.dtype or str or VarType, shape_or_dtype represents dtype, it can be bool, float16, float32, float64, int8, int32, int64, uint8.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, A viewed Tensor with the same data as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})

            >>> x = paddle.rand([2, 4, 6], dtype="float32")

            >>> out = paddle.view(x, [8, 6])
            >>> print(out.shape)
            [8, 6]

            >>> import paddle
            >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})

            >>> x = paddle.rand([2, 4, 6], dtype="float32")

            >>> out = paddle.view(x, "uint8")
            >>> print(out.shape)
            [2, 4, 24]

    )
r3   r4   rr   r   
view_shaper   rV   rW   r   Z
view_dtype)r   Zshape_or_dtyperB   r   r   r    view  s
   &rv  c                 C   s   t | |jS )a  
    View x with other's shape.

    Note that the output Tensor will share data with origin Tensor and doesn't
    have a Tensor copy in ``dygraph`` mode.

    Args:
        x (Tensor): An N-D Tensor. The data type is ``float32``, ``float64``, ``int32``, ``int64`` or ``bool``
        other (Tensor): The result tensor has the same size as other.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, A viewed Tensor with the same shape as ``other``.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})

            >>> x = paddle.rand([2, 4, 6], dtype="float32")
            >>> y = paddle.rand([8, 6], dtype="float32")

            >>> out = paddle.view_as(x, y)
            >>> print(out.shape)
            [8, 6]
    )r   ru  r   )r   otherrB   r   r   r    view_as  s   rx  c                 C   r  )a  
    View x with specified shape, stride and offset, which contains all slices of size from x in the dimension axis.

    Note that the output Tensor will share data with origin Tensor and doesn't
    have a Tensor copy in ``dygraph`` mode.

    Args:
        x (Tensor): An N-D Tensor. The data type is ``float32``, ``float64``, ``int32``, ``int64`` or ``bool``
        axis (int): The axis along which the input is unfolded.
        size (int): The size of each slice that is unfolded.
        step (int): The step between each slice.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, A unfold Tensor with the same data type as ``x``.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> paddle.base.set_flags({"FLAGS_use_stride_kernel": True})

            >>> x = paddle.arange(9, dtype="float64")

            >>> out = paddle.unfold(x, 0, 2, 4)
            >>> print(out)
            Tensor(shape=[2, 2], dtype=float64, place=Place(cpu), stop_gradient=True,
            [[0., 1.],
             [4., 5.]])
    )r   Ztensor_unfold)r   r   sizesteprB   r   r   r    unfold  s    r{  )r   r   r   r   r   r   c                 C   s   t |ts	tdt |tstj|| jd}nt|jdkr"tdt| j}t |tr7||d ks7|| k r;td|dk rC|| }t	t
t| j}||d< d||< |rft| | t| |f| | S t| |}t||f|}t||}|S )Nzindex must be Tensorr&   r   z"value must be scalar or 0-D tensorr   z8The axis should be int, and in range [-rank(x), rank(x)))r3   r
   rt   r5   r6   r'   rs   r   r   r4   ru   r   rp  rr  )r   r   r   r   r   r   r   rH   r   r   r    _index_fill_impl   s0   


 r|  c                 C      t | |||dS )a  
    Outplace version of ``index_fill_`` API, the output Tensor will be inplaced with input ``x``.
    Please refer to :ref:`api_paddle_index_fill_`.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> input_tensor = paddle.to_tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype='int64')
            >>> index = paddle.to_tensor([0, 2], dtype="int32")
            >>> value = -1
            >>> res = paddle.index_fill(input_tensor, index, 0, value)
            >>> print(input_tensor)
            Tensor(shape=[3, 3], dtype=int64, place=Place(gpu:0), stop_gradient=True,
                   [[1, 2, 3],
                    [4, 5, 6],
                    [7, 8, 9]])
            >>> print(res)
            Tensor(shape=[3, 3], dtype=int64, place=Place(gpu:0), stop_gradient=True,
                   [[-1, -1, -1],
                    [ 4,  5,  6],
                    [-1, -1, -1]])

    Fr|  ro  r   r   r    
index_fillB  s   r  c                 C   r}  )a  
    Fill the elements of the input tensor with value by the spcific axis and index.

    Args:
        x (Tensor) : The Destination Tensor. Supported data types are int32, int64, float16, float32, float64.
        index (Tensor): The 1-D Tensor containing the indices to index.
            The data type of ``index`` must be int32 or int64.
        axis (int): The dimension along which to index.
        value (float): The tensor used to fill with.
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.

    Returns:
        Tensor, same dimention and dtype with x.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> input_tensor = paddle.to_tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype='int64')
            >>> index = paddle.to_tensor([0, 2], dtype="int32")
            >>> value = -1
            >>> res = paddle.index_fill_(input_tensor, index, 0, value)
            >>> print(input_tensor)
            Tensor(shape=[3, 3], dtype=int64, place=Place(gpu:0), stop_gradient=True,
                   [[-1, -1, -1],
                    [ 4,  5,  6],
                    [-1, -1, -1]])
            >>> print(res)
            Tensor(shape=[3, 3], dtype=int64, place=Place(gpu:0), stop_gradient=True,
                   [[-1, -1, -1],
                    [ 4,  5,  6],
                    [-1, -1, -1]])

    Tr~  ro  r   r   r    index_fill_^  s   $r  c                 C   s   t | |||||S )a,  
    Embed the values of Tensor ``y`` into Tensor ``x`` along the diagonal elements
    of Tensor ``x``, with respect to ``axis1`` and ``axis2``.

    This function returns a tensor with fresh storage.

    The argument ``offset`` controls which diagonal to consider:

    - 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.

    Note:
        ``y`` should have the same shape as :ref:`paddle.diagonal <api_paddle_diagonal>`.

    Args:
        x (Tensor): ``x`` is the original Tensor. Must be at least 2-dimensional.
        y (Tensor): ``y`` is the Tensor to embed into ``x``
        offset (int, optional): which diagonal to consider. Default: 0 (main diagonal).
        axis1 (int, optional): first axis with respect to which to take diagonal. Default: 0.
        axis2 (int, optional): second axis with respect to which to take diagonal. Default: 1.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor, Tensor with diagonal embedeed with ``y``.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> x = paddle.arange(6.0).reshape((2, 3))
            >>> y = paddle.ones((2,))
            >>> out = x.diagonal_scatter(y)
            >>> print(out)
            Tensor(shape=[2, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
                   [[1., 1., 2.],
                    [3., 1., 5.]])

    r   )r   r   r   Zaxis1Zaxis2rB   r   r   r    diagonal_scatter  s   (r  c              
   C   s  | j }|j }t|tst|}|dk r||| 7 }|dk r#|t|7 }||= t|t|kr<tdt| d t| tt|D ]}|| || krZtdt| d t| qBddlm} |g}	|d g}
dg}|g}g }|g}d| i}||	|
|||d}| j	}||d	< |
|}||d
< t rt| ||	|
||||S tdi t }|j| j	d}|  }|jd|d|i|ddid |S )aH  
    Embeds the values of the values tensor into x at the given index of axis.

    Args:
        x (Tensor) : The Destination Tensor. Supported data types are `bool`, `float16`, `float32`, `float64`, `uint8`, `int8`, `int16`, `int32`, `int64`, `bfloat16`, `complex64`, `complex128`.
        values (Tensor) : The tensor to embed into x. Supported data types are `bool`, `float16`, `float32`, `float64`, `uint8`, `int8`, `int16`, `int32`, `int64`, `bfloat16`, `complex64`, `complex128`.
        axis (int) : the dimension to insert the slice into.
        index (int) : the index to select with.
        name (str, optional): Name for the operation (optional, default is None).

    Returns:
        Tensor, same dtype and shape with x

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> x = paddle.zeros((2,3,4)).astype("float32")
            >>> values = paddle.ones((2,4)).astype("float32")
            >>> res = paddle.select_scatter(x,values,1,1)
            >>> print(res)
            Tensor(shape=[2, 3, 4], dtype=float32, place=Place(cpu), stop_gradient=True,
                   [[[0., 0., 0., 0.],
                     [1., 1., 1., 1.],
                     [0., 0., 0., 0.]],
                    [[0., 0., 0., 0.],
                     [1., 1., 1., 1.],
                     [0., 0., 0., 0.]]])

    r   zEexpected values to have a size equal to the slice of x. value size = z slice size = r   )default_main_programr   rh   )ri   rk   rn   stepsdecrease_axes	none_axesr'   ZValueTensorselect_scatterr&   	set_valuer+   )r/   r0   r1   r2   Zinplace_mapN)r  )r   r3   r4   rs   ra  r<   ru   base.frameworkr  r'   rh  r   r   Zset_value_with_tensorr   r>   r?   Zcurrent_blockrA   )r   ri  r   r   rB   r   Zvalue_shaperF   r  rk   rn   r  ri   r  r  r0   r2   r'   rG   r  Z	cur_blockr   r   r    r    s    

	

r  )r   FNrX  )r   Nre   )NNN)r   FN)r   r   r   F)r   r   r   N)r   rf   N)NN)FFNrO   N)FFFNrO   Nr^   )TN)r   N)T)re  TT)re  T)FN)orx   r7   r5   r   Zpaddle.tensorr   Zpaddle.utils.inplace_utilsr   Zbase.data_feederr   r   r   r	   r  r
   r+  r   r   r   r   r   r   r   r   Zcreationr   r   r   __all__r#   rR   rX   rg   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r  r  r  r   r)  r/  r1  r2  r3  r4  r;  rC  rD  rE  rF  rT  rU  rW  r[  r_  rf  rl  rm  rn  rp  rr  rs  rt  rv  rx  r{  Z	__METHODSitemsrB   funcsetattrr`   ra   r|  r  r  r  r  r   r   r   r    <module>   s   (

 L
 
T
c
8
L O
"

 
[
# 

! 

uH
h 
$
f 
 
Y
2 
 	
 
( 

_
S^

V
)
' 

D
r
x NEF
H
k 
X 
b
.
0
O
s*
_
 *
F
+
<D!-$
"
&+