o
    W۷iX                     @  s   d dl mZ d dlZd dlZ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 d dl	mZ eZedd	d
dZeddddZdd Zdd Zdd Zd)ddZd*ddZd+ddZeddd d!Zed"dd#d$Zd,d%d&Zd-d'd(ZdS ).    )annotationsN)_core)_accelerator)cub)common)runtimezS x, raw T bins, int32 n_binszraw U yaD  
    if (x < bins[0] or bins[n_bins - 1] < x) {
        return;
    }
    int high = n_bins - 1;
    int low = 0;

    while (high - low > 1) {
        int mid = (high + low) / 2;
        if (bins[mid] <= x) {
            low = mid;
        } else {
            high = mid;
        }
    }
    atomicAdd(&y[low], U(1));
    cupy_histogram_kernelz,S x, raw T bins, int32 n_bins, raw W weightszraw Y yaM  
    if (x < bins[0] or bins[n_bins - 1] < x) {
        return;
    }
    int high = n_bins - 1;
    int low = 0;

    while (high - low > 1) {
        int mid = (high + low) / 2;
        if (bins[mid] <= x) {
            low = mid;
        } else {
            high = mid;
        }
    }
    atomicAdd(&y[low], (Y)weights[i]);
    cupy_weighted_histogram_kernelc                 C  s|   | j tjkrtjd| j tjtdd | tj} |dur6t	|tj
s(td|j| jkr2td| }|  } | |fS )z: Check a and weights have matching shapes, and ravel both z1Converting input from {} to {} for compatibility.   )
stacklevelNzweights must be a cupy.ndarrayz(weights should have the same shape as a.)dtypecupybool_warningswarnformatuint8RuntimeWarningastype
isinstancendarray
ValueErrorshaperavel)aweights r   P/home/ubuntu/vllm_env/lib/python3.10/site-packages/cupy/_statistics/histogram.py_ravel_and_check_weightsC   s    r   c                 C  s   |dur#|\}}||krt dt|rt|s"t d||n$| jdkr-d}d}n|  }|  }t|r?t|sGt d||||krS|d }|d }||fS )z^
    Determine the outer bin edges to use, from either the data or the range
    argument
    Nz/max must be larger than min in range parameter.z(supplied range of [{}, {}] is not finiter      z,autodetected range of [{}, {}] is not finiteg      ?)r   numpyisfiniter   sizeminmaxr   )r   range
first_edge	last_edger   r   r   _get_outer_edgesX   s8   
r(   c                 C  s4  d}d}t |trtdt |tjst|dkrFt |tjr#|}nt|}|dd |dd k r:t	dt |tjrEt|}n.t|dkrpzt
|}W n ty_   tdw |dk rht	dt| |\}}nt	d	|durt||| }t|tjrt|t}tj|||d d
|d}|S )a5  
    Computes the bins used internally by `histogram`.

    Args:
        a (ndarray): Ravelled data array
        bins (int or ndarray): Forwarded argument from `histogram`.
        range (None or tuple): Forwarded argument from `histogram`.

    Returns:
        bin_edges (ndarray): Array of bin edges
    Nz+only integer and array bins are implementedr   z1`bins` must increase monotonically, when an arrayr   z0`bins` must be an integer, a string, or an arrayz(`bins` must be positive, when an integerz `bins` must be 1d, when an arrayT)endpointr   )r   strNotImplementedErrorr   r   r    ndimasarrayanyr   operatorindex	TypeErrorr(   result_type
issubdtypeintegerfloatlinspace)r   binsr%   n_equal_bins	bin_edgesr&   r'   bin_typer   r   r   _get_bin_edgesy   sL   



r<   
   Fc                 C  s  | j jdkr
tdt| tjstdt| |\} }t| ||}|du rtj	|j
d tjd}t D ]}|tjkr| j
dkr|j
dkrt|tjsMJ t| j tjrXt}nt|j | j }|tjkrlt sltj}| j|dd	} |j|d
d	}	| j jdv r|	d  d7  < n| j jdkr|	d }
t|
|
d |	d< tjr|jtjdd	}t| ||	}|du rq4|}tjr|jtjdd	} n	q4t| ||j
| net |j tj!pt |j tj"}|std|j jdkrtj	|j
d tj"d}t#| ||j
|j$|j$ t#| ||j
|j%|j% n&|j jdv rtj	|j
d t&d}ntj	|j
d tj!d}t#| ||j
|| |rIt't(|tj!}|| |)  |fS ||fS )a3  Computes the histogram of a set of data.

    Args:
        x (cupy.ndarray): Input array.
        bins (int or cupy.ndarray): If ``bins`` is an int, it represents the
            number of bins. If ``bins`` is an :class:`~cupy.ndarray`, it
            represents a bin edges.
        range (2-tuple of float, optional): The lower and upper range of the
            bins.  If not provided, range is simply ``(x.min(), x.max())``.
            Values outside the range are ignored. The first element of the
            range must be less than or equal to the second. `range` affects the
            automatic bin computation as well. While bin width is computed to
            be optimal based on the actual data within `range`, the bin count
            will fill the entire range including portions containing no data.
        density (bool, optional): If False, the default, returns the number of
            samples in each bin. If True, returns the probability *density*
            function at the bin, ``bin_count / sample_count / bin_volume``.
        weights (cupy.ndarray, optional): An array of weights, of the same
            shape as `x`.  Each value in `x` only contributes its associated
            weight towards the bin count (instead of 1).
    Returns:
        tuple: ``(hist, bin_edges)`` where ``hist`` is a :class:`cupy.ndarray`
        storing the values of the histogram, and ``bin_edges`` is a
        :class:`cupy.ndarray` storing the bin edges.

    .. warning::

        This function may synchronize the device.

    .. seealso:: :func:`numpy.histogram`
    czcomplex number is not supportedzx must be a cupy.ndarrayNr   r   F)copyTuir)   fzJonly weights with dtype that can be cast to float or complex are supportedbui)*r   kindr,   r   r   r   r   r   r<   zerosr"   int64r   get_routine_acceleratorsACCELERATOR_CUBr    r4   r5   r6   r3   float16r   _is_fp16_supportedfloat32r   	nextafterr   is_hipuint64r   cub_histogram_histogram_kernelcan_castfloat64
complex128_weighted_histogram_kernelrealimagintarraydiffsum)xr8   r%   densityr   r:   yacceleratorr;   acc_bin_edgelastoutsimple_weightsdbr   r   r   	histogram   s~   !

re   c                   s  t tjrjdkrddtjf j\}}ntjddj\}}t|t	}|dg  |dg }|dur?t
|}zt|}	|	|krLtdW n ty[   ||g }Y nw |du red| }n
t||krotdt|D ]}
t||
 dkr||
 dk rtd	|
tdd|
f ||
 \}}t	||
 d }t||| |
< n<t||
 dkrt ||
 tjstd
||
  |
<  |
 dd  |
 dd k rtd|
ntd|
t |
 d ||
< t |
 ||
< qst fddt|D }t|D ]}
dd|
f  |
 d k}||
 |  d8  < qt||}tj||t|d}||}|t}|tddf }|| }|rz| }t|D ]}
dg| }||
 d ||
< |||
 | }q\|| }t|jt
|d krtd| fS )a  Compute the multidimensional histogram of some data.

    Args:
        sample (cupy.ndarray): The data to be histogrammed. (N, D) or (D, N)
            array

            Note the unusual interpretation of sample when an array_like:

            * When an array, each row is a coordinate in a D-dimensional
              space - such as ``histogramdd(cupy.array([p1, p2, p3]))``.
            * When an array_like, each element is the list of values for single
              coordinate - such as ``histogramdd((X, Y, Z))``.

            The first form should be preferred.
        bins (int or tuple of int or cupy.ndarray): The bin specification:

            * A sequence of arrays describing the monotonically increasing bin
              edges along each dimension.
            * The number of bins for each dimension (nx, ny, ... =bins)
            * The number of bins for all dimensions (nx=ny=...=bins).
        range (sequence, optional): A sequence of length D, each an optional
            (lower, upper) tuple giving the outer bin edges to be used if the
            edges are not given explicitly in `bins`. An entry of None in the
            sequence results in the minimum and maximum values being used for
            the corresponding dimension. The default, None, is equivalent to
            passing a tuple of D None values.
        weights (cupy.ndarray): An array of values `w_i` weighing each sample
            `(x_i, y_i, z_i, ...)`. The values of the returned histogram are
            equal to the sum of the weights belonging to the samples falling
            into each bin.
        density (bool, optional): If False, the default, returns the number of
            samples in each bin. If True, returns the probability *density*
            function at the bin, ``bin_count / sample_count / bin_volume``.

    Returns:
        tuple:
        H (cupy.ndarray):
            The multidimensional histogram of sample x. See
            normed and weights for the different possible semantics.
        edges (list of cupy.ndarray):
            A list of D arrays describing the bin
            edges for each dimension.

    .. warning::

        This function may synchronize the device.

    .. seealso:: :func:`numpy.histogramdd`
    r   Nr)   )axiszFThe dimension of bins must be equal to the dimension of the  sample x.)Nz0range argument must have one entry per dimensionr   z,`bins[{}]` must be positive, when an integerzarray-like bins not supportedz:`bins[{}]` must be monotonically increasing, when an arrayz'`bins[{}]` must be a scalar or 1d arrayc                 3  s0    | ]}t j | d d |f ddV  qd S )Nright)side)r   searchsorted).0iedgessampler   r   	<genexpr>  s
    
zhistogramdd.<locals>.<genexpr>)	minlength   zInternal Shape Error)r   r   r   r-   newaxisr   stackr    emptyrX   r.   lenr   r2   _ranger   r(   r7   r/   rZ   tupleravel_multi_indexbincountprodreshaper   r6   slicer[   RuntimeError)rn   r8   r%   r   r]   nsamplesr-   nbindedgesnbinsrk   sminsmaxnumncounton_edgexyhistcoresr   r   rl   r   histogramdd$  s   2





$	


r   c                 C  s   zt |}W n ty   d}Y nw |dkr-|dkr-t|tjr)| }}||g}ntdt| |g||||\}	}
|	|
d |
d fS )a  Compute the bi-dimensional histogram of two data samples.

    Args:
        x (cupy.ndarray): The first array of samples to be histogrammed.
        y (cupy.ndarray): The second array of samples to be histogrammed.
        bins (int or tuple of int or cupy.ndarray): The bin specification:

            * A sequence of arrays describing the monotonically increasing bin
              edges along each dimension.
            * The number of bins for each dimension (nx, ny)
            * The number of bins for all dimensions (nx=ny=bins).
        range (sequence, optional): A sequence of length two, each an optional
            (lower, upper) tuple giving the outer bin edges to be used if the
            edges are not given explicitly in `bins`. An entry of None in the
            sequence results in the minimum and maximum values being used for
            the corresponding dimension. The default, None, is equivalent to
            passing a tuple of two None values.
        weights (cupy.ndarray): An array of values `w_i` weighing each sample
            `(x_i, y_i)`. The values of the returned histogram are equal to the
            sum of the weights belonging to the samples falling into each bin.
        density (bool, optional): If False, the default, returns the number of
            samples in each bin. If True, returns the probability *density*
            function at the bin, ``bin_count / sample_count / bin_volume``.

    Returns:
        tuple:
        H (cupy.ndarray):
            The multidimensional histogram of sample x. See
            normed and weights for the different possible semantics.
        edges0 (tuple of cupy.ndarray):
            A list of D arrays describing the bin
            edges for the first dimension.
        edges1 (tuple of cupy.ndarray):
            A list of D arrays describing the bin
            edges for the second dimension.

    .. warning::

        This function may synchronize the device.

    .. seealso:: :func:`numpy.histogram2d`
    r   rq   z%array-like bins not supported in CuPyr   )ru   r2   r   r   r   r   r   )r\   r^   r8   r%   r   r]   nxedgesyedgesr   rm   r   r   r   histogram2d  s   +
r   zS xz	raw U binzatomicAdd(&bin[x], U(1))cupy_bincount_kernelzS x, T wzatomicAdd(&bin[x], w) cupy_bincount_with_weight_kernelc                 C  sL  | j dkr	td| j dk rtd| jjdkrtd| dk  r&td|dur4| j|jkr4td	|durDt|}|dk rDtd
tt	| d }|durVt	||}|du rtj
|ftjd}t D ]&}tjs|tjkr| jdkr|dkrt| ||d }|du rqg|} |S qgt| | |S tj
|ftjd}t| || |S )a,  Count number of occurrences of each value in array of non-negative ints.

    Args:
        x (cupy.ndarray): Input array.
        weights (cupy.ndarray): Weights array which has the same shape as
            ``x``.
        minlength (int): A minimum number of bins for the output array.

    Returns:
        cupy.ndarray: The result of binning the input array. The length of
        output is equal to ``max(cupy.max(x) + 1, minlength)``.

    .. warning::

        This function may synchronize the device.

    .. seealso:: :func:`numpy.bincount`

    r   !object too deep for desired array+object of too small depth for desired arrayrC   zx must be int arrayr   z3The first argument of bincount must be non-negativeNz0The weights and list don't have the same length.zminlength must be non-negativer?   r@   )r-   r   r   rE   r2   r/   r   rX   r   r$   rF   r    intpr   rH   r   rN   rI   r"   r   rP   _bincount_kernelrS   _bincount_with_weight_kernel)r\   r   rp   r"   br_   rb   r   r   r   ry     sF   




ry   c                 C  sZ   | j jdkr
td|jdkrtd|jdk rtd|r dnd}tjj|| |dd	S )
a~  Finds the indices of the bins to which each value in input array belongs.

    .. note::

        In order to avoid device synchronization, digitize does not raise
        an exception when the array is not monotonic

    Args:
        x (cupy.ndarray): Input array.
        bins (cupy.ndarray): Array of bins.
            It has to be 1-dimensional and monotonic increasing or decreasing.
        right (bool):
            Indicates whether the intervals include the right or the left bin
            edge.

    Returns:
        cupy.ndarray: Output array of indices, of same shape as ``x``.

    .. seealso:: :func:`numpy.digitize`
    r>   zx may not be complexr   r   r   leftrg   NF)	r   rE   r2   r-   r   r   _sortingsearch_searchsorted)r\   r8   rg   rh   r   r   r   digitizeG  s   

r   )r=   NFN)r=   NNF)r=   NNN)NN)F)
__future__r   r0   r   r    r   r   
cupy._corer   	cupy.cudar   r   r   r%   rv   ElementwiseKernelrQ   rU   r   r(   r<   re   r   r   r   r   ry   r   r   r   r   r   <module>   sT    !
;
p 
;
?