
    `i8                     n   d dl Z d dl mZ d dlmZ d dl mZ d dlmZ d dlmZ d&dZ	d&d	Z
d&d
Zd&dZd Zd Z ej        ddd          Zd'dZd ZdZdZdZ ej        ddedeez             ZdZ ej        dddez   dz   deez             Z ej        dd d!ez   dz   d"eez             Zd(d$Zd% ZdS ))    N)_core)fusion)_util)_routines_indexing)_routines_statisticsFc                 4    |                      ||||          S )a  Returns the indices of the maximum along an axis.

    Args:
        a (cupy.ndarray): Array to take argmax.
        axis (int): Along which axis to find the maximum. ``a`` is flattened by
            default.
        dtype: Data type specifier.
        out (cupy.ndarray): Output array.
        keepdims (bool): If ``True``, the axis ``axis`` is preserved as an axis
            of length one.

    Returns:
        cupy.ndarray: The indices of the maximum of ``a`` along an axis.

    .. note::
       ``dtype`` and ``keepdim`` arguments are specific to CuPy. They are
       not in NumPy.

    .. note::
       ``axis`` argument accepts a tuple of ints, but this is specific to
       CuPy. NumPy does not support it.

    .. seealso:: :func:`numpy.argmax`

    axisdtypeoutkeepdims)argmaxar
   r   r   r   s        h/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/cupy/_sorting/search.pyr   r   
       6 88Uh8GGG    c                 v    | j         j        dv rt          | ||||          S t          j        | ||||          S )a  Return the indices of the maximum values in the specified axis ignoring
    NaNs. For all-NaN slice ``-1`` is returned.
    Subclass cannot be passed yet, subok=True still unsupported

    Args:
        a (cupy.ndarray): Array to take nanargmax.
        axis (int): Along which axis to find the maximum. ``a`` is flattened by
            default.

    Returns:
        cupy.ndarray: The indices of the maximum of ``a``
        along an axis ignoring NaN values.

    .. note:: For performance reasons, ``cupy.nanargmax`` returns
            ``out of range values`` for all-NaN slice
            whereas ``numpy.nanargmax`` raises ``ValueError``
    .. seealso:: :func:`numpy.nanargmax`
    biur	   )r   kindr   _statistics
_nanargmaxr   s        r   	nanargmaxr   (   E    & 	w|uad%S8LLLL!!T3x@@@r   c                 4    |                      ||||          S )a  Returns the indices of the minimum along an axis.

    Args:
        a (cupy.ndarray): Array to take argmin.
        axis (int): Along which axis to find the minimum. ``a`` is flattened by
            default.
        dtype: Data type specifier.
        out (cupy.ndarray): Output array.
        keepdims (bool): If ``True``, the axis ``axis`` is preserved as an axis
            of length one.

    Returns:
        cupy.ndarray: The indices of the minimum of ``a`` along an axis.

    .. note::
       ``dtype`` and ``keepdim`` arguments are specific to CuPy. They are
       not in NumPy.

    .. note::
       ``axis`` argument accepts a tuple of ints, but this is specific to
       CuPy. NumPy does not support it.

    .. seealso:: :func:`numpy.argmin`

    r	   )argminr   s        r   r   r   A   r   r   c                 v    | j         j        dv rt          | ||||          S t          j        | ||||          S )a  Return the indices of the minimum values in the specified axis ignoring
    NaNs. For all-NaN slice ``-1`` is returned.
    Subclass cannot be passed yet, subok=True still unsupported

    Args:
        a (cupy.ndarray): Array to take nanargmin.
        axis (int): Along which axis to find the minimum. ``a`` is flattened by
            default.

    Returns:
        cupy.ndarray: The indices of the minimum of ``a``
        along an axis ignoring NaN values.

    .. note:: For performance reasons, ``cupy.nanargmin`` returns
            ``out of range values`` for all-NaN slice
            whereas ``numpy.nanargmin`` raises ``ValueError``
    .. seealso:: :func:`numpy.nanargmin`
    r   r	   )r   r   r   r   
_nanargminr   s        r   	nanargminr   _   r   r   c                 V    t          j        | d           |                                 S )a  Return the indices of the elements that are non-zero.

    Returns a tuple of arrays, one for each dimension of a,
    containing the indices of the non-zero elements in that dimension.

    Args:
        a (cupy.ndarray): array

    Returns:
        tuple of arrays: Indices of elements that are non-zero.

    .. warning::

        This function may synchronize the device.

    .. seealso:: :func:`numpy.nonzero`

    r   arg_name)r   check_arraynonzeror   s    r   r$   r$   x   s(    & 
a#&&&&99;;r   c                     t          j        | d           |                                                                 d         S )a  Return indices that are non-zero in the flattened version of a.

    This is equivalent to a.ravel().nonzero()[0].

    Args:
        a (cupy.ndarray): input array

    Returns:
        cupy.ndarray: Output array,
        containing the indices of the elements of a.ravel() that are non-zero.

    .. warning::

        This function may synchronize the device.

    .. seealso:: :func:`numpy.flatnonzero`
    r   r!   r   )r   r#   ravelr$   r%   s    r   flatnonzeror(      s9    $ 
a#&&&&7799q!!r   
cupy_where)z???->?z?bb->bz?BB->Bz?hh->hz?HH->Hz?ii->iz?II->Iz?ll->lz?LL->Lz?qq->qz?QQ->Qz?ee->ez?ff->fz?hd->dz?Hd->dz?dd->dz?FF->Fz?DD->Dzout0 = in0 ? in1 : in2c                 2   |du |du f                     d          }|dk    rt          d          |dk    rt          |           S t          j                    rt          j        t          | ||          S t          |                     d          ||          S )a  Return elements, either from x or y, depending on condition.

    If only condition is given, return ``condition.nonzero()``.

    Args:
        condition (cupy.ndarray): When True, take x, otherwise take y.
        x (cupy.ndarray): Values from which to choose on ``True``.
        y (cupy.ndarray): Values from which to choose on ``False``.

    Returns:
        cupy.ndarray: Each element of output contains elements of ``x`` when
        ``condition`` is ``True``, otherwise elements of ``y``. If only
        ``condition`` is given, return the tuple ``condition.nonzero()``,
        the indices where ``condition`` is True.

    .. warning::

        This function may synchronize the device if both ``x`` and ``y`` are
        omitted.

    .. seealso:: :func:`numpy.where`

    NT   z)Must provide both 'x' and 'y' or neither.   ?)count
ValueErrorr$   r   
_is_fusing_call_ufunc_where_ufuncastype)	conditionxymissings       r   wherer8      s    2 Dy!t)$**400G!||HIII!||y!!! A!,	1a@@@	((--q!444r   c                 V    t          j        | d           t          j        |           S )a  Return the indices of the elements that are non-zero.

    Returns a (N, ndim) dimantional array containing the
    indices of the non-zero elements. Where `N` is number of
    non-zero elements and `ndim` is dimension of the given array.

    Args:
        a (cupy.ndarray): array

    Returns:
        cupy.ndarray: Indices of elements that are non-zero.

    .. seealso:: :func:`numpy.argwhere`

    r   r!   )r   r#   	_indexing_ndarray_argwherer%   s    r   argwherer<      s+      
a#&&&&&q)))r   zO
template<typename T>
__device__ bool _isnan(T val) {
    return val != val;
}
a  
#ifdef __HIP_DEVICE_COMPILE__
  #define no_thread_divergence(do_work, to_return) \
    if (!is_done) {                                \
      do_work;                                     \
      is_done = true;                              \
    }
#else
  #define no_thread_divergence(do_work, to_return) \
    do_work;                                       \
    if (to_return) { return; }
#endif
a  
    #ifdef __HIP_DEVICE_COMPILE__
    bool is_done = false;
    #endif

    // Array is assumed to be monotonically
    // increasing unless a check is requested with the
    // `assume_increasing = False` parameter.
    // `digitize` allows increasing and decreasing arrays.
    bool inc = true;
    if (!assume_increasing && n_bins >= 2) {
        // In the case all the bins are nan the array is considered
        // to be decreasing in numpy
        inc = (bins[0] <= bins[n_bins-1])
              || (!_isnan<T>(bins[0]) && _isnan<T>(bins[n_bins-1]));
    }

    if (_isnan<S>(x)) {
        long long pos = (inc ? n_bins : 0);
        if (!side_is_right) {
            if (inc) {
                while (pos > 0 && _isnan<T>(bins[pos-1])) {
                    --pos;
                }
            } else {
                while (pos < n_bins && _isnan<T>(bins[pos])) {
                    ++pos;
                }
            }
        }
        no_thread_divergence( y = pos , true )
    }

    bool greater = false;
    if (side_is_right) {
        greater = inc && x >= bins[n_bins-1];
    } else {
        greater = (inc ? x > bins[n_bins-1] : x <= bins[n_bins-1]);
    }
    if (greater) {
        no_thread_divergence( y = n_bins , true )
    }

    long long left = 0;
    // In the case the bins is all NaNs, digitize
    // needs to place all the valid values to the right
    if (!inc) {
        while (_isnan<T>(bins[left]) && left < n_bins) {
            ++left;
        }
        if (left == n_bins) {
            no_thread_divergence( y = n_bins , true )
        }
        if (side_is_right
                && !_isnan<T>(bins[n_bins-1]) && !_isnan<S>(x)
                && bins[n_bins-1] > x) {
            no_thread_divergence( y = n_bins , true )
        }
    }

    long long right = n_bins-1;
    while (left < right) {
        long long m = left + (right - left) / 2;
        bool look_right = true;
        if (side_is_right) {
            look_right = (inc ? bins[m] <= x : bins[m] > x);
        } else {
            look_right = (inc ? bins[m] < x : bins[m] >= x);
        }
        if (look_right) {
            left = m + 1;
        } else {
            right = m;
        }
    }
    no_thread_divergence( y = right , false )
zIS x, raw T bins, int64 n_bins, bool side_is_right, bool assume_increasingzint64 ycupy_searchsorted_kernel)namepreambleaJ  
#ifdef __HIP_DEVICE_COMPILE__
  #define no_thread_divergence(do_work, to_return) \
    if (!is_done) {                                \
      do_work;                                     \
      is_done = true;                              \
    }
#else
  #define no_thread_divergence(do_work, to_return) \
    do_work;                                       \
    if (to_return) {                               \
      out = (y == n_bins ? false : bins[y] == x);  \
      if (invert) out = !out;                      \
      return;                                      \
    }
#endif
z*S x, raw T bins, int64 n_bins, bool invertzbool outze
    const bool assume_increasing = true;
    const bool side_is_right = false;
    long long y;
    zQ
    out = (y == n_bins ? false : bins[y] == x);
    if (invert) out = !out;
    cupy_exists_kernelzbool out, int64 yzT
    const bool assume_increasing = true;
    const bool side_is_right = false;
    #cupy_exists_and_searchsorted_kernelleftc                 (    t          | |||d          S )a  Finds indices where elements should be inserted to maintain order.

    Find the indices into a sorted array ``a`` such that,
    if the corresponding elements in ``v`` were inserted before the indices,
    the order of ``a`` would be preserved.

    Args:
        a (cupy.ndarray): Input array. If ``sorter`` is ``None``, then
            it must be sorted in ascending order,
            otherwise ``sorter`` must be an array of indices that sort it.
        v (cupy.ndarray): Values to insert into ``a``.
        side : {'left', 'right'}
            If ``left``, return the index of the first suitable location found
            If ``right``, return the last such index.
            If there is no suitable index, return either 0 or length of ``a``.
        sorter : 1-D array_like
            Optional array of integer indices that sort array ``a`` into
            ascending order. They are typically the result of
            :func:`~cupy.argsort`.

    Returns:
        cupy.ndarray: Array of insertion points with the same shape as ``v``.

    .. note:: When a is not in ascending order, behavior is undefined.

    .. seealso:: :func:`numpy.searchsorted`

    T)_searchsorted)r   vsidesorters       r   searchsortedrH     s    : AtVT222r   c                 V   t          | t          j                  st          d          t          |t          j                  st          d          | j        dk    rt          d          | j        dk     rt          d          | j        dk    r%t          j        |j        t          j	                  S | j
        j        dk    }|j
        j        dk    }|r|s|                    | j
                  }n|r|s|                     |j
                  } |Q|j
        j        d
vrt          d          |j        | j        k    rt          d          |                     |          } t          j        |j        t          j	                  }t          || | j        |dk    ||           |S )z`assume_increasing` is used in the kernel to
    skip monotonically increasing or decreasing verification
    inside the cuda kernel.
    z'Only int or ndarray are supported for az'Only int or ndarray are supported for vr+   z!object too deep for desired arrayz+object of too small depth for desired arrayr   )r   cN)iuzsorter must be of integer typezsorter.size must equal a.sizeright)
isinstancecupyndarrayNotImplementedErrorndimr/   sizezerosshapeint64r   r   r3   	TypeErrortake_searchsorted_kernel)r   rE   rF   rG   assume_increasinga_iscomplexv_iscomplexr6   s           r   rD   rD     s   
 a&& M!"KLLLa&& M!"KLLLvzz<===vzzFGGGv{{z!'4444',#%K',#%K ; HHQW	 [ HHQW <J..<===;!&  <===FF6NN
17$*---AAqvtw8I1MMMHr   )NNNF)NN)rB   N)rO   r   
cupy._corer   r   r   r:   r   r   r   r   r   r   r$   r(   create_ufuncr2   r8   r<   	_preamble_hip_preamble_searchsorted_codeElementwiseKernelrY   _exists_kernel_exists_and_searchsorted_kernelrH   rD    r   r   <module>rf      s?                      6 6 6 6 6 6 : : : : : :H H H H<A A A A2H H H H<A A A A2  ." " ", "u!# 	 	"5 "5 "5 "5J* * *,	L ^ /u.	#i.EG G G & )(0
 
 #Y}-DF F F #:%"90 		 4}$#& #& #& 3 3 3 3@& & & & &r   