o
    ְi                     @   sf   d dl Z d dlZd dlmZ dd ZdddZedd	d
dZdd ZdddZdddZ	dd Z
dS )    N)_corec                 C   sl   t |}| j|jkrtdt |}|  d }|jdkr#dS |jdkr,td| j||dd dS )a}  Change elements of an array based on conditional and input values.

    This function uses the first N elements of `vals`, where N is the number
    of true values in `mask`.

    Args:
        arr (cupy.ndarray): Array to put data into.
        mask (array-like): Boolean mask array. Must have the same size as `a`.
        vals (array-like): Values to put into `a`. Only the first
            N elements are used, where N is the number of True values in
            `mask`. If `vals` is smaller than N, it will be repeated, and if
            elements of `a` are to be masked, this sequence must be non-empty.

    Examples
    --------
    >>> arr = np.arange(6).reshape(2, 3)
    >>> np.place(arr, arr>2, [44, 55])
    >>> arr
    array([[ 0,  1,  2],
           [44, 55, 44]])

    .. warning::

        This function may synchronize the device.

    .. seealso:: :func:`numpy.place`
    z$Mask and data must be the same size.r   Nz"Cannot insert from an empty array.wrapmode)cupyasarraysize
ValueErrorravelnonzeroput)arrmaskvalsmask_indices r   I/home/ubuntu/.local/lib/python3.10/site-packages/cupy/_indexing/insert.pyplace   s   



r   r   c                 C   s   | j |||d dS )a  Replaces specified elements of an array with given values.

    Args:
        a (cupy.ndarray): Target array.
        ind (array-like): Target indices, interpreted as integers.
        v (array-like): Values to place in `a` at target indices.
            If `v` is shorter than `ind` it will be repeated as necessary.
        mode (str): How out-of-bounds indices will behave. Its value must be
            either `'raise'`, `'wrap'` or `'clip'`. Otherwise,
            :class:`TypeError` is raised.

    .. note::
        Default `mode` is set to `'wrap'` to avoid unintended performance drop.
        If you need NumPy's behavior, please pass `mode='raise'` manually.

    .. seealso:: :func:`numpy.put`
    r   N)r   )aindvr   r   r   r   r   1   s   r   z%Q mask, raw S values, uint64 len_valszT outz3
    if (mask) out = (T) values[i % len_vals];
    cupy_putmask_kernelc                 C   s   t | tjs
tdt |tjstdt|s#t |tjs#td| j|jks-td|tj	}t|r>|| |< dS t
|j| jsPtd|j| j| j|jkr^|| | |< dS | }t||t||  dS )a  
    Changes elements of an array inplace, based on a conditional mask and
    input values.

    Sets ``a.flat[n] = values[n]`` for each n where ``mask.flat[n]==True``.
    If `values` is not the same size as `a` and `mask` then it will repeat.

    Args:
        a (cupy.ndarray): Target array.
        mask (cupy.ndarray): Boolean mask array. It has to be
            the same shape as `a`.
        values (cupy.ndarray or scalar): Values to put into `a` where `mask`
            is True. If `values` is smaller than `a`, then it will be
            repeated.

    Examples
    --------
    >>> x = cupy.arange(6).reshape(2, 3)
    >>> cupy.putmask(x, x>2, x**2)
    >>> x
    array([[ 0,  1,  2],
           [ 9, 16, 25]])

    If `values` is smaller than `a` it is repeated:

    >>> x = cupy.arange(6)
    >>> cupy.putmask(x, x>2, cupy.array([-33, -44]))
    >>> x
    array([  0,   1,   2, -44, -33, -44])

    .. seealso:: :func:`numpy.putmask`

    z"`a` should be of type cupy.ndarrayz%`mask` should be of type cupy.ndarrayz'`values` should be of type cupy.ndarrayz#mask and data must be the same sizezACannot cast array data from {} to {} according to the rule 'safe'N)
isinstancer   ndarray	TypeErrorisscalarshaper	   astypenumpybool_can_castdtypeformatr
   _putmask_kernellen)r   r   valuesr   r   r   putmaskO   s&   #
r&   Fc                 C   s   | j dk r	tdd}| j dkr$| jd d }|s#| jd | jd  }ntt| jdks3tddt| jdd   }|| jd||< dS )a1  Fills the main diagonal of the given array of any dimensionality.

    For an array `a` with ``a.ndim > 2``, the diagonal is the list of
    locations with indices ``a[i, i, ..., i]`` all identical. This function
    modifies the input array in-place, it does not return a value.

    Args:
        a (cupy.ndarray): The array, at least 2-D.
        val (scalar): The value to be written on the diagonal.
            Its type must be compatible with that of the array a.
        wrap (bool): If specified, the diagonal is "wrapped" after N columns.
            This affects only tall matrices.

    Examples
    --------
    >>> a = cupy.zeros((3, 3), int)
    >>> cupy.fill_diagonal(a, 5)
    >>> a
    array([[5, 0, 0],
           [0, 5, 0],
           [0, 0, 5]])

    .. seealso:: :func:`numpy.fill_diagonal`
       zarray must be at least 2-dN   r   /All dimensions of input must be of equal length)	ndimr	   r   r   alldiffcumprodsumflat)r   valr   endstepr   r   r   fill_diagonal   s   

r4   r'   c                 C   s   t | }|f| S )aI  Return the indices to access the main diagonal of an array.

    Returns a tuple of indices that can be used to access the main
    diagonal of an array with ``ndim >= 2`` dimensions and shape
    (n, n, ..., n).

    Args:
        n (int): The size, along each dimension of the arrays for which
            the indices are to be returned.
        ndim (int): The number of dimensions. default `2`.

    Examples
    --------
    Create a set of indices to access the diagonal of a (4, 4) array:

    >>> di = cupy.diag_indices(4)
    >>> di
    (array([0, 1, 2, 3]), array([0, 1, 2, 3]))
    >>> a = cupy.arange(16).reshape(4, 4)
    >>> a
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [12, 13, 14, 15]])
    >>> a[di] = 100
    >>> a
    array([[100,   1,   2,   3],
           [  4, 100,   6,   7],
           [  8,   9, 100,  11],
           [ 12,  13,  14, 100]])

    Create indices to manipulate a 3-D array:

    >>> d3 = cupy.diag_indices(2, 3)
    >>> d3
    (array([0, 1]), array([0, 1]), array([0, 1]))

    And use it to set the diagonal of an array of zeros to 1:

    >>> a = cupy.zeros((2, 2, 2), dtype=int)
    >>> a[d3] = 1
    >>> a
    array([[[1, 0],
            [0, 0]],
    <BLANKLINE>
           [[0, 0],
            [0, 1]]])

    .. seealso:: :func:`numpy.diag_indices`

    )r   arange)nr+   idxr   r   r   diag_indices   s   
4
r8   c                 C   sV   t | tjs
td| jdkstdtt| jdks"tdt	| jd | jS )z
    Return the indices to access the main diagonal of an n-dimensional array.
    See `diag_indices` for full details.

    Args:
        arr (cupy.ndarray): At least 2-D.

    .. seealso:: :func:`numpy.diag_indices_from`

    zArgument must be cupy.ndarrayr'   z input array must be at least 2-dr   r)   )
r   r   r   r   r+   r	   r,   r-   r   r8   )r   r   r   r   diag_indices_from   s   
r9   )r   )F)r'   )r   r   r   r   r   ElementwiseKernelr#   r&   r4   r8   r9   r   r   r   r   <module>   s    
*	
?
)8