o
    i(                     @   s   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Zdd Zeddd	d Z	ed
ddd Z
dddZdd ZdddZdd ZdddZdS )    N)_core)_decomposition)_utilc                 C   s,   t | ||fd}|tj|dddd}|S )N)F
compute_uvr   axis)cupymoveaxisr   svd)xrow_axiscol_axisopyresult r   O/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/cupy/linalg/_norms.py_multi_svd_norm   s   r   
_norm_ord2)z?->lzb->lzB->Lzh->lzH->Lzi->lzI->Lzl->lzL->Lzq->qzQ->Q)ze->e)NNNfloatzf->fzd->d)z	in0 * in0a + bout0 = sqrt(type_out0_raw(a))N_norm_ord2_complex)zF->fzD->d)z1in0.real() * in0.real() + in0.imag() * in0.imag()r   r   NFc                 C   sl  t | jjtjs| t} |du rT| j}|du s(|dkr |dks(|dkrT|dv rT| jjdkr@t	| 
 }||9 }t| }n	t| |   }|rR|d| }|S | j}|du rbtt|}nt|ts|zt|}W n tyx   tdw |f}t|dkr|tjkrt	| j||dS |tj krt	| j||dS |d	kr| d	k| jjj||dS |dkrt	| j||dS |du s|dkr| jjdkrt| ||dS t| ||dS zt| W n ty   td
w t	| }||C }|j||d}|tj||jdC }|S t|dkr2|\}	}
|	d	k r|	|7 }	|
d	k r%|
|7 }
d	|	  kr1|k r@n nd	|
  kr?|k sIn td|| jf |	|
krRtd|dkrgtj tj!d	d}t"| |	|
|}n|dkr|tj tj!dd}t"| |	|
|}n|dkr|
|	kr|
d8 }
t	| j|	dj|
d}n|tjkr|	|
kr|	d8 }	t	| j|
dj|	d}nd|dkr|
|	kr|
d8 }
t	| j|	dj|
d}nI|tj kr|	|
kr|	d8 }	t	| j|
dj|	d}n,|dv r| jjdkrt| |d}nt| |d}n|dkrt"| |	|
tj}ntd|r0t#| j}d||d	 < d||d < ||}|S td)a  Returns one of matrix norms specified by ``ord`` parameter.

    See numpy.linalg.norm for more detail.

    Args:
        x (cupy.ndarray): Array to take norm. If ``axis`` is None,
            ``x`` must be 1-D or 2-D.
        ord (non-zero int, inf, -inf, 'fro'): Norm type.
        axis (int, 2-tuple of ints, None): 1-D or 2-D norm is cumputed over
            ``axis``.
        keepdims (bool): If this is set ``True``, the axes which are normed
            over are left.

    Returns:
        cupy.ndarray

    N      )ffroc)r   z6'axis' must be None, an integer or a tuple of integersr
   keepdimsr   zInvalid norm order for vectors.)dtypez*Invalid axis %r for an array with shape %rzDuplicate axes given.)indicesr   r   r	   )Nr   r   nucz Invalid norm order for matrices.z&Improper number of dimensions to norm.)$
issubclassr#   typenumpyinexactastyper   ndimkindabsravelr   sqrtsumreshapetuplerange
isinstanceint	Exception	TypeErrorleninfmaxminrealr   r   
ValueError
reciprocalshape	functoolspartialtaker   list)r   ordr
   r"   r+   sretndabsxr   r   op_maxop_min	ret_shaper   r   r   norm   s   




6












rL   c                 C   s   t | \}}|t| S )a  Returns the determinant of an array.

    Args:
        a (cupy.ndarray): The input matrix with dimension ``(..., N, N)``.

    Returns:
        cupy.ndarray: Determinant of ``a``. Its shape is ``a.shape[:-2]``.

    .. seealso:: :func:`numpy.linalg.det`
    )slogdetr   exp)asignlogdetr   r   r   det   s   rR   c                 C   st   | j dk r| dk tS tj| dd}|du r0|jdddt| jd	d  t	|j
j }||kjdtjd
S )aB  Return matrix rank of array using SVD method

    Args:
        M (cupy.ndarray): Input array. Its `ndim` must be less than or equal to
            2.
        tol (None or float): Threshold of singular value of `M`.
            When `tol` is `None`, and `eps` is the epsilon value for datatype
            of `M`, then `tol` is set to `S.max() * max(M.shape) * eps`,
            where `S` is the singular value of `M`.
            It obeys :func:`numpy.linalg.matrix_rank`.

    Returns:
        cupy.ndarray: Rank of `M`.

    .. seealso:: :func:`numpy.linalg.matrix_rank`
    r   r   Fr   Nr   Tr!   r   )r
   r#   )r+   anyr*   r5   r   r   r:   r?   r(   finfor#   epsr0   intp)MtolSr   r   r   matrix_rank   s   
rZ   c                 C   sx  t |  t |  t | \}}t|j }| j}|dd }|d }| j	dkr;t
||}t
||}||fS t| |\}	}
}t
j|	ddd}t
t
|jdd}t
j|
t
d|d kdd}|jdkrw|t
j|dk dd7 }|d	 d d }|jd
kr|t
j|t
| dd }||}|j|dd}|dk}t
||d||t
||d||fS )a  Returns sign and logarithm of the determinant of an array.

    It calculates the natural logarithm of the determinant of a given value.

    Args:
        a (cupy.ndarray): The input matrix with dimension ``(..., N, N)``.

    Returns:
        tuple of :class:`~cupy.ndarray`:
            It returns a tuple ``(sign, logdet)``. ``sign`` represents each
            sign of the determinant as a real number ``0``, ``1`` or ``-1``.
            'logdet' represents the natural logarithm of the absolute of the
            determinant.
            If the determinant is zero, ``sign`` will be ``0`` and ``logdet``
            will be ``-inf``.
            The shapes of both ``sign`` and ``logdet`` are equal to
            ``a.shape[:-2]``.

    .. 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`.

    .. warning::
        To produce the same results as :func:`numpy.linalg.slogdet` for
        singular inputs, set the `linalg` configuration to `raise`.

    .. seealso:: :func:`numpy.linalg.slogdet`
    Nr   r   r   )axis1axis2r	   r   r   r   r    F)copyz-inf)r   _assert_stacked_2d_assert_stacked_squarelinalg_common_typer(   r#   charlowerr?   sizer   oneszerosr   
_lu_factordiagonallogr-   r0   count_nonzeroaranger,   prodr*   wherer'   r1   )rO   r#   
sign_dtypelogdet_dtypea_shaper?   nrP   rQ   luipivdev_infodiagnon_zerosingularr   r   r   rM      s4   
 




rM   r   c                 C   s   |  |||||S )a  Returns the sum along the diagonals of an array.

    It computes the sum along the diagonals at ``axis1`` and ``axis2``.

    Args:
        a (cupy.ndarray): Array to take trace.
        offset (int): Index of diagonals. Zero indicates the main diagonal, a
            positive value an upper diagonal, and a negative value a lower
            diagonal.
        axis1 (int): The first axis along which the trace is taken.
        axis2 (int): The second axis along which the trace is taken.
        dtype: Data type specifier of the output.
        out (cupy.ndarray): Output array.

    Returns:
        cupy.ndarray: The trace of ``a`` along axes ``(axis1, axis2)``.

    .. seealso:: :func:`numpy.trace`

    )trace)rO   offsetr[   r\   r#   outr   r   r   rw     s   rw   )NNF)N)r   r   r   NN)r(   r   r   cupy.linalgr   r   r@   r   create_reduction_funcr   r   rL   rR   rZ   rM   rw   r   r   r   r   <module>   s0    
 
N