o
    X۷i7                     @  s   d dl mZ d dl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	 Zdd
dZdd ZdddZdd Zdd ZdddZdddZdS )    )annotationsN)linalg)internal)device)_decomposition)_utilc                 C  s  ddl m} ddlm}m} t| | t|  t|  |j	dkr't
d|j	dkrD| jd |jkr8t
dt|| jdd }n| jdd |jdd krVt
d	| j	d
krh| jd | krh|| |S t| |\}}|jdkr|t|j|S | j	d
kr| j|ddd} |j|ddd}|| | |j|ddS | j|ddd} tj||d}| jdd }tt|D ]}	t|	|}
||
 j|ddd}|| |
 | |||
< q|S )a"  Solves a linear matrix equation.

    It computes the exact solution of ``x`` in ``ax = b``,
    where ``a`` is a square and full rank matrix.

    Args:
        a (cupy.ndarray): The matrix with dimension ``(..., M, M)``.
        b (cupy.ndarray): The matrix with dimension ``(M,)`` or
            ``(..., M, K)``.

    Returns:
        cupy.ndarray:
            The matrix with dimension ``(..., M)`` or ``(..., M, 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.solve`
    r   lapack)batched_gesvget_batched_gesv_limitz"b must have at least one dimension   zHa must have (..., M, M) shape and b must have (M,) for one-dimensional bNzPa must have (..., M, M) shape and b must have (..., M, K) for multidimensional b   TFcopyorderFr   Cdtype)cupyxr	   cupy.cublasr
   r   r   _assert_cupy_array_assert_stacked_2d_assert_stacked_squarendim
ValueErrorshapesizecupybroadcast_tolinalg_common_typeemptyastypegesv
empty_likerangenumpyprodunravel_index)abr	   r
   r   r   	out_dtypexr   iindexbi r3   H/home/ubuntu/vllm_env/lib/python3.10/site-packages/cupy/linalg/_solve.pysolve   sH   







r5   c                 C  s   |dur!t t| j}|D ]}|| || j| q| |} | j| j|j  d }t|}| 	d|} |
 }t| |}|	|S )a  Solves tensor equations denoted by ``ax = b``.

    Suppose that ``b`` is equivalent to ``cupy.tensordot(a, x)``.
    This function computes tensor ``x`` from ``a`` and ``b``.

    Args:
        a (cupy.ndarray): The tensor with ``len(shape) >= 1``
        b (cupy.ndarray): The tensor with ``len(shape) >= 1``
        axes (tuple of ints): Axes in ``a`` to reorder to the right
            before inversion.

    Returns:
        cupy.ndarray:
            The tensor with shape ``Q`` such that ``b.shape + Q == a.shape``.

    .. 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.tensorsolve`
    Nr   )listr(   r   removeinsert	transposer   r   r*   reshaperavelr5   )r,   r-   axesallaxeskoldshaper*   resultr3   r3   r4   tensorsolveW   s   




rA   c                 C  s0   | j j }t| } tjt| |ddS )Nr   axis)r   charlowerr!   ascontiguousarraysumsquareview)r/   
real_dtyper3   r3   r4   _nrm2_last_axis   s   
rK   c                 C  s|  t | | t |  |jdkrtd|j| jdd \}}|jd }||kr0tdtjj	| dd\}}}|du rLt
|jjt|| }n|dksT|d	kr[t
|jj}d	| }	t|jt
j}
|jdkr||  }||k}d|	|< |
|jt
jd
8 }
t|j| |	 j}t|j |}||ks|
|krtjd|jd
}n|| | }tt|j}|||
|fS )a}  Return the least-squares solution to a linear matrix equation.

    Solves the equation `a x = b` by computing a vector `x` that
    minimizes the Euclidean 2-norm `|| b - a x ||^2`.  The equation may
    be under-, well-, or over- determined (i.e., the number of
    linearly independent rows of `a` can be less than, equal to, or
    greater than its number of linearly independent columns).  If `a`
    is square and of full rank, then `x` (but for round-off error) is
    the "exact" solution of the equation.

    Args:
        a (cupy.ndarray): "Coefficient" matrix with dimension ``(M, N)``
        b (cupy.ndarray): "Dependent variable" values with dimension ``(M,)``
            or ``(M, K)``
        rcond (float, optional): Cutoff parameter for small singular values.
            For stability it computes the largest singular value denoted by
            ``s``, and sets all singular values smaller than ``s`` to zero.

    Returns:
        tuple:
            A tuple of ``(x, residuals, rank, s)``. Note ``x`` is the
            least-squares solution with shape ``(N,)`` or ``(N, K)`` depending
            if ``b`` was two-dimensional. The sums of ``residuals`` is the
            squared Euclidean 2-norm for each column in b - a*x. The
            ``residuals`` is an empty array if the rank of a is < N or M <= N,
            but  iff b is 1-dimensional, this is a (1,) shape array, Otherwise
            the shape is (K,). The ``rank`` of matrix ``a`` is an integer. The
            singular values of ``a`` are ``s``.

    .. 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.lstsq`
    r   zA{}-dimensional array given. Array must be at most two-dimensionalr   Nr   zIncompatible dimensionsFfull_matricesr   r   )r   )r   r   
_assert_2dr   r   LinAlgErrorformatr   r!   svdr)   finfor   epsmaxarrayr    int32rG   dotTconjr$   
atleast_1drK   )r,   r-   rcondmnm2usvhs1rankcutoff	sing_valszr/   residser3   r3   r4   lstsq   s:   '




ri   c                 C  s   ddl m} t|  t|  t|  | jdkrt| S t| \}}| j	dkr1t
| j|S | jr6dnd}| j|d|d} t
j| jd ||d}|dkrV|| | n|| j|j |j|d	d
S )a  Computes the inverse of a matrix.

    This function computes matrix ``a_inv`` from n-dimensional regular matrix
    ``a`` such that ``dot(a, a_inv) == eye(n)``.

    Args:
        a (cupy.ndarray): The regular matrix

    Returns:
        cupy.ndarray: The inverse of a matrix.

    .. 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.inv`
    r   r      r   r   Tr   )r   r   Fr   )r   r	   r   r   r   r   r   _batched_invr#   r    r!   r$   r   _f_contiguousr%   eyer&   rX   )r,   r	   r   r.   r   r-   r3   r3   r4   inv   s    




rn   c              
   C  s4  t | \}}| jdkrt| j|S |tjkr#tjjj	}tjjj
}n:|tjkr3tjjj}tjjj}n*|tjkrCtjjj}tjjj}n|tjkrStjjj}tjjj}n
d| j}t|d| jv ritj| |dS | j}| j|ddd|d |d } t }| jd }| jd }	|	}
|	|
 | j }| jj}|||  }tj|||tj d}tj||	ftj!d}tj|ftj!d}|||	|jj|
|jj|jj| tj"j #|| t| }|
}|	| |j }|jj}|||  }tj|||tj d}|||	|jj|
|jj|jj||jj|	 tj"j #|| ||j|d	d
S )Nr   zDdtype must be float32, float64, complex64 or complex128 (actual: {})r   r   )r   r   r   r   Fr   )$r   r#   r    r!   r$   r   float32cudacublassgetrfBatchedsgetriBatchedfloat64dgetrfBatcheddgetriBatched	complex64cgetrfBatchedcgetriBatched
complex128zgetrfBatchedzgetriBatchedrP   r   r   r'   r%   r:   r   get_cublas_handleitemsizedataptrarangeuintprV   r   3_check_cublas_info_array_if_synchronization_allowed)r,   r   r.   getrfgetrimsga_shapehandle
batch_sizer]   ldastepstartstopa_arraypivot_array
info_arraycldcc_arrayr3   r3   r4   rk     sh   









 


rk   V瞯<c                 C  s   t |  | jdkr5t | \}}| jdd \}}|dks"|dkr%| j}tj| jdd ||f |dS tj	| 
 dd\}}}|tj|dd }	||	d	 k}
tj||d
 d||
< t|dd|d	 |dd S )ak  Compute the Moore-Penrose pseudoinverse of a matrix.

    It computes a pseudoinverse of a matrix ``a``, which is a generalization
    of the inverse matrix with Singular Value Decomposition (SVD).
    Note that it automatically removes small singular values for stability.

    Args:
        a (cupy.ndarray): The matrix with dimension ``(..., M, N)``
        rcond (float or cupy.ndarray): Cutoff parameter for small singular
            values. For stability it computes the largest singular value
            denoted by ``s``, and sets all singular values smaller than
            ``rcond * s`` to zero. Broadcasts against the stack of matrices.

    Returns:
        cupy.ndarray: The pseudoinverse of ``a`` with dimension
        ``(..., N, M)``.

    .. 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.pinv`
    r   r   Nr   FrL   r   rB   ).N)out)r   r   r    r#   r   r   r!   r$   r   rQ   rY   amax
reciprocalmatmulswapaxes)r,   r[   _r.   r\   r]   r_   r`   vtrd   leqr3   r3   r4   pinv@  s   

 $r   r   c                 C  sh   t |  |dkrtd| j}||d |d|  }t||d }| |d} t| }|j| S )a  Computes the inverse of a tensor.

    This function computes tensor ``a_inv`` from tensor ``a`` such that
    ``tensordot(a_inv, a, ind) == I``, where ``I`` denotes the identity tensor.

    Args:
        a (cupy.ndarray):
            The tensor such that
            ``prod(a.shape[:ind]) == prod(a.shape[ind:])``.
        ind (int):
            The positive number used in ``axes`` option of ``tensordot``.

    Returns:
        cupy.ndarray:
            The inverse of a tensor whose shape is equivalent to
            ``a.shape[ind:] + a.shape[:ind]``.

    .. 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.tensorinv`
    r   zInvalid ind argumentNr   )r   r   r   r   r   r*   r:   rn   )r,   indr?   invshaper*   a_invr3   r3   r4   	tensorinvn  s   

r   )N)r   )r   )
__future__r   r)   r   r!   
cupy._corer   	cupy.cudar   cupy.linalgr   r   r5   rA   rK   ri   rn   rk   r   r   r3   r3   r3   r4   <module>   s     
J)
P,
>.