o
    X۷i)                     @  sv   d dl mZ d dlZejdk rd dlmZ n	d dlm  mZ d dl	Z	d dl
mZ dd Zdd	 Zd
d Zdd ZdS )    )annotationsN2)index_tricks)internalc                 O  s  |j }t||}t||d}t|jdd }dd |D }zt|}W n t	y2   t
dw | || g|R i |}	t|	}	t|jdd |	j |	j}
|	|
|< |D ]}| || g|R i |}t||
|< qZt|	j D ]	}t|
d|}
qv|
S )a  Apply a function to 1-D slices along the given axis.

    Args:
        func1d (function (M,) -> (Nj...)): This function should accept 1-D
            arrays. It is applied to 1-D slices of ``arr`` along the specified
            axis. It must return a 1-D ``cupy.ndarray``.
        axis (integer): Axis along which ``arr`` is sliced.
        arr (cupy.ndarray (Ni..., M, Nk...)): Input array.
        args: Additional arguments for ``func1d``.
        kwargs: Additional keyword arguments for ``func1d``.

    Returns:
        cupy.ndarray: The output array. The shape of ``out`` is identical to
        the shape of ``arr``, except along the ``axis`` dimension. This
        axis is removed, and replaced with new dimensions equal to the
        shape of the return value of ``func1d``. So if ``func1d`` returns a
        scalar ``out`` will have one fewer dimensions than ``arr``.

    .. seealso:: :func:`numpy.apply_along_axis`
    Nc                 s  s    | ]}|t f V  qd S )N)Ellipsis).0ind r
   J/home/ubuntu/vllm_env/lib/python3.10/site-packages/cupy/lib/_shape_base.py	<genexpr>)   s    z#apply_along_axis.<locals>.<genexpr>z;Cannot apply_along_axis when any iteration dimensions are 0)ndimr   _normalize_axis_indexcupymoveaxisr   ndindexshapenextStopIteration
ValueErrorasarrayemptydtyperange)func1daxisarrargskwargsr   
inarr_viewindsind0resbuffr	   outir
   r
   r   apply_along_axis   s,   
r&   c                 C  s   t |}|j}t|jdkr|f}|D ](}t||}| ||}|j|jkr+|}qt ||}|j|jkr:|}qtd|S )aa  
    Apply a function repeatedly over multiple axes.

    `func` is called as `res = func(a, axis)`, where `axis` is the first
    element of `axes`.  The result `res` of the function call must have
    either the same dimensions as `a` or one less dimension.  If `res`
    has one less dimension than `a`, a dimension is inserted before
    `axis`.  The call to `func` is then repeated for each axis in `axes`,
    with `res` as the first argument.

    Parameters
    ----------
    func : function
        This function must take two arguments, `func(a, axis)`.
    a : array_like
        Input array.
    axes : array_like
        Axes over which `func` is applied; the elements must be integers.

    Returns
    -------
    apply_over_axis : ndarray
        The output array.  The number of dimensions is the same as `a`,
        but the shape can be different.  This depends on whether `func`
        changes the shape of its output with respect to its input.

    See Also
    --------
    apply_along_axis :
        Apply a function to 1-D slices of an array along the given axis.

    Notes
    -----
    This function is equivalent to tuple axis arguments to reorderable ufuncs
    with keepdims=True. Tuple axis arguments to ufuncs have been available.

    Examples
    --------
    >>> a = np.arange(24).reshape(2,3,4)
    >>> a
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11]],
           [[12, 13, 14, 15],
            [16, 17, 18, 19],
            [20, 21, 22, 23]]])

    Sum over axes 0 and 2. The result has same number of dimensions
    as the original array:

    >>> np.apply_over_axes(np.sum, a, [0,2])
    array([[[ 60],
            [ 92],
            [124]]])

    Tuple axis arguments to ufuncs are equivalent:

    >>> np.sum(a, axis=(0,2), keepdims=True)
    array([[[ 60],
            [ 92],
            [124]]])

    r   z7function is not returning an array of the correct shape)	r   r   r   numpyarrayr   r   expand_dimsr   )funcaaxesvalNr   r"   r
   r
   r   apply_over_axesH   s   
@
r/   c           	      C  s   t |jt jstdt| |jkrtdd|j }tt	|d g tt	|d |j }g }t
|| D ])\}}|d u rD|| q6|d | d ||d d   }|t || q6t|S )Nz"`indices` must be an integer arrayz;`indices` and `arr` must have the same number of dimensions)   r0   )r   )r   
issubdtyper   integer
IndexErrorlenr   r   listr   zipappendarangereshapetuple)		arr_shapeindicesr   
shape_ones	dest_dimsfancy_indexdimn	ind_shaper
   r
   r   _make_along_axis_idx   s"   
 rC   c                 C  sT   |du r|j dkrtdt| || dS t|| j }| j}|| t|||< dS )av  
    Put values into the destination array by matching 1d index and data slices.

    This iterates over matching 1d slices oriented along the specified axis in
    the index and data arrays, and uses the former to place values into the
    latter. These slices can be different lengths.

    Functions returning an index along an axis, like `argsort` and
    `argpartition`, produce suitable indices for this function.

    Args:
        arr : cupy.ndarray (Ni..., M, Nk...)
            Destination array.
        indices : cupy.ndarray (Ni..., J, Nk...)
            Indices to change along each 1d slice of `arr`. This must match the
            dimension of arr, but dimensions in Ni and Nj may be 1 to broadcast
            against `arr`.
        values : array_like (Ni..., J, Nk...)
            values to insert at those indices. Its shape and dimension are
            broadcast to match that of `indices`.
        axis : int
            The axis to take 1d slices along. If axis is None, the destination
            array is treated as if a flattened 1d view had been created of it.

    .. seealso:: :func:`numpy.put_along_axis`
    Nr0   z+Tuple setitem isn't supported for flatiter.)r   NotImplementedErrorr   putr   r   r   rC   )r   r<   valuesr   r;   r
   r
   r   put_along_axis   s   
rG   )
__future__r   r'   __version__	numpy.libr   numpy.lib._index_tricks_impllib_index_tricks_implr   
cupy._corer   r&   r/   rC   rG   r
   r
   r
   r   <module>   s    
;T