o
    X۷i8                     @  s   d dl m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dZd"ddZejddddZdd Zdd Zd#ddZdd Zd#ddZdd  ZdS )$    )annotationsN)device)runtime)_util)_dtypedtypenumpy.dtype | strreturnNonec                 C  s&   t | tjr	| j} | dvrtdd S )NfdFD>Only float32, float64, complex64, and complex128 are supported)
isinstancenumpyr   charRuntimeErrorr    r   M/home/ubuntu/vllm_env/lib/python3.10/site-packages/cupy/linalg/_eigenvalue.py_check_dtype   s   r   Fc                 C  sl  ddl m} ddl m} |dvrtdtj| dd\}}|j }|j }	| j|d| d	}
| j	\}}t
||}t
d
tj}t j}|rM|j}n|j}|dkrX|j}n|j}tjst| t|}t|}| }zF||||||||
jj|||jj|\}}t
|d}t|d}||||||||
jj|||jj||jj||jj||jj W | | n| | w t
j!j"|j| na|dkr|j#}|j$}n%|dkr|j%}|j&}n|dkr|j'}|j(}n|dkr|j)}|j*}nt+d||||||
jj||jj}t
||}||||||
jj||jj|jj||jj
 t
j!j"|| |j|	dd|
j|ddfS )Nr   )cublascusolver)LUz UPLO argument must be 'L' or 'U'F)reject_float16Fordercopyr   r   bfdDr   )r   ),cupy_backends.cuda.libsr   r   
ValueErrorr   linalg_common_typer   lowerastypeshapecupyemptyr   int32r   Devicecusolver_handleCUSOLVER_EIG_MODE_VECTORCUSOLVER_EIG_MODE_NOVECTORCUBLAS_FILL_MODE_LOWERCUBLAS_FILL_MODE_UPPERr   is_hipr   r   to_cuda_dtypecreateParamsxsyevd_bufferSizedataptrxsyevdctypesdestroyParamslinalg3_check_cusolver_dev_info_if_synchronization_allowedssyevd_bufferSizessyevddsyevd_bufferSizedsyevdcheevd_bufferSizecheevdzheevd_bufferSizezheevdr   )aUPLOwith_eigen_vectoroverwrite_ar   r   r   v_dtype
real_dtypew_dtypevmldawdev_infohandlejobzuplotype_vtype_wparamswork_device_sizework_host_sizsework_device	work_hostbuffer_sizesyevd	work_sizeworkr   r   r   _syevd   s   







r_   zuint64 n, raw C w, raw R v_realzraw C v_complexa  
        int col_idx = i % n;
        auto ew_i       = w[col_idx].imag();
        // if img == 0 -> ev = ev[i]
        // if img positive -> ev = ev[i] + i*ev[i+1]
        // if img negative -> ev = ev[i-1] - i*ev[i]
        int real_idx = i - ((ew_i < 0) ? 1 : 0);
        int img_idx  = i + ((ew_i > 0) ? 1 : 0);
        R factor     = ((ew_i > 0) ? R(1.0) : ((ew_i < 0) ? R(-1.0) : R(0.0)));
        v_complex[i].real(v_real[real_idx]);
        v_complex[i].imag(factor * v_real[img_idx]);
     cupy_assemble_complex_evs_kernelc                 C  s&   t | }t|| ||| d}||S )N)size)len_assemble_complex_evs_kernelreshape)rO   v_realr(   n	v_complexr   r   r   _assemble_complex_evsx   s   
rh   c                 C  s4  ddl m} ddlm} ddlm} |dstdtjr!t	dt
| \}}t| t|j }t| dd	jd
d} || jkrM| j|d
dd}n| }| jdd  \}	}
tj| jd d	 |d}tj| |d}||k}|r{tj|	|	f|dd}tdtj}t j}|r|j}n|j}|j}t|}t|}|  }z|r|n|}|!|||||	||j"j#|
||j"j#||j"j#|
||j"j#|
|\}}t|d}||d}t$| jdkr/t%| jd d D ]I}|| }|| }|r|n|| }|&|||||	||j"j#|
||j"j#||j"j#|
||j"j#|
||j"j#||j'j"||j"j# |r-|r-t(|||j||< qn5|&|||||	||j"j#|
||j"j#||j"j#|
||j"j#|
||j"j#||j'j"||j"j# |rd|rdt(|||j}W |)| n|)| w tj*j
+|j&| t| dd	jd
d} |r|st|dd	jd
d}||fS )Nr   r   )check_availability)empty_pinnedgeevzgeev is not availablezgeev is not implemented for HIPC)r   Tr   r   r   )r   r   r   r      ),r#   r   cupyx.cusolverri   cupyxrj   r   r   r2   NotImplementedErrorr   r%   r   r   r   r   upperr)   swapaxesr   r'   r(   r*   
empty_liker+   r   r,   r-   r.   r/   r   r3   r4   xgeev_bufferSizer6   r7   rb   ndindexxgeevr9   rh   r:   r;   r<   )rE   rG   r   ri   rj   input_dtype_complex_dtypea_rM   rN   rO   rL   
real_inputre   rP   rQ   jobvrjobvltype_complex
type_inputrV   v_rW   work_host_sizerY   rZ   inda_indw_indv_indr   r   r   _geev~   s   






r   r   c                 C  s   ddl }t|  t|  | jdkr5t| \}}|j }t	| j
dd |}t	| j
|}||fS | jdks=tjrK|j| |d\}}||fS t| |dS )a  
    Return the eigenvalues and eigenvectors of a complex Hermitian
    (conjugate symmetric) or a real symmetric matrix.

    Returns two objects, a 1-D array containing the eigenvalues of `a`, and
    a 2-D square array or matrix (depending on the input type) of the
    corresponding eigenvectors (in columns).

    Args:
        a (cupy.ndarray): A symmetric 2-D square matrix ``(M, M)`` or a batch
            of symmetric 2-D square matrices ``(..., M, M)``.
        UPLO (str): Select from ``'L'`` or ``'U'``. It specifies which
            part of ``a`` is used. ``'L'`` uses the lower triangular part of
            ``a``, and ``'U'`` uses the upper triangular part of ``a``.
    Returns:
        tuple of :class:`~cupy.ndarray`:
            Returns a tuple ``(w, v)``. ``w`` contains eigenvalues and
            ``v`` contains eigenvectors. ``v[:, i]`` is an eigenvector
            corresponding to an eigenvalue ``w[i]``. For batch input,
            ``v[k, :, i]`` is an eigenvector corresponding to an eigenvalue
            ``w[k, i]`` of ``a[k]``.

    .. warning::
        This function calls one or more cuSOLVER routine(s) which may yield
        invalid results if input conditions are not met.
        To detect these invalid results, you can set the `linalg`
        configuration to a value that is not `ignore` in
        :func:`cupyx.errstate` or :func:`cupyx.seterr`.

    .. seealso:: :func:`numpy.linalg.eigh`
    r   Nrm   ro   Trp   r   _assert_stacked_2d_assert_stacked_squarera   r%   r   r&   r)   r*   r(   ndimr   r2   r   syevjr_   )rE   rF   rq   rz   rI   rK   rO   rL   r   r   r   eigh   s    



r   c                 C  sb   t |  t |  | jdkr,t | \}}t| jdd |}t| j|}||fS t| dS )a  
    Return the eigenvalues and eigenvectors of a matrix.

    Returns two objects, a 1-D array containing the eigenvalues of `a`, and
    a 2-D square array or matrix (depending on the input type) of the
    corresponding eigenvectors (in columns).

    Args:
        a (cupy.ndarray): A symmetric 2-D square matrix ``(M, M)`` or a batch
            of symmetric 2-D square matrices ``(..., M, M)``.
    Returns:
        tuple of :class:`~cupy.ndarray`:
            Returns a tuple ``(w, v)``. ``w`` contains eigenvalues and
            ``v`` contains eigenvectors. ``v[:, i]`` is an eigenvector
            corresponding to an eigenvalue ``w[i]``. For batch input,
            ``v[k, :, i]`` is an eigenvector corresponding to an eigenvalue
            ``w[k, i]`` of ``a[k]``.
    Notes:
        There is no guarantee of the order of the eigenvalues:
        it can even be different from ``numpy.linalg.eig``.

    .. warning::
        This function calls one or more cuSOLVER routine(s) which may yield
        invalid results if input conditions are not met.
        To detect these invalid results, you can set the `linalg`
        configuration to a value that is not `ignore` in
        :func:`cupyx.errstate` or :func:`cupyx.seterr`.

    .. seealso:: :func:`numpy.linalg.eig`
    r   Nrm   T	r   r   r   ra   r%   r)   r*   r(   r   )rE   rz   rI   rO   rL   r   r   r   eig  s   



r   c                 C  s   ddl }t|  t|  | jdkr*t| \}}|j }t	| j
dd |S | jdks2tjr:|j| |dS t| |dd S )a-  
    Compute the eigenvalues of a complex Hermitian or real symmetric matrix.

    Main difference from eigh: the eigenvectors are not computed.

    Args:
        a (cupy.ndarray): A symmetric 2-D square matrix ``(M, M)`` or a batch
            of symmetric 2-D square matrices ``(..., M, M)``.
        UPLO (str): Select from ``'L'`` or ``'U'``. It specifies which
            part of ``a`` is used. ``'L'`` uses the lower triangular part of
            ``a``, and ``'U'`` uses the upper triangular part of ``a``.
    Returns:
        cupy.ndarray:
            Returns eigenvalues as a vector ``w``. For batch input,
            ``w[k]`` is a vector of eigenvalues of matrix ``a[k]``.

    .. warning::
        This function calls one or more cuSOLVER routine(s) which may yield
        invalid results if input conditions are not met.
        To detect these invalid results, you can set the `linalg`
        configuration to a value that is not `ignore` in
        :func:`cupyx.errstate` or :func:`cupyx.seterr`.

    .. seealso:: :func:`numpy.linalg.eigvalsh`
    r   Nrm   ro   Fr   )rE   rF   rq   rz   rI   rK   r   r   r   eigvalsh=  s   



r   c                 C  sT   t |  t |  | jdkr#t | \}}t| jdd |}|S t| dd S )a  
    Compute the eigenvalues of a matrix.

    Main difference from eig: the eigenvectors are not computed.

    Args:
        a (cupy.ndarray): A symmetric 2-D square matrix ``(M, M)`` or a batch
            of symmetric 2-D square matrices ``(..., M, M)``.
    Returns:
        cupy.ndarray:
            Returns eigenvalues as a vector ``w``. For batch input,
            ``w[k]`` is a vector of eigenvalues of matrix ``a[k]``.
    Notes:
        There is no guarantee of the order of the eigenvalues:
        it can even be different from ``numpy.linalg.eigvals``.

    .. warning::
        This function calls one or more cuSOLVER routine(s) which may yield
        invalid results if input conditions are not met.
        To detect these invalid results, you can set the `linalg`
        configuration to a value that is not `ignore` in
        :func:`cupyx.errstate` or :func:`cupyx.seterr`.

    .. seealso:: :func:`numpy.linalg.eigvals`
    r   Nrm   Fr   )rE   rz   rI   rO   r   r   r   eigvalsf  s   


r   )r   r   r	   r
   )F)r   )
__future__r   r   r)   	cupy.cudar   r   cupy.linalgr   
cupy._corer   r   r_   _coreElementwiseKernelrc   rh   r   r   r   r   r   r   r   r   r   <module>   s(    

	P
b2
+)