o
    i7                     @   s   d dl 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l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 )    N)linalg)internal)device)_decomposition)_utilc                 C   s  ddl m} ddlm}m} | jdkr | jd | kr || |S t| | t	|  t
|  | j|jks>| j|jd krO| jdd |jd| jd  ksStdt| |\}}|jdkrgt|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_limit      NzEa must have (..., M, M) shape and b must have (..., M) or (..., M, K)TFcopyorderFr   Cdtype)cupyxr   cupy.cublasr   r	   ndimshaper   _assert_cupy_array_assert_stacked_2d_assert_stacked_square
ValueErrorlinalg_common_typesizecupyemptyastypegesv
empty_likerangenumpyprodunravel_index)abr   r   r	   r   	out_dtypexr   iindexbi r0   O/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/cupy/linalg/_solve.pysolve   s:   


"


r2   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ravelr2   )r)   r*   axesallaxeskoldshaper'   resultr0   r0   r1   tensorsolveT   s   




r>   c                 C   s0   | j j }t| } tjt| |ddS )Nr   axis)r   charlowerr    ascontiguousarraysumsquareview)r,   
real_dtyper0   r0   r1   _nrm2_last_axis}   s   
rH   warnc                 C   s  |dkrt dt d}t| | t|  |jdkr%td	|j| j
dd \}}|j
d }||kr<td	tjj| d
d\}}}|du rXt|jjt|| }n|dks`|dkrgt|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 )as  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): 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`
    rI   a
  `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.
To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.r   r
   zA{}-dimensional array given. Array must be at most two-dimensionalr   Nr   zIncompatible dimensionsFfull_matricesr   r   )r   )warningsrI   FutureWarningr   r   
_assert_2dr   r   LinAlgErrorformatr   r    svdr&   finfor   epsmaxarrayr   int32rD   dotTconjr!   
atleast_1drH   )r)   r*   rcondmnm2usvhs1rankcutoff	sing_valszr,   residser0   r0   r1   lstsq   sF   '




ri   c                 C   s   t |  t |  t |  | jdkrt| S t | \}}| jdkr+t	| j
|S | jr0dnd}| j|d|d} tj| j
d ||d}|dkrQtj| | n	tj| 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   Tr   )r   r   Fr   )r   r   r   r   r   _batched_invr   r   r    r!   r   _f_contiguousr"   eyer   r   r#   rX   )r)   r   r+   r   r*   r0   r0   r1   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"   r7   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_arrayr0   r0   r1   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   FrJ   r   r?   ).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   leqr0   r0   r1   pinvG  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'   r7   rn   )r)   indr<   invshaper'   a_invr0   r0   r1   	tensorinvu  s   

r   )N)rI   )r   )r
   )rL   r&   r   r    
cupy._corer   	cupy.cudar   cupy.linalgr   r   r   r2   r>   rH   ri   rn   rk   r   r   r0   r0   r0   r1   <module>   s"    
F)
[+
>.