
    Ed*                         d dl mZ ddlmZmZmZmZ ddlmZ 	 ddZ		 	 ddZ
efdZed	d	fd
Zed	fdZed	ddfdZdS )    )FunctionType   )_get_intermediate_simp_iszero_dotprodsimp	_simplify)_find_reasonable_pivotTc	                      fd}	 fd}
 fd}t          t                    d\  }}g }g }|k     r>||k     r7t           |	|          |d         ||          \  }}}}|D ]\  }}||z  }| |z  |z   <   ||dz  }U|                    |           |dk    r) |
|||z              |                    |||z   f           |du rJ||}}| |z  |z   <   t	          |z  |z   dz   |dz   z            D ]}  |         |z             |<   |}t	          |          D ]<}||k    r	|du r||k     r |z  |z            } ||          r. |||||           =|dz  }|k     r||k     7|d	u rk|d	u rgt          |          D ]W\  }} |z  |z            }| |z  |z   <   t	          |z  |z   dz   |dz   z            D ]}  |         |z             |<   X t          |          t          |          fS )
a  Row reduce a flat list representation of a matrix and return a tuple
    (rref_matrix, pivot_cols, swaps) where ``rref_matrix`` is a flat list,
    ``pivot_cols`` are the pivot columns and ``swaps`` are any row swaps that
    were used in the process of row reduction.

    Parameters
    ==========

    mat : list
        list of matrix elements, must be ``rows`` * ``cols`` in length

    rows, cols : integer
        number of rows and columns in flat list representation

    one : SymPy object
        represents the value one, from ``Matrix.one``

    iszerofunc : determines if an entry can be used as a pivot

    simpfunc : used to simplify elements and test if they are
        zero if ``iszerofunc`` returns `None`

    normalize_last : indicates where all row reduction should
        happen in a fraction-free manner and then the rows are
        normalized (so that the pivots are 1), or whether
        rows should be normalized along the way (like the naive
        row reduction algorithm)

    normalize : whether pivot rows should be normalized so that
        the pivot value is 1

    zero_above : whether entries above the pivot should be zeroed.
        If ``zero_above=False``, an echelon matrix will be returned.
    c                     | d          S N )icolsmats    9lib/python3.11/site-packages/sympy/matrices/reductions.pyget_colz!_row_reduce_list.<locals>.get_col,   s    17d7|    c                     |z  |dz   z           | z  | dz   z           c| z  | dz   z  <   |z  |dz   z  <   d S )Nr   r   )r   jr   r   s     r   row_swapz"_row_reduce_list.<locals>.row_swap/   so    $At|#$c!D&!a%*=&> 	;AdFAE4< #afa!eT\&9":":":r   c                     ||z
  z  }t          |z  |dz   z            D ](} | |         z  |||z            z  z
            |<   )dS )z,Does the row op row[i] = a*row[i] - b*row[j]r   N)range)	ar   br   qpr   isimpr   s	         r   cross_cancelz&_row_reduce_list.<locals>.cross_cancel3   sm    UDLqvAt|,, 	4 	4AU1SV8aAE
l233CFF	4 	4r   r   r   Nr   r   FT)r   r   r	   appendr   	enumeratetuple)r   rowsr   one
iszerofuncsimpfuncnormalize_last	normalize
zero_abover   r   r   piv_rowpiv_col
pivot_colsswapspivot_offset	pivot_valassumed_nonzeronewly_determinedoffsetvalr   r   r   rowpiv_ipiv_jr   s   ` `                         @r   _row_reduce_listr7      s_   J     ? ? ? ? ? ?4 4 4 4 4 4 4 #<00EGWJE D. ,Wt^ ,,B  *J-B -B	*i)
 . 	- 	-MVSgF),Ctg%&& 	qLG'"""1 	<HWlW4555LL'<'#9:;;; U" 	GqA!C$
O1T6A:>AE4<88 3 3s1v	122AI ;; 	7 	7Cg~ U" sW} c$h()Cz# LCg66661Y D. ,Wt^ ,^  3)t"3 3%j11 	3 	3LE5E$J./I&)Cd
U"#5:-1EAIt3CDD 3 3s1v	122A3 j!!5<<//r   c                     t          t          |           | j        | j        | j        |||||	  	        \  }}}|                     | j        | j        |          ||fS )Nr'   r(   r)   )r7   listr#   r   r$   _new)	Mr%   r&   r'   r(   r)   r   r,   r-   s	            r   _row_reducer=   y   sb     .d1ggqvqvquJ8 8 8CU 66!&!&#&&
E99r   c                    | j         dk    s| j        dk    rdS t          fd| dddf         D                       } | d                   r|ot          | ddddf                   S |ot          | ddddf                   S )zReturns `True` if the matrix is in echelon form. That is, all rows of
    zeros are at the bottom, and below each leading non-zero in a row are
    exclusively zeros.r   Tc              3   .   K   | ]} |          V  d S r   r   ).0tr%   s     r   	<genexpr>z_is_echelon.<locals>.<genexpr>   s+      66jjmm666666r   r   Nr   )r#   r   all_is_echelon)r<   r%   zeros_belows    ` r   rD   rD      s    
 	v{ afk t6666Qqrr1uX66666Kz!D' A@{1QQQU8Z@@@=;qQRRy*===r   Fc                     t          |t                    r|nt          }t          | ||ddd          \  }}}|r||fS |S )an  Returns a matrix row-equivalent to ``M`` that is in echelon form. Note
    that echelon form of a matrix is *not* unique, however, properties like the
    row space and the null space are preserved.

    Examples
    ========

    >>> from sympy import Matrix
    >>> M = Matrix([[1, 2], [3, 4]])
    >>> M.echelon_form()
    Matrix([
    [1,  2],
    [0, -2]])
    TFr9   
isinstancer   r   r=   )r<   r%   simplifywith_pivotsr&   r   pivots_s           r   _echelon_formrM      s_      &h==Lxx9H J5UD D DNC  F{Jr   c                    d }t          |t                    r|nt          }| j        dk    s| j        dk    rdS | j        dk    s| j        dk    rfd| D             }d|v rdS | j        dk    rW| j        dk    rLfd| D             }d|vrd|vrdS |                                 } |          rd|v rdS  |          du rdS  || 	          \  }}t          ||d
dd          \  }}	}t          |	          S )zReturns the rank of a matrix.

    Examples
    ========

    >>> from sympy import Matrix
    >>> from sympy.abc import x
    >>> m = Matrix([[1, 2], [x, 1 - 1/x]])
    >>> m.rank()
    2
    >>> n = Matrix(3, 3, range(1, 10))
    >>> n.rank()
    2
    c                       fdfdt           j                  D             }d t          |          D             }                     |d          |fS )a  Permute columns with complicated elements as
        far right as they can go.  Since the ``sympy`` row reduction
        algorithms start on the left, having complexity right-shifted
        speeds things up.

        Returns a tuple (mat, perm) where perm is a permutation
        of the columns to perform to shift the complex columns right, and mat
        is the permuted matrix.c                 N    t          fdd d | f         D                       S )Nc              3   6   K   | ]} |          dndV  d S )Nr   r   r   )r@   er%   s     r   rB   zO_rank.<locals>._permute_complexity_right.<locals>.complexity.<locals>.<genexpr>   s4      JJQJJqMM8qqqJJJJJJr   )sum)r   r<   r%   s    r   
complexityz<_rank.<locals>._permute_complexity_right.<locals>.complexity   s4     JJJJ!AAAqD'JJJJJJr   c                 *    g | ]} |          |fS r   r   )r@   r   rT   s     r   
<listcomp>z<_rank.<locals>._permute_complexity_right.<locals>.<listcomp>   s&    ===!JJqMM1%===r   c                     g | ]\  }}|S r   r   )r@   r   r   s      r   rV   z<_rank.<locals>._permute_complexity_right.<locals>.<listcomp>   s    333!Q1333r   r   )orientation)r   r   sortedpermute)r<   r%   complexpermrT   s   ``  @r   _permute_complexity_rightz(_rank.<locals>._permute_complexity_right   s    	K 	K 	K 	K 	K 	K
 >===uQV}}===336'??333		$F	33T::r   r   r   c                 &    g | ]} |          S r   r   r@   xr%   s     r   rV   z_rank.<locals>.<listcomp>   !    ***1A***r   F   c                 &    g | ]} |          S r   r   r_   s     r   rV   z_rank.<locals>.<listcomp>   ra   r   N)r%   Tr9   )rH   r   r   r#   r   detr=   len)
r<   r%   rI   r]   r&   zerosdr   rL   rK   s
    `        r   _rankrh      sz    ; ; ;( &h==Lxx9H
 	v{ afk qv{ afk *******E> 	1v{ qv{ ******* 	$e"3 	1EEGG:a== 	Ue^ 	1:a==E! 	1,,Q:FFFFCsJ/ / /LAvq v;;r   c                     t          |t                    r|nt          }t          | |||dd          \  }}}|r||f}|S )a'	  Return reduced row-echelon form of matrix and indices of pivot vars.

    Parameters
    ==========

    iszerofunc : Function
        A function used for detecting whether an element can
        act as a pivot.  ``lambda x: x.is_zero`` is used by default.

    simplify : Function
        A function used to simplify elements when looking for a pivot.
        By default SymPy's ``simplify`` is used.

    pivots : True or False
        If ``True``, a tuple containing the row-reduced matrix and a tuple
        of pivot columns is returned.  If ``False`` just the row-reduced
        matrix is returned.

    normalize_last : True or False
        If ``True``, no pivots are normalized to `1` until after all
        entries above and below each pivot are zeroed.  This means the row
        reduction algorithm is fraction free until the very last step.
        If ``False``, the naive row reduction procedure is used where
        each pivot is normalized to be `1` before row operations are
        used to zero above and below the pivot.

    Examples
    ========

    >>> from sympy import Matrix
    >>> from sympy.abc import x
    >>> m = Matrix([[1, 2], [x, 1 - 1/x]])
    >>> m.rref()
    (Matrix([
    [1, 0],
    [0, 1]]), (0, 1))
    >>> rref_matrix, rref_pivots = m.rref()
    >>> rref_matrix
    Matrix([
    [1, 0],
    [0, 1]])
    >>> rref_pivots
    (0, 1)

    ``iszerofunc`` can correct rounding errors in matrices with float
    values. In the following example, calling ``rref()`` leads to
    floating point errors, incorrectly row reducing the matrix.
    ``iszerofunc= lambda x: abs(x)<1e-9`` sets sufficiently small numbers
    to zero, avoiding this error.

    >>> m = Matrix([[0.9, -0.1, -0.2, 0], [-0.8, 0.9, -0.4, 0], [-0.1, -0.8, 0.6, 0]])
    >>> m.rref()
    (Matrix([
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0]]), (0, 1, 2))
    >>> m.rref(iszerofunc=lambda x:abs(x)<1e-9)
    (Matrix([
    [1, 0, -0.301369863013699, 0],
    [0, 1, -0.712328767123288, 0],
    [0, 0,         0,          0]]), (0, 1))

    Notes
    =====

    The default value of ``normalize_last=True`` can provide significant
    speedup to row reduction, especially on matrices with symbols.  However,
    if you depend on the form row reduction algorithm leaves entries
    of the matrix, set ``noramlize_last=False``
    T)r(   r)   rG   )	r<   r%   rI   rK   r'   r&   r   r,   rL   s	            r   _rrefrj      s^    R &h==Lxx9H$Q
Hdt= = =CQ   JJr   N)TTT)typesr   	utilitiesr   r   r   r   determinantr	   r7   r=   rD   rM   rh   rj   r   r   r   <module>rn      s         O O O O O O O O O O O O / / / / / / AEn0 n0 n0 n0d 9=+/: : : : & > > > >  !(%U    8  % C C C CL  %Q Q Q Q Q Qr   