
    
9j9                       S SK Jr  S SKrS SKJr  S SKJr  S SKJr  S SKJr  S SKJ	r
  S%S jrS%S	 jrS%S
 jrS%S jrS rS r\R"                  " SSS5      rS&S jrS rSrSrSr\R0                  " SS\S\\-   S9rSr\R0                  " SSS\-   S-   S\\-   S9r\R0                  " SS S!\-   S-   S"\\-   S9rS'S# jrS$ rg)(    )annotationsN)_core)fusion)_util)_routines_indexing)_routines_statisticsc                "    U R                  XX4S9$ )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        N/home/wildlama/miniconda3/lib/python3.13/site-packages/cupy/_sorting/search.pyr   r          6 888GG    c                |    U R                   R                  S;   a  [        XX#US9$ [        R                  " XX2U5      $ )az  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   *   8    & 	ww||ua%8LL!!!3x@@r   c                "    U R                  XX4S9$ )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   C   r   r   c                |    U R                   R                  S;   a  [        XX#US9$ [        R                  " XX2U5      $ )az  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    a   r   r   c                L    [         R                  " U SS9  U R                  5       $ )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%   z   s     & 
a#&99;r   c                n    [         R                  " U SS9  U R                  5       R                  5       S   $ )ar  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)      s.    $ 
a#&779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?dd->dz?FF->Fz?DD->Dzout0 = in0 ? in1 : in2c                   USL USL 4R                  S5      nUS:X  a  [        S5      eUS:X  a  [        U 5      $ [        R                  " 5       (       a  [        R
                  " [        XU5      $ [        U R                  SSS9X5      $ )	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.   ?F)copy)count
ValueErrorr%   r   
_is_fusing_call_ufunc_where_ufuncastype)	conditionxymissings       r   wherer:      s    2 Dy!t)$**40G!|HII!|y!!!!,	a@@	((5(91@@r   c                X    [         R                  " U SS9  [        R                  " U 5      $ )ao  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 outz
    // Handle empty bins array to avoid illegal memory access
    if (n_bins == 0) {
        out = (invert ? true : false);
        return;
    }

    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 yz
    // Handle empty bins array to avoid illegal memory access
    if (n_bins == 0) {
        out = (invert ? true : false);
        y = 0;
        return;
    }

    const bool assume_increasing = true;
    const bool side_is_right = false;
    #cupy_exists_and_searchsorted_kernelc                    [        XX#S5      $ )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   searchsortedrI     s    : tT22r   c                \   [        U [        R                  5      (       d  [        S5      e[        U[        R                  5      (       dD  [        U[        [
        -  [        -  5      (       d  [        S5      e[        R                  " U5      nU R                  S:  a  [        S5      eU R                  S:  a  [        S5      eU R                  S:X  a-  [        R                  " UR                  [        R                  S9$ U R                  R                  S:H  nUR                  R                  S:H  nU(       a#  U(       d  UR!                  U R                  5      nO)U(       a"  U(       d  U R!                  UR                  5      n Ub[  UR                  R                  S	;  a  [#        S
5      eUR                  U R                  :w  a  [        S5      eU R%                  U5      n [        R                  " UR                  [        R                  S9n['        XU R                  US:H  XG5        U$ )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 az3Only python scalars or ndarrays are supported for vr,   z!object too deep for desired arrayz+object of too small depth for desired arrayr   )r   c)iuzsorter must be of integer typezsorter.size must equal a.sizeright)
isinstancecupyndarrayNotImplementedErrorintfloatcomplexasarrayndimr1   sizezerosshapeint64r   r   r5   	TypeErrortake_searchsorted_kernel)r   rF   rG   rH   assume_increasinga_iscomplexv_iscomplexr8   s           r   rE   rE     s   
 a&&!"KLLa&&!S5[7233%EG GLLOvvz<==vvzFGGvv{zz!''44'',,#%K'',,#%K;HHQWW	[HHQWW <<J.<==;;!&& <==FF6N

177$**-Aqvvtw8IMHr   )NNNF)NN)leftN)
__future__r   rP   r   
cupy._corer   r   r   r<   r   r   r   r   r   r    r%   r)   create_ufuncr4   r:   r>   	_preamble_hip_preamble_searchsorted_codeElementwiseKernelr^   _exists_kernel_exists_and_searchsorted_kernelrI   rE    r   r   <module>rm      s7   "     6 :H<A2H<A2.", !!# #AL*,	L ^ ..	#i.EG & ((0
  #Y}-D#F( #("9"90
  4}$%#& *3@)r   