o
    X۷i.[                     @  s  d Z ddlm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
 ddlZzddlZd	ZW n eyA   d
ZY nw eejejfZeejfZeddddZeddddZdd Zdd ZeddddZdd Zdd Zdd  Zejd!d"d#d$d	d%Z ejd&d'd(d)d	d%Z!	dAd*d+Z"ed,d-d.d/Z#G d0d1 d1Z$d2d3 Z%d4d5 Z&d6d7 Z'd8d9 Z(dBd;d<Z)d=d> Z*d?d@ Z+dS )Cz*Indexing mixin for sparse matrix classes.
    )annotationsN)_core)
isspmatrix)spmatrix)device)runtimeTFzT d, S ind, int32 minorzraw T answerz+if (ind == minor) atomicAdd(&answer[0], d);#cupyx_scipy_sparse_compress_getitemz"T real, T imag, S ind, int32 minorz$raw T answer_real, raw T answer_imagzo
    if (ind == minor) {
    atomicAdd(&answer_real[0], real);
    atomicAdd(&answer_imag[0], imag);
    }
    +cupyx_scipy_sparse_compress_getitem_complexc           
      C  sT   |||d  }t |d t |d }}|| }||| }| || }	|	||fS )aE  Return a submatrix of the input sparse matrix by slicing major axis.

    Args:
        Ax (cupy.ndarray): data array from input sparse matrix
        Aj (cupy.ndarray): indices array from input sparse matrix
        Ap (cupy.ndarray): indptr array from input sparse matrix
        start (int): starting index of major axis
        stop (int): ending index of major axis

    Returns:
        Bx (cupy.ndarray): data array of output sparse matrix
        Bj (cupy.ndarray): indices array of output sparse matrix
        Bp (cupy.ndarray): indptr array of output sparse matrix

       r   )int)
AxAjApstartstopstart_offsetstop_offsetBpBjBx r   O/home/ubuntu/vllm_env/lib/python3.10/site-packages/cupyx/scipy/sparse/_index.py_get_csr_submatrix_major_axis-   s   
r   c           
      C  sn   ||k||k @ }t j|jd |jd}d|d< ||dd< t j||d || }|| | }| | }	|	||fS )aE  Return a submatrix of the input sparse matrix by slicing minor axis.

    Args:
        Ax (cupy.ndarray): data array from input sparse matrix
        Aj (cupy.ndarray): indices array from input sparse matrix
        Ap (cupy.ndarray): indptr array from input sparse matrix
        start (int): starting index of minor axis
        stop (int): ending index of minor axis

    Returns:
        Bx (cupy.ndarray): data array of output sparse matrix
        Bj (cupy.ndarray): indices array of output sparse matrix
        Bp (cupy.ndarray): indptr array of output sparse matrix

    r
   dtyper   Nout)cupyemptysizer   cumsum)
r   r   r   r   r   maskmask_sumr   r   r   r   r   r   _get_csr_submatrix_minor_axisF   s   
r$   zNint32 out_rows, raw I rows, raw int32 Ap, raw int32 Aj, raw T Ax, raw int32 Bpzint32 Bj, T BxaD  
    const I row = rows[out_rows];

    // Look up starting offset
    const I starting_output_offset = Bp[out_rows];
    const I output_offset = i - starting_output_offset;
    const I starting_input_offset = Ap[row];

    Bj = Aj[starting_input_offset + output_offset];
    Bx = Ax[starting_input_offset + output_offset];
$cupyx_scipy_sparse_csr_row_index_kerc           
      C  sx   t |}t j|jd |jd}d|d< t j|| |dd d t|d }t||}t||||| |\}}	|	||fS )a  Populate indices and data arrays from the given row index
    Args:
        Ax (cupy.ndarray): data array from input sparse matrix
        Aj (cupy.ndarray): indices array from input sparse matrix
        Ap (cupy.ndarray): indptr array from input sparse matrix
        rows (cupy.ndarray): index array of rows to populate
    Returns:
        Bx (cupy.ndarray): data array of output sparse matrix
        Bj (cupy.ndarray): indices array of output sparse matrix
        Bp (cupy.ndarray): indptr array for output sparse matrix
    r
   r   r   Nr   r   )	r   diffr   r    r   r!   r   _csr_indptr_to_coo_rows_csr_row_index_ker)
r   r   r   rowsrow_nnzr   nnzout_rowsr   r   r   r   r   _csr_row_indexs   s   


r-   c                 C  sb   ddl m} tj| tjd}t }tj	r| dkrt
d|||jj| |jd |jj|j |S )Nr   )cusparser   z@hipSPARSE currently cannot handle sparse matrices with null ptrsr
   )cupy_backends.cuda.libsr.   r   r   numpyint32r   get_cusparse_handler   is_hip
ValueErrorxcsr2coodataptrr    CUSPARSE_INDEX_BASE_ZERO)r+   r   r.   r,   handler   r   r   r'      s   r'   c           
      C  s   t j| |d} t j||d}t || g}t ||}| | }|| }|| }t j|jdd}	t||||	|jd d ||	 ||	 ||	 fS )z;Find the unique indices for each row and keep only the lastr   boolr
   r    )r   asarraystacklexsortastypeonesr    _unique_mask_kern)
ijx	idx_dtypestackedorderindptr_insertsindices_insertsdata_insertsr"   r   r   r   _select_last_indices   s   
rK   zqraw I insert_indices, raw T insert_values, raw I insertion_indptr,
        raw I Ap, raw I Aj, raw T Ax, raw I Bpzraw I Bj, raw T Bxa  

        const I input_row_start = Ap[i];
        const I input_row_end = Ap[i+1];
        const I input_count = input_row_end - input_row_start;

        const I insert_row_start = insertion_indptr[i];
        const I insert_row_end = insertion_indptr[i+1];
        const I insert_count = insert_row_end - insert_row_start;

        I input_offset = 0;
        I insert_offset = 0;

        I output_n = Bp[i];

        I cur_existing_index = -1;
        T cur_existing_value = -1;

        I cur_insert_index = -1;
        T cur_insert_value = -1;

        if(input_offset < input_count) {
            cur_existing_index = Aj[input_row_start+input_offset];
            cur_existing_value = Ax[input_row_start+input_offset];
        }

        if(insert_offset < insert_count) {
            cur_insert_index = insert_indices[insert_row_start+insert_offset];
            cur_insert_value = insert_values[insert_row_start+insert_offset];
        }


        for(I jj = 0; jj < input_count + insert_count; jj++) {

            // if we have both available, use the lowest one.
            if(input_offset < input_count &&
               insert_offset < insert_count) {

                if(cur_existing_index < cur_insert_index) {
                    Bj[output_n] = cur_existing_index;
                    Bx[output_n] = cur_existing_value;

                    ++input_offset;

                    if(input_offset < input_count) {
                        cur_existing_index = Aj[input_row_start+input_offset];
                        cur_existing_value = Ax[input_row_start+input_offset];
                    }


                } else {
                    Bj[output_n] = cur_insert_index;
                    Bx[output_n] = cur_insert_value;

                    ++insert_offset;
                    if(insert_offset < insert_count) {
                        cur_insert_index =
                            insert_indices[insert_row_start+insert_offset];
                        cur_insert_value =
                            insert_values[insert_row_start+insert_offset];
                    }
                }

            } else if(input_offset < input_count) {
                Bj[output_n] = cur_existing_index;
                Bx[output_n] = cur_existing_value;

                ++input_offset;
                if(input_offset < input_count) {
                    cur_existing_index = Aj[input_row_start+input_offset];
                    cur_existing_value = Ax[input_row_start+input_offset];
                }

            } else {
                    Bj[output_n] = cur_insert_index;
                    Bx[output_n] = cur_insert_value;

                    ++insert_offset;
                    if(insert_offset < insert_count) {
                        cur_insert_index =
                            insert_indices[insert_row_start+insert_offset];
                        cur_insert_value =
                            insert_values[insert_row_start+insert_offset];
                    }
            }

            output_n++;
        }
    1cupyx_scipy_sparse_csr_copy_existing_indices_kern)	no_returnz#raw I rows, raw I cols, raw I orderzraw bool maskaT  
    I cur_row = rows[i];
    I next_row = rows[i+1];

    I cur_col = cols[i];
    I next_col = cols[i+1];

    I cur_order = order[i];
    I next_order = order[i+1];

    if(cur_row == next_row && cur_col == next_col) {
        if(cur_order < next_order)
            mask[i] = false;
        else
            mask[i+1] = false;
    }
    #cupyx_scipy_sparse_unique_mask_kernc                 C  sD   ||dk   | 7  < ||dk   |7  < t | ||||||||jd	S )a  Populate data array for a set of rows and columns
    Args
        n_row : total number of rows in input array
        n_col : total number of columns in input array
        Ap : indptr array for input sparse matrix
        Aj : indices array for input sparse matrix
        Ax : data array for input sparse matrix
        Bi : array of rows to extract from input sparse matrix
        Bj : array of columns to extract from input sparse matrix
    Returns
        Bx : data array for output sparse matrix
    r   r;   )_csr_sample_values_kernr    )n_rown_colr   r   r   Bir   not_found_valr   r   r   _csr_sample_values)  s   rT   zWI n_row, I n_col, raw I Ap, raw I Aj, raw T Ax,
    raw I Bi, raw I Bj, I not_found_valzraw T Bxat  
    const I j = Bi[i]; // sample row
    const I k = Bj[i]; // sample column
    const I row_start = Ap[j];
    const I row_end   = Ap[j+1];
    T x = 0;
    bool val_found = false;
    for(I jj = row_start; jj < row_end; jj++) {
        if (Aj[jj] == k) {
            x += Ax[jj];
            val_found = true;
        }
    }
    Bx[i] = val_found ? x : not_found_val;
)cupyx_scipy_sparse_csr_sample_values_kernc                   @  s   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*S )+
IndexMixinzS
    This class provides common dispatching and validation logic for indexing.
    c                 C  s  t rtjtjdk rtd| |\}}t|t	r@t|t	r&| 
||S t|tr1| ||S |jdkr<| ||S tdt|trxt|t	rP| ||S t|tri|td krc||krc|  S | ||S |jdkrt| ||S td|jdkrt|t	r| ||S t|tr| ||S n5t|t	r| ||S t|trtd|jd dkr|jdks|jd dkr| |d d df | S t||\}}|j|jkrtd|jdkr| jt|j| jdS | ||S )Nz1.4.0z,Sparse __getitem__() requires Scipy >= 1.4.0r
   zindex results in >2 dimensionsr   'number of row and column indices differr   ) scipy_availabler0   libNumpyVersionscipy__version__NotImplementedError_parse_indices
isinstance_int_scalar_types_get_intXintslice_get_intXslicendim_get_intXarray
IndexError_get_sliceXintcopy_get_sliceXslice_get_sliceXarray_get_arrayXint_get_arrayXsliceshape_get_columnXarrayravelr   broadcast_arraysr    	__class__
atleast_2dr   _get_arrayXarray)selfkeyrowcolr   r   r   __getitem__\  sZ   













&
zIndexMixin.__getitem__c           
      C  s  |  |\}}t|tr.t|tr.tj|| jd}|jdkr"td| |||j	d  d S t|t
rEtj|| jd  d d d f }nt|}t|t
rntj|| jd  d d d f }|jdkrm|d d d f }nt|}t||\}}|j|jkrtdt|r|jdkr|d  }|d  }|jd dko|jd dk}|jd dko|jd dk}|s|jd |jd kr|s|jd |jd kstd|jdkrd S |jdd}|  | ||| d S tj|| jd}t||\}}	|jdkrd S ||j}| ||| d S )	Nr   r
   z&Trying to assign a sequence to an itemr   rW   zshape mismatch in assignmentT)rh   )r^   r_   r`   r   r<   r   r    r4   _set_intXintflatrb   arangeindicesrm   
atleast_1drd   rp   rf   r   tocoosum_duplicates_set_arrayXarray_sparsereshape_set_arrayXarray)
rt   ru   rD   rv   rw   rB   rC   broadcast_rowbroadcast_col_r   r   r   __setitem__  sV   


$

"




zIndexMixin.__setitem__c                 C  s.   t |tjtjfr|jdkr|jdkrdS dS )Nr   r
   TF)r_   r   ndarrayr0   rd   r    )rt   indexr   r   r   
_is_scalar  s   zIndexMixin._is_scalarc                 C  s   | j \}}t|\}}| |r| }| |r| }t|tr)t||d}nt|ts4| ||}t|trCt||d}||fS t|tsN| ||}||fS )Nrv   column)	rm   _unpack_indexr   itemr_   r`   _normalize_indexrb   
_asindices)rt   ru   MNrv   rw   r   r   r   r^     s    






zIndexMixin._parse_indicesc              
   C  sN   zt j|| jjd}W n tttfy   tdw |jdvr#td|| S )a  Convert `idx` to a valid index for an axis with a given length.
        Subclasses that need special validation can override this method.

        idx is assumed to be at least a 1-dimensional array-like, but can
        have no more than 2 dimensions.
        r   zinvalid index)r
      zIndex dimension must be <= 2)	r   r<   r|   r   r4   	TypeErrorMemoryErrorrf   rd   )rt   idxlengthrD   r   r   r   r     s   
zIndexMixin._asindicesc                 C  s&   | j \}}t||d}| |tdS )zReturn a copy of row i of the matrix, as a (1 x n) row vector.

        Args:
            i (integer): Row

        Returns:
            cupyx.scipy.sparse.spmatrix: Sparse matrix with single row
        r   N)rm   r   rc   rb   rt   rB   r   r   r   r   r   getrow     
	zIndexMixin.getrowc                 C  s&   | j \}}t||d}| td|S )zReturn a copy of column i of the matrix, as a (m x 1) column vector.

        Args:
            i (integer): Column

        Returns:
            cupyx.scipy.sparse.spmatrix: Sparse matrix with single column
        r   N)rm   r   rg   rb   r   r   r   r   getcol   r   zIndexMixin.getcolc                 C     t  Nr]   rt   rv   rw   r   r   r   ra        zIndexMixin._get_intXintc                 C  r   r   r   r   r   r   r   re     r   zIndexMixin._get_intXarrayc                 C  r   r   r   r   r   r   r   rc     r   zIndexMixin._get_intXslicec                 C  r   r   r   r   r   r   r   rg     r   zIndexMixin._get_sliceXintc                 C  r   r   r   r   r   r   r   ri     r   zIndexMixin._get_sliceXslicec                 C  r   r   r   r   r   r   r   rj     r   zIndexMixin._get_sliceXarrayc                 C  r   r   r   r   r   r   r   rk     r   zIndexMixin._get_arrayXintc                 C  r   r   r   r   r   r   r   rl   "  r   zIndexMixin._get_arrayXslicec                 C  r   r   r   r   r   r   r   rn   %  r   zIndexMixin._get_columnXarrayc                 C  r   r   r   r   r   r   r   rs   (  r   zIndexMixin._get_arrayXarrayc                 C  r   r   r   rt   rv   rw   rD   r   r   r   ry   +  r   zIndexMixin._set_intXintc                 C  r   r   r   r   r   r   r   r   .  r   zIndexMixin._set_arrayXarrayc                 C  s6   t j| | jd}t ||\}}| ||| d S )Nr   )r   r<   toarrayr   rp   r   )rt   rv   rw   rD   r   r   r   r   r   1  s   z"IndexMixin._set_arrayXarray_sparseN)__name__
__module____qualname____doc__rx   r   r   r^   r   r   r   ra   re   rc   rg   ri   rj   rk   rl   rn   rs   ry   r   r   r   r   r   r   rV   W  s,    43rV   c                 C  s   t r	t| tjjS dS )NF)rX   r_   r[   sparser   )r   r   r   r   _try_is_scipy_spmatrix8  s   r   c                 C  sF  t | ttjtjfst| r| jdkr| jjdkr| 	 S t
| } t | trUt| dkr1| \}}nJt| dkrA| d td}}n:t| dkrQtdtd}}n*tdt| }|du re| td}}n|jdk rrt|tdfS |jdkr{|	 S t|st|rtdt|}t|}|durt|}|durt|}||fS )a   Parse index. Always return a tuple of the form (row, col).
    Valid type for row/col is integer, slice, or array of integers.

    Returns:
          resulting row & col indices : single integer, slice, or
          array of integers. If row & column indices are supplied
          explicitly, they are used as the major/minor indices.
          If only one index is supplied, the minor index is
          assumed to be all (e.g., [maj, :]).
    r   br
   r   Nzinvalid number of indiceszoIndexing with sparse matrices is not supported except boolean indexing where matrix and index are equal shapes.)r_   r   r   r   r0   r   rd   r   kindnonzero_eliminate_ellipsistuplelenrb   rf   _compatible_boolean_index_boolean_index_to_arrayr   )r   rv   rw   r   bool_rowbool_colr   r   r   r   >  sD   




r   c                 C  s   | t u rtdtdfS t| ts| S t| D ]\}}|t u r#|} nq| S t| dkr4tdtdfS t| dkr\|dkrT| d t u rLtdtdfS td| d fS | d tdfS g }| |d d D ]}|t urq|| qf|t| }tdd| }| d| tdf|  t| S )z6Process indices with Ellipsis. Returns modified index.Nr
   r   r   )Ellipsisrb   r_   r   	enumerater   appendmax)r   rC   vfirst_ellipsistailndnslicer   r   r   r   v  s4   

"r   c                 C  s6   | | k s	| |krt d|| | dk r| |7 } | S )Nz{} ({}) out of ranger   )rf   format)rD   dimnamer   r   r   r     s
   r   r   c                 C  sZ   |dk rdS zt | dkr| d nd}W n
 ty   Y dS w t|tr&dS t||d S )zQReturns True if first element of the incompatible
    array type is boolean.
    r
   Nr   T)r   r   r_   _bool_scalar_types_first_element_bool)r   max_dimfirstr   r   r   r     s   
r   c                 C  s8   t | dr| jjdkr| S dS t| rtj| ddS dS )ztReturns a boolean index array that can be converted to
    integer array. Returns None if no such array exists.
    rd   r   r:   r   N)hasattrr   r   r   r   r<   r   r   r   r   r     s   
r   c                 C  s0   | j dkr	tdtj| | jd} t| d S )Nr
   zinvalid index shaper   r   )rd   rf   r   arrayr   wherer   r   r   r   r     s   
r   )r   )r   ),r   
__future__r   r   r   cupyx.scipy.sparse._baser   r   	cupy.cudar   r   r0   scipy.sparser[   rX   ImportErrorr   integerint_r`   r:   bool_r   ElementwiseKernel_compress_getitem_kern_compress_getitem_complex_kernr   r$   r(   r-   r'   rK   _insert_many_populate_arraysrA   rT   rO   rV   r   r   r   r   r   r   r   r   r   r   r   <module>   s    

X_
 b8$
