
    \h%                         S r SSKJrJrJrJrJr  SSKJr  SSK	J
r
  SSKJr  SSKJr  SSKJrJrJr  SS	KJr  SS
KJr  \
S:w  a  SS/r " S S\5      rS rS rS rS rS rS rS r S r!S r"S r#S r$S r%g)z

Module for the SDM class.

    )addnegpossubmul)defaultdict)GROUND_TYPES)doctest_depends_on)_strongly_connected_components   )DMBadInputErrorDMDomainErrorDMShapeError)QQ)DDMflintz
SDM.to_dfmzSDM.to_dfm_or_ddmc                     ^  \ rS rSrSrSrSrSrU 4S jrS r	S r
S rS	 rS
 rS r\S 5       rS r\S 5       r\S 5       rS rS r\S 5       rS r\S 5       rS r\S 5       rS r\S 5       rS rS rS rS r \!" S/S9S 5       r"\!" S/S9S  5       r#\S! 5       r$\S" 5       r%\S# 5       r&\SNS$ j5       r'S% r(S& r)S' r*S( r+S) r,S* r-S+ r.S, r/S- r0S. r1S/ r2S0 r3S1 r4S2 r5S3 r6S4 r7S5 r8S6 r9S7 r:S8 r;S9 r<S: r=S; r>S< r?S= r@SNS> jrAS? rBS@ rCSA rDSB rESC rFSD rGSE rHSF rISG rJSH rK\L" SISJ5      4SK jrM\L" SISJ5      4SL jrNSMrOU =rP$ )OSDM   ac  Sparse matrix based on polys domain elements

This is a dict subclass and is a wrapper for a dict of dicts that supports
basic matrix arithmetic +, -, *, **.


In order to create a new :py:class:`~.SDM`, a dict
of dicts mapping non-zero elements to their
corresponding row and column in the matrix is needed.

We also need to specify the shape and :py:class:`~.Domain`
of our :py:class:`~.SDM` object.

We declare a 2x2 :py:class:`~.SDM` matrix belonging
to QQ domain as shown below.
The 2x2 Matrix in the example is

.. math::
       A = \left[\begin{array}{ccc}
            0 & \frac{1}{2} \\
            0 & 0 \end{array} \right]


>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> elemsdict = {0:{1:QQ(1, 2)}}
>>> A = SDM(elemsdict, (2, 2), QQ)
>>> A
{0: {1: 1/2}}

We can manipulate :py:class:`~.SDM` the same way
as a Matrix class

>>> from sympy import ZZ
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> B  = SDM({0:{0: ZZ(3)}, 1:{1:ZZ(4)}}, (2, 2), ZZ)
>>> A + B
{0: {0: 3, 1: 2}, 1: {0: 1, 1: 4}}

Multiplication

>>> A*B
{0: {1: 8}, 1: {0: 3}}
>>> A*ZZ(2)
{0: {1: 4}, 1: {0: 2}}

sparseFc                   >^^ [         TU ]  U5        U=U l        =u  U l        U l        u  mmX0l        [        U4S jU  5       5      (       d  [        S5      e[        U4S jU R                  5        5       5      (       d  [        S5      eg )Nc              3   N   >#    U  H  nS Us=:*  =(       a    T:  Os  v   M     g7fr   N ).0rms     P/var/www/auris/envauris/lib/python3.13/site-packages/sympy/polys/matrices/sdm.py	<genexpr>SDM.__init__.<locals>.<genexpr>S   s     ,t!1::A::ts   "%zRow out of rangec              3   `   >#    U  H#  o  H  nS Us=:*  =(       a    T:  Os  v   M     M%     g7fr   r   )r   rowcns      r   r   r    U   s%     D#11::A:::s   +.zColumn out of range)	super__init__shaperowscolsdomainallr   values)self	elemsdictr'   r*   r   r$   	__class__s       @@r   r&   SDM.__init__N   sy    #388
8)TY	DAq,t,,,!"455DDDD!"788 E    c                     X   U   $ ! [          as    U R                  u  p4U* Us=::  a  U:  aK  O  OHU* Us=::  a  U:  a:  O  O7 XU-     X$-     s $ ! [          a    U R                  R                  s s $ f = f[	        S5      ef = fNzindex out of range)KeyErrorr'   r*   zero
IndexError)r-   ijr   r$   s        r   getitemSDM.getitemX   s    
	771: 	7::DArQ{{rQ{{,A;qu-- ,;;+++, !!566	7s-   	 :BAB A72B6A77Bc                 6   U R                   u  pEU* Us=::  a  U:  a  O  OU* Us=::  a  U:  d  O  [        S5      eX-  X%-  p!U(       a	   X0U   U'   g U R                  US 5      nUb   Xb	 U(       d  X	 g g g ! [         a    X#0X'    g f = f! [         a     g f = fr3   )r'   r6   r4   get)r-   r7   r8   valuer   r$   rowis          r   setitemSDM.setiteme   s    zza!a!122uae1%"Q
 88At$D$   G    	  %*%   s$   
A6 (B 6BB
BBc                    U R                   u  p4[        U5      U   n[        U5      U   n0 nU R                  5        Hc  u  pX;   d  M  U	R                  5        V
Vs0 s H  u  pX;   d  M  UR                  U
5      U_M      n	n
nU	(       d  MP  XUR                  U5      '   Me     U R	                  U[        U5      [        U5      4U R                  5      $ s  snn
f N)r'   rangeitemsindexnewlenr*   )r-   slice1slice2r   r$   ricisdmr7   r"   r8   es               r   extract_sliceSDM.extract_slicez   s    zz1Xf1XfjjlFAw25))+I+$!~rxx{A~+I3'*$	 # xxc"gs2w/==	 Js   C+Cc                    U (       a  U(       a  U(       d0  U R                  [        U5      [        U5      4U R                  5      $ U R                  u  p4U* [	        U5      s=::  a  [        U5      s=::  a  U:  d  O  [        S5      eU* [	        U5      s=::  a  [        U5      s=::  a  U:  d  O  [        S5      e[        [        5      n[        [        5      n[        U5       H  u  pxXXU-     R                  U5        M     [        U5       H  u  pXjU-     R                  U	5        M     [        U5      n[        U5      nU n0 nXR                  5       -   H\  nX   n0 nXR                  5       -   H  n
X   nXj    H  n	UUU	'   M
     M     U(       d  M?  XX    H  nUR                  5       X'   M     M^     U R                  U[        U5      [        U5      4U R                  5      $ )NzRow index out of rangezColumn index out of range)zerosrG   r*   r'   minmaxr6   r   list	enumerateappendsetkeyscopyrF   )r-   r(   r)   r   r$   rowmapcolmapi2i1j2j1rowsetcolsetsdm1sdm2row1row2row1_j1s                     r   extractSDM.extract   s   $::s4y#d)4dkkBBzzc$i03t90q0566c$i03t90q0899 T"T"oFB6N!!"% &oFB6N!!"% & VV99;&B8DDyy{*( *B&DH % + t *B#yy{DH % ' xxs4y#d)4dkkBBr1   c                     / nU R                  5        HD  u  p#SR                  S UR                  5        5       5      nUR                  U< SU< S35        MF     SSR                  U5      -  $ )N, c              3   8   #    U  H  u  pU< S U< 3v   M     g7f)z: Nr   )r   r8   elems      r   r   SDM.__str__.<locals>.<genexpr>   s      Q['!Q!5[s   z: {}z{%s})rD   joinrV   )r-   rowsstrr7   r"   elemsstrs        r   __str__SDM.__str__   sZ    jjlFAyy QSYY[ QQHNNH56 # 		'***r1   c                     [        U 5      R                  n[        R                  U 5      nU< SU< SU R                  < SU R
                  < S3$ )N(rj   ))type__name__dict__repr__r'   r*   )r-   clsr(   s      r   rz   SDM.__repr__   s6    4j!!}}T"#&djj$++FFr1   c                     U " XU5      $ )a  

Parameters
==========

sdm: A dict of dicts for non-zero elements in SDM
shape: tuple representing dimension of SDM
domain: Represents :py:class:`~.Domain` of SDM

Returns
=======

An :py:class:`~.SDM` object

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> elemsdict = {0:{1: QQ(2)}}
>>> A = SDM.new(elemsdict, (2, 2), QQ)
>>> A
{0: {1: 2}}

r   )r{   rL   r'   r*   s       r   rF   SDM.new   s    6 3v&&r1   c                     U R                  5        VVs0 s H  u  pXR                  5       _M     nnnU R                  X0R                  U R                  5      $ s  snnf )z
Returns the copy of a :py:class:`~.SDM` object

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> elemsdict = {0:{1:QQ(2)}, 1:{}}
>>> A = SDM(elemsdict, (2, 2), QQ)
>>> B = A.copy()
>>> B
{0: {1: 2}, 1: {}}

)rD   rY   rF   r'   r*   )Ar7   AiAcs       r   rY   SDM.copy   sF      )*	2	uqal	2uuR!((++ 3s   Ac                   ^^	^
 Uu  nm
[        T5      U:X  a  [        U
4S jT 5       5      (       d  [        S5      eUU
4S jm	U	4S j[        U5       5       nU VVs0 s H  u  pgU(       d  M  Xg_M     nnnU " XU5      $ s  snnf )aJ  
Create :py:class:`~.SDM` object from a list of lists.

Parameters
==========

ddm:
    list of lists containing domain elements
shape:
    Dimensions of :py:class:`~.SDM` matrix
domain:
    Represents :py:class:`~.Domain` of :py:class:`~.SDM` object

Returns
=======

:py:class:`~.SDM` containing elements of ddm

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> ddm = [[QQ(1, 2), QQ(0)], [QQ(0), QQ(3, 4)]]
>>> A = SDM.from_list(ddm, (2, 2), QQ)
>>> A
{0: {0: 1/2}, 1: {1: 3/4}}

See Also
========

to_list
from_list_flat
from_dok
from_ddm
c              3   @   >#    U  H  n[        U5      T:H  v   M     g 7frB   )rG   )r   r"   r$   s     r   r    SDM.from_list.<locals>.<genexpr>  s     %Csc#h!mss   zInconsistent row-list/shapec                 r   > [        T5       Vs0 s H  nTU    U   (       d  M  UTU    U   _M     sn$ s  snf rB   )rC   )r7   r8   ddmr$   s     r   <lambda>SDM.from_list.<locals>.<lambda>  s3    qGASVAYKAc!fQiKGGs   44c              3   6   >#    U  H  oT" U5      4v   M     g 7frB   r   )r   r7   getrows     r   r   r     s     2AVAYs   )rG   r+   r   rC   )r{   r   r'   r*   r   irowsr7   r"   rL   r   r$   s    `       @@r   	from_listSDM.from_list   sw    N 1CA#%Cs%C"C"C!"?@@G2q2$)1E&!SvqvE13v&& 2s   B/Bc                 N    U R                  XR                  UR                  5      $ )a  
Create :py:class:`~.SDM` from a :py:class:`~.DDM`.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> ddm = DDM( [[QQ(1, 2), 0], [0, QQ(3, 4)]], (2, 2), QQ)
>>> A = SDM.from_ddm(ddm)
>>> A
{0: {0: 1/2}, 1: {1: 3/4}}
>>> SDM.from_ddm(ddm).to_ddm() == ddm
True

See Also
========

to_ddm
from_list
from_list_flat
from_dok
)r   r'   r*   )r{   r   s     r   from_ddmSDM.from_ddm  s    4 }}S))SZZ88r1   c                    U R                   u  pU R                  R                  n[        U5       Vs/ s H  oC/U-  PM
     nnU R	                  5        H%  u  pgUR	                  5        H  u  pXU   U'   M     M'     U$ s  snf )z
Convert a :py:class:`~.SDM` object to a list of lists.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> elemsdict = {0:{1:QQ(2)}, 1:{}}
>>> A = SDM(elemsdict, (2, 2), QQ)
>>> A.to_list()
[[0, 2], [0, 0]]


)r'   r*   r5   rC   rD   )
Mr   r$   r5   _r   r7   r"   r8   rM   s
             r   to_listSDM.to_list5  ss      wwxx}}#(8,8avz8,ggiFA		Aq	 $   
	 -s   A>c                     U R                   u  pU R                  R                  nU/X-  -  nU R                  5        H'  u  pVUR                  5        H  u  pxXXR-  U-   '   M     M)     U$ )aY  
Convert :py:class:`~.SDM` to a flat list.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0:{1:QQ(2)}, 1:{0: QQ(3)}}, (2, 2), QQ)
>>> A.to_list_flat()
[0, 2, 3, 0]
>>> A == A.from_list_flat(A.to_list_flat(), A.shape, A.domain)
True

See Also
========

from_list_flat
to_list
to_dok
to_ddm
)r'   r*   r5   rD   )	r   r   r$   r5   flatr7   r"   r8   rM   s	            r   to_list_flatSDM.to_list_flatM  sb    . wwxx}}vggiFA		 !QS1W $   r1   c                     Uu  pE[        U5      XE-  :w  a  [        S5      e[        [        5      n[	        U5       H"  u  pxU(       d  M  [        Xu5      u  pXU	   U
'   M$     U " XbU5      $ )aj  
Create :py:class:`~.SDM` from a flat list of elements.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM.from_list_flat([QQ(0), QQ(2), QQ(0), QQ(0)], (2, 2), QQ)
>>> A
{0: {1: 2}}
>>> A == A.from_list_flat(A.to_list_flat(), A.shape, A.domain)
True

See Also
========

to_list_flat
from_list
from_dok
from_ddm
zInconsistent flat-list shape)rG   r   r   ry   rU   divmod)r{   elementsr'   r*   r   r$   rL   injelementr7   r8   s              r   from_list_flatSDM.from_list_flatl  sj    0 x=AE!!"@AA$%h/LCwc~#Aq	 0 3v&&r1   c                     U R                  5       n[        U5      n[        UR                  5       5      nX R                  4nX44$ )a  
Convert :class:`SDM` to a flat list of nonzero elements and data.

Explanation
===========

This is used to operate on a list of the elements of a matrix and then
reconstruct a modified matrix with elements in the same positions using
:meth:`from_flat_nz`. Zero elements are omitted from the list.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0:{1:QQ(2)}, 1:{0: QQ(3)}}, (2, 2), QQ)
>>> elements, data = A.to_flat_nz()
>>> elements
[2, 3]
>>> A == A.from_flat_nz(elements, data, A.domain)
True

See Also
========

from_flat_nz
to_list_flat
sympy.polys.matrices.ddm.DDM.to_flat_nz
sympy.polys.matrices.domainmatrix.DomainMatrix.to_flat_nz
)to_doktuplerT   r,   r'   )r   dokindicesr   datas        r   
to_flat_nzSDM.to_flat_nz  s<    > hhj*

%!~r1   c                 V    Uu  pE[        [        XA5      5      nU R                  XeU5      $ )z
Reconstruct a :class:`~.SDM` after calling :meth:`to_flat_nz`.

See :meth:`to_flat_nz` for explanation.

See Also
========

to_flat_nz
from_list_flat
sympy.polys.matrices.ddm.DDM.from_flat_nz
sympy.polys.matrices.domainmatrix.DomainMatrix.from_flat_nz
)ry   zipfrom_dok)r{   r   r   r*   r   r'   r   s          r   from_flat_nzSDM.from_flat_nz  s+     3w)*||C//r1   c                 t    U R                  5        VVs0 s H  u  pXR                  5       _M     snn$ s  snnf )a@  
Convert to dictionary of dictionaries (dod) format.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0: {1: QQ(2)}, 1: {0: QQ(3)}}, (2, 2), QQ)
>>> A.to_dod()
{0: {1: 2}, 1: {0: 3}}

See Also
========

from_dod
sympy.polys.matrices.domainmatrix.DomainMatrix.to_dod
)rD   rY   )r   r7   r"   s      r   to_dod
SDM.to_dod  s,    & -.GGI6I&!88:I666s   4c                     [        [        5      nUR                  5        H.  u  pVUR                  5        H  u  pxU(       d  M  XU   U'   M     M0     U " XBU5      $ )a  
Create :py:class:`~.SDM` from dictionary of dictionaries (dod) format.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> dod = {0: {1: QQ(2)}, 1: {0: QQ(3)}}
>>> A = SDM.from_dod(dod, (2, 2), QQ)
>>> A
{0: {1: 2}, 1: {0: 3}}
>>> A == SDM.from_dod(A.to_dod(), A.shape, A.domain)
True

See Also
========

to_dod
sympy.polys.matrices.domainmatrix.DomainMatrix.to_dod
r   ry   rD   )	r{   dodr'   r*   rL   r7   r"   r8   rM   s	            r   from_dodSDM.from_dod  sQ    . $iikFA		1 !F1I $ " 3v&&r1   c           	          U R                  5        VVVVs0 s H#  u  pUR                  5         H	  u  p4X4U_M     M%     snnnn$ s  snnnnf )a  
Convert to dictionary of keys (dok) format.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0: {1: QQ(2)}, 1: {0: QQ(3)}}, (2, 2), QQ)
>>> A.to_dok()
{(0, 1): 2, (1, 0): 3}

See Also
========

from_dok
to_list
to_list_flat
to_ddm
rD   r   r7   r"   r8   rM   s        r   r   
SDM.to_dok  s:    * )*	J	faciikda	k	JJJs   *A
c                     [        [        5      nUR                  5        H  u  u  pVnU(       d  M  XtU   U'   M     U " XBU5      $ )a}  
Create :py:class:`~.SDM` from dictionary of keys (dok) format.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> dok = {(0, 1): QQ(2), (1, 0): QQ(3)}
>>> A = SDM.from_dok(dok, (2, 2), QQ)
>>> A
{0: {1: 2}, 1: {0: 3}}
>>> A == SDM.from_dok(A.to_dok(), A.shape, A.domain)
True

See Also
========

to_dok
from_list
from_list_flat
from_ddm
r   )r{   r   r'   r*   rL   r7   r8   rM   s           r   r   SDM.from_dok  sC    2 $IFQAqAq	 % 3v&&r1   c              #   n   #    U R                  5        H  nUR                  5        Sh  vN   M     g N	7f)z
Iterate over the nonzero values of a :py:class:`~.SDM` matrix.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0: {1: QQ(2)}, 1: {0: QQ(3)}}, (2, 2), QQ)
>>> list(A.iter_values())
[2, 3]

N)r,   )r   r"   s     r   iter_valuesSDM.iter_values/  s)      88:Czz|## #s   '53
5c              #   ~   #    U R                  5        H%  u  pUR                  5        H  u  p4X4U4v   M     M'     g7f)aN  
Iterate over indices and values of the nonzero elements.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0: {1: QQ(2)}, 1: {0: QQ(3)}}, (2, 2), QQ)
>>> list(A.iter_items())
[((0, 1), 2), ((1, 0), 3)]

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.iter_items
Nr   r   s        r   
iter_itemsSDM.iter_items@  s6     $ ggiFA		fai $  s   ;=c                 `    [        U R                  5       U R                  U R                  5      $ )z
Convert a :py:class:`~.SDM` object to a :py:class:`~.DDM` object

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ)
>>> A.to_ddm()
[[0, 2], [0, 0]]

)r   r   r'   r*   r   s    r   to_ddm
SDM.to_ddmV  s!     199;22r1   c                     U $ )z5
Convert to :py:class:`~.SDM` format (returns self).
r   r   s    r   to_sdm
SDM.to_sdmf  s	     r1   r   )ground_typesc                 >    U R                  5       R                  5       $ )aH  
Convert a :py:class:`~.SDM` object to a :py:class:`~.DFM` object

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ)
>>> A.to_dfm()
[[0, 2], [0, 0]]

See Also
========

to_ddm
to_dfm_or_ddm
sympy.polys.matrices.domainmatrix.DomainMatrix.to_dfm
)r   to_dfmr   s    r   r   
SDM.to_dfml  s    * xxz  ""r1   c                 >    U R                  5       R                  5       $ )a  
Convert to :py:class:`~.DFM` if possible, else :py:class:`~.DDM`.

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ)
>>> A.to_dfm_or_ddm()
[[0, 2], [0, 0]]
>>> type(A.to_dfm_or_ddm())  # depends on the ground types
<class 'sympy.polys.matrices._dfm.DFM'>

See Also
========

to_ddm
to_dfm
sympy.polys.matrices.domainmatrix.DomainMatrix.to_dfm_or_ddm
)r   to_dfm_or_ddmr   s    r   r   SDM.to_dfm_or_ddm  s    . xxz''))r1   c                     U " 0 X5      $ )aQ  

Returns a :py:class:`~.SDM` of size shape,
belonging to the specified domain

In the example below we declare a matrix A where,

.. math::
    A := \left[\begin{array}{ccc}
    0 & 0 & 0 \\
    0 & 0 & 0 \end{array} \right]

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM.zeros((2, 3), QQ)
>>> A
{}

r   )r{   r'   r*   s      r   rQ   	SDM.zeros  s    * 2u%%r1   c                     UR                   nUu  pE[        [        [        U5      U/U-  5      5      n[        U5       Vs0 s H  owUR	                  5       _M     nnU " XU5      $ s  snf rB   )onery   r   rC   rY   )	r{   r'   r*   r   r   r$   r"   r7   rL   s	            r   onesSDM.ones  s_    jj3uQx#q)*&+Ah/h#((*}h/3v&& 0s    A%c                     [        U[        5      (       a  XpCOUu  p4UR                  n[        [	        X45      5       Vs0 s H  ofXe0_M     nnU " XsU4U5      $ s  snf )z

Returns a identity :py:class:`~.SDM` matrix of dimensions
size x size, belonging to the specified domain

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> I = SDM.eye((2, 2), QQ)
>>> I
{0: {0: 1}, 1: {1: 1}}

)
isinstanceintr   rC   rR   )r{   r'   r*   r(   r)   r   r7   rL   s           r   eyeSDM.eye  s_    " eS!!$JDjj$)#d/$:;$:q1({$:;3tf-- <s   Ac                     Uc  [        U5      [        U5      4n[        U5       VVs0 s H  u  pEU(       d  M  XDU0_M     nnnU " XcU5      $ s  snnf rB   )rG   rU   )r{   diagonalr*   r'   r7   vrL   s          r   diagSDM.diag  sR    =]CM2E%.x%8>%8TQAyqa&y%8>3v&& ?s
   AAc                 p    [        U 5      nU R                  XR                  SSS2   U R                  5      $ )z

Returns the transpose of a :py:class:`~.SDM` matrix

Examples
========

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ)
>>> A.transpose()
{1: {0: 2}}

N)sdm_transposerF   r'   r*   )r   MTs     r   	transposeSDM.transpose  s/     1uuR211r1   c                     [        U[        5      (       d  [        $ U R                  UR                  :w  a'  [	        SU R                  < SUR                  < 35      eU R                  U5      $ )NMatrix size mismatch: z + )r   r   NotImplementedr'   r   r   r   Bs     r   __add__SDM.__add__  J    !S!!!!WW!''177STTuuQxr1   c                     [        U[        5      (       d  [        $ U R                  UR                  :w  a'  [	        SU R                  < SUR                  < 35      eU R                  U5      $ )Nr   z - )r   r   r   r'   r   r   r   s     r   __sub__SDM.__sub__  r   r1   c                 "    U R                  5       $ rB   )r   r   s    r   __neg__SDM.__neg__  s    uuwr1   c                     [        U[        5      (       a  U R                  U5      $ XR                  ;   a  U R	                  U5      $ [
        $ )zA * B)r   r   matmulr*   r   r   r   s     r   __mul__SDM.__mul__  s9    a88A;((]558O!!r1   c                 N    XR                   ;   a  U R                  U5      $ [        $ rB   )r*   rmulr   )abs     r   __rmul__SDM.__rmul__  s    =66!9!!r1   c                     U R                   UR                   :w  a  [        eU R                  u  p#UR                  u  pEX4:w  a  [        e[	        XU R                   X%5      nU R                  XbU4U R                   5      $ )a  
Performs matrix multiplication of two SDM matrices

Parameters
==========

A, B: SDM to multiply

Returns
=======

SDM
    SDM after multiplication

Raises
======

DomainError
    If domain of A does not match
    with that of B

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> B = SDM({0:{0:ZZ(2), 1:ZZ(3)}, 1:{0:ZZ(4)}}, (2, 2), ZZ)
>>> A.matmul(B)
{0: {0: 8}, 1: {0: 2, 1: 3}}

)r*   r   r'   r   
sdm_matmulrF   )r   r   r   r$   n2oCs          r   r   
SDM.matmul  sg    B 88qxxww7qQXXq,uuQA))r1   c                 p   ^ [        U U4S j5      nU R                  X R                  U R                  5      $ )z
Multiplies each element of A with a scalar b

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> A.mul(ZZ(3))
{0: {1: 6}, 1: {0: 3}}

c                    > U T-  $ rB   r   aijr   s    r   r   SDM.mul.<locals>.<lambda>E  s	    Ar1   	unop_dictrF   r'   r*   r   r   Csdms    ` r   r   SDM.mul7  s+     -.uuT77AHH--r1   c                 p   ^ [        U U4S j5      nU R                  X R                  U R                  5      $ )Nc                    > TU -  $ rB   r   r	  s    r   r   SDM.rmul.<locals>.<lambda>I  s	    #r1   r  r  s    ` r   r   SDM.rmulH  s)    -.uuT77AHH--r1   c                 *  ^ U R                   UR                   :w  a  [        eU R                  UR                  :w  a  [        eU R                   R                  mU4S jn[        X[        X"5      nU R                  X0R                  U R                   5      $ )Nc                    > T$ rB   r   )rM   r5   s    r   r   %SDM.mul_elementwise.<locals>.<lambda>R  s    $r1   )r*   r   r'   r   r5   
binop_dictr   rF   )r   r   fzeror  r5   s       @r   mul_elementwiseSDM.mul_elementwiseL  sh    88qxx77aggxx}}!U2uuT77AHH--r1   c                     [        X[        [        [        5      nU R                  X R                  U R
                  5      $ )a  

Adds two :py:class:`~.SDM` matrices

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> B = SDM({0:{0: ZZ(3)}, 1:{1:ZZ(4)}}, (2, 2), ZZ)
>>> A.add(B)
{0: {0: 3, 1: 2}, 1: {0: 1, 1: 4}}

)r  r   r   rF   r'   r*   r   r   r  s      r   r   SDM.addV  -      !S#.uuT77AHH--r1   c                     [        X[        [        [        5      nU R	                  X R
                  U R                  5      $ )a#  

Subtracts two :py:class:`~.SDM` matrices

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> B  = SDM({0:{0: ZZ(3)}, 1:{1:ZZ(4)}}, (2, 2), ZZ)
>>> A.sub(B)
{0: {0: -3, 1: 2}, 1: {0: 1, 1: -4}}

)r  r   r   r   rF   r'   r*   r  s      r   r   SDM.subi  r  r1   c                 n    [        U [        5      nU R                  XR                  U R                  5      $ )z

Returns the negative of a :py:class:`~.SDM` matrix

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> A.neg()
{0: {1: -2}, 1: {0: -1}}

)r  r   rF   r'   r*   )r   r  s     r   r   SDM.neg|  s)     C uuT77AHH--r1   c                    ^^ U R                   mTT:X  a  U R                  5       $ [        U UU4S j5      nU R                  X R                  T5      $ )a  
Converts the :py:class:`~.Domain` of a :py:class:`~.SDM` matrix to K

Examples
========

>>> from sympy import ZZ, QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> A.convert_to(QQ)
{0: {1: 2}, 1: {0: 1}}

c                 (   > TR                  U T5      $ rB   )convert_from)rM   KKolds    r   r    SDM.convert_to.<locals>.<lambda>  s    ANN1d$;r1   )r*   rY   r  rF   r'   )r   r'  Akr(  s    ` @r   
convert_toSDM.convert_to  sB     xx9668Oq;<uuR!$$r1   c                 P    [        [        [        U R                  5       5      5      $ )a!  Number of non-zero elements in the :py:class:`~.SDM` matrix.

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> A.nnz()
2

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.nnz
)summaprG   r,   r   s    r   nnzSDM.nnz  s    " 3sAHHJ'((r1   c           
          U R                   u  pX:X  d   e[        U5      nU Vs0 s H  oD[        U R                  U/ 5      5      _M      nn[	        X55      $ s  snf )a#  Strongly connected components of a square matrix *A*.

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0: ZZ(2)}, 1:{1:ZZ(1)}}, (2, 2), ZZ)
>>> A.scc()
[[0], [1]]

See also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.scc
)r'   rC   rT   r<   r   )r   r(   r)   Vr   Emaps         r   sccSDM.scc  sX    " WW
||$K/01q!4a%%q1-a66 2s   %Ac                 n    [        U 5      u  pnU R                  XR                  U R                  5      U4$ )a  

Returns reduced-row echelon form and list of pivots for the :py:class:`~.SDM`

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(2), 1:QQ(4)}}, (2, 2), QQ)
>>> A.rref()
({0: {0: 1, 1: 2}}, [0])

)	sdm_irrefrF   r'   r*   )r   r   pivotsr   s       r   rrefSDM.rref  s/     !|1uuQ*F22r1   c                     U R                   n[        X5      u  p#nU R                  X R                  U R                   5      nXSU4$ )a  

Returns reduced-row echelon form (RREF) with denominator and pivots.

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(2), 1:QQ(4)}}, (2, 2), QQ)
>>> A.rref_den()
({0: {0: 1, 1: 2}}, 1, [0])

)r*   sdm_rref_denrF   r'   )r   r'  
A_rref_sdmdenomr9  A_rrefs         r   rref_denSDM.rref_den  s?     HH$0$6!
6z77AHH5f$$r1   c                 Z    U R                  5       R                  5       R                  5       $ )z

Returns inverse of a matrix A

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> A.inv()
{0: {0: -2, 1: 1}, 1: {0: 3/2, 1: -1/2}}

)r   invr   r   s    r   rD  SDM.inv  s#      $$&--//r1   c                 >    U R                  5       R                  5       $ )z
Returns determinant of A

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> A.det()
-2

)r   detr   s    r   rG  SDM.det  s    *  $$&&r1   c                     U R                  5       R                  5       u  pnU R                  U5      U R                  U5      U4$ )a  

Returns LU decomposition for a matrix A

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> A.lu()
({0: {0: 1}, 1: {0: 3, 1: 1}}, {0: {0: 1, 1: 2}, 1: {1: -2}}, [])

)r   lur   )r   LUswapss       r   rJ  SDM.lu  s6     hhjmmoezz!}ajjmU22r1   c                     U R                  5       R                  5       u  pUR                  5       nUR                  5       nX44$ )z
QR decomposition for SDM (Sparse Domain Matrix).

Returns:
    - Q: Orthogonal matrix as a SDM.
    - R: Upper triangular matrix as a SDM.
)r   qrr   )r-   ddm_qddm_rQRs        r   rP  SDM.qr,  s7     {{}'')LLNLLNtr1   c                 z    U R                  U R                  5       R                  UR                  5       5      5      $ )a  

Uses LU decomposition to solve Ax = b,

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> b = SDM({0:{0:QQ(1)}, 1:{0:QQ(2)}}, (2, 1), QQ)
>>> A.lu_solve(b)
{1: {0: 1/2}}

)r   r   lu_solve)r   r   s     r   rW  SDM.lu_solve9  s*      zz!((*--ahhj9::r1   c                     U R                  5       R                  5       u  pp4UR                  5       nUR                  5       nUR                  5       nUR                  5       nXVXx4$ )zx
Fraction free LU decomposition of SDM.

Uses DDM implementation.

See Also
========

sympy.polys.matrices.ddm.DDM.fflu
)r   fflur   )	r-   ddm_pddm_lddm_dddm_uPrK  DrL  s	            r   rZ  SDM.ffluK  sV     &*%7%7%9%>%>%@"eLLNLLNLLNLLNQzr1   c                    U R                   S   nU R                  R                  n[        U 5      u  p4n[	        X2XU5      u  pg[        [        U5      5      n[        U5      U4nU R                  XhU R                  5      U4$ )a(  
Nullspace of a :py:class:`~.SDM` matrix A.

The domain of the matrix must be a field.

It is better to use the :meth:`~.DomainMatrix.nullspace` method rather
than this method which is otherwise no longer used.

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0: QQ(2), 1: QQ(4)}}, (2, 2), QQ)
>>> A.nullspace()
({0: {0: -2, 1: 1}}, [1])


See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace
    The preferred way to get the nullspace of a matrix.

r   )	r'   r*   r   r8  sdm_nullspace_from_rrefry   rU   rG   rF   )	r   ncolsr   r   r9  nzcolsr'  	nonpivotsr'   s	            r   	nullspaceSDM.nullspace]  sq    4 
hhll%aL6.qufM1QuuQqxx()33r1   c                 P   U R                   u  p#U R                  nUc'  [        [        [        U R                  5       5      5      nU(       d'  U R                  X34U5      [        [        U5      5      4$ [        U5      U:X  a  U R                  SU4U5      / 4$ U S   US      nUR                  U5      (       a   e[        U5      n[        [        5      nU R                  5        H2  u  pU	R                  5        H  u  pXz   R                  X45        M     M4     / n/ n[        U5       HD  n
X;   a  M
  UR                  U
5        X0nXz    H  u  pU* XU   '   M     UR                  U5        MF     [!        [#        U5      5      nU R%                  U[        U5      U4U5      nUU4$ )a  
Returns nullspace for a :py:class:`~.SDM` matrix ``A`` in RREF.

The domain of the matrix can be any domain.

The matrix must already be in reduced row echelon form (RREF).

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0: QQ(2), 1: QQ(4)}}, (2, 2), QQ)
>>> A_rref, pivots = A.rref()
>>> A_null, nonpivots = A_rref.nullspace_from_rref(pivots)
>>> A_null
{0: {0: -2, 1: 1}}
>>> pivots
[0]
>>> nonpivots
[1]

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace
    The higher-level function that would usually be called instead of
    calling this one directly.

sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace_from_rref
    The higher-level direct equivalent of this function.

sympy.polys.matrices.ddm.DDM.nullspace_from_rref
    The equivalent function for dense :py:class:`~.DDM` matrices.

r   )r'   r*   sortedr/  rR   r,   r   rT   rC   rG   rQ   is_zerorW   r   rD   rV   ry   rU   rF   )r   r9  r   r$   r'  	pivot_val
pivots_setnonzero_colsr7   r   r8   Aijbasisrf  veciprL   A_nulls                     r   nullspace_from_rrefSDM.nullspace_from_rref  s   J wwHH>CQXXZ01F55!#T%(^33[A77Aq61%r)) aDO	99Y''''[

 #4(WWYEA((*&&x0 %  	qAQ.C'?#&$2J + LL  9U#$sSZOQ/	""r1   c                     U R                   S   n[        U 5      u  p#n[        X!U5      nU(       a  SU0O0 nU R                  USUS-
  4U R                  5      $ )Nr   r   )r'   r8  sdm_particular_from_rrefrF   r*   )r   rd  r   r9  re  r_  reps          r   
particularSDM.particular  sU    
%aL6$Qv6qebuuS1eAg,11r1   c                    [        U R                  5       5      nU R                  u  p4U R                  nU H  nUR                  u  pxXs:X  d   eUR                  U:X  d   eUR	                  5        H?  u  pUR                  U	S5      nUc  0 =X)'   nU
R	                  5        H  u  pXX-   '   M     MA     XH-  nM     U R                  X#U4U R                  5      $ )a'  Horizontally stacks :py:class:`~.SDM` matrices.

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM

>>> A = SDM({0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}}, (2, 2), ZZ)
>>> B = SDM({0: {0: ZZ(5), 1: ZZ(6)}, 1: {0: ZZ(7), 1: ZZ(8)}}, (2, 2), ZZ)
>>> A.hstack(B)
{0: {0: 1, 1: 2, 2: 5, 3: 6}, 1: {0: 3, 1: 4, 2: 7, 3: 8}}

>>> C = SDM({0: {0: ZZ(9), 1: ZZ(10)}, 1: {0: ZZ(11), 1: ZZ(12)}}, (2, 2), ZZ)
>>> A.hstack(B, C)
{0: {0: 1, 1: 2, 2: 5, 3: 6, 4: 9, 5: 10}, 1: {0: 3, 1: 4, 2: 7, 3: 8, 4: 11, 5: 12}}
N)ry   rY   r'   r*   rD   r<   rF   )r   r   Anewr(   r)   r*   BkBkrowsBkcolsr7   Bkir   r8   Bkijs                 r   hstack
SDM.hstack  s    $ AFFH~WW
BXXNF>!>99&&&((*XXa&:#%%DGb"yy{GA#'qxL  +	 % ND  uuT$<22r1   c                 J   [        U R                  5       5      nU R                  u  p4U R                  nU HM  nUR                  u  pxX:X  d   eUR                  U:X  d   eUR	                  5        H  u  pXX-   '   M     X7-  nMO     U R                  X#U4U R                  5      $ )aC  Vertically stacks :py:class:`~.SDM` matrices.

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM

>>> A = SDM({0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}}, (2, 2), ZZ)
>>> B = SDM({0: {0: ZZ(5), 1: ZZ(6)}, 1: {0: ZZ(7), 1: ZZ(8)}}, (2, 2), ZZ)
>>> A.vstack(B)
{0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}, 2: {0: 5, 1: 6}, 3: {0: 7, 1: 8}}

>>> C = SDM({0: {0: ZZ(9), 1: ZZ(10)}, 1: {0: ZZ(11), 1: ZZ(12)}}, (2, 2), ZZ)
>>> A.vstack(B, C)
{0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}, 2: {0: 5, 1: 6}, 3: {0: 7, 1: 8}, 4: {0: 9, 1: 10}, 5: {0: 11, 1: 12}}
)ry   rY   r'   r*   rD   rF   )r   r   r|  r(   r)   r*   r}  r~  r  r7   r  s              r   vstack
SDM.vstack  s    $ AFFH~WW
BXXNF>!>99&&&((*!$QX %ND  uuT$<22r1   c                     U R                  5        VVVVs0 s H0  u  p4X4R                  5        VVs0 s H  u  pVXQ" U5      _M     snn_M2     nnnnnU R                  XpR                  U5      $ s  snnf s  snnnnf rB   )rD   rF   r'   )r-   funcr*   r7   r"   r8   rM   rL   s           r   	applyfuncSDM.applyfunc#  s]    EIZZ\R\61q))+6+$!1d1g:+66\RxxZZ00 7Rs   A4
A.A4
.A4
c                     U R                   nU R                  u  p#[        XU5      nUR                  /US-   -  nUR	                  5        H	  u  pgXuU'   M     U$ )ar  
Returns the coefficients of the characteristic polynomial
of the :py:class:`~.SDM` matrix. These elements will be domain elements.
The domain of the elements will be same as domain of the :py:class:`~.SDM`.

Examples
========

>>> from sympy import QQ, Symbol
>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy.polys import Poly
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> A.charpoly()
[1, -5, -2]

We can create a polynomial using the
coefficients using :py:class:`~.Poly`

>>> x = Symbol('x')
>>> p = Poly(A.charpoly(), x, domain=A.domain)
>>> p
Poly(x**2 - 5*x - 2, x, domain='QQ')

r   )r*   r'   sdm_berkr5   rD   )r   r'  r$   r   pdictplistr7   pis           r   charpolySDM.charpoly'  sV    2 HHwwq!AE"[[]EA!H #r1   c                     U (       + $ )z0
Says whether this matrix has all zero entries.
r   r-   s    r   is_zero_matrixSDM.is_zero_matrixH  s     xr1   c                 B    [        S U R                  5        5       5      $ )zf
Says whether this matrix is upper-triangular. True can be returned
even if the matrix is not square.
c              3   B   #    U  H  u  pU  H	  o1U:*  v   M     M     g 7frB   r   r   r7   r"   r8   s       r   r   SDM.is_upper.<locals>.<genexpr>S       Bfac6c6   r+   rD   r  s    r   is_upperSDM.is_upperN      
 B

BBBr1   c                 B    [        S U R                  5        5       5      $ )zf
Says whether this matrix is lower-triangular. True can be returned
even if the matrix is not square.
c              3   B   #    U  H  u  pU  H	  o1U:  v   M     M     g 7frB   r   r  s       r   r   SDM.is_lower.<locals>.<genexpr>Z  r  r  r  r  s    r   is_lowerSDM.is_lowerU  r  r1   c                 B    [        S U R                  5        5       5      $ )z^
Says whether this matrix is diagonal. True can be returned
even if the matrix is not square.
c              3   B   #    U  H  u  pU  H	  o1U:H  v   M     M     g 7frB   r   r  s       r   r   "SDM.is_diagonal.<locals>.<genexpr>a  r  r  r  r  s    r   is_diagonalSDM.is_diagonal\  r  r1   c                     U R                   u  pU R                  R                  nU R                  5        VVs/ s H  u  pEXB:  d  M  UR	                  XC5      PM     snn$ s  snnf )z/
Returns the diagonal of the matrix as a list.
)r'   r*   r5   rD   r<   )r-   r   r$   r5   r7   r"   s         r   r   SDM.diagonalc  sN     zz{{/3zz|E|VQqu  |EEEs   A A       c                 X    U R                  5       R                  US9R                  5       $ )zA
Returns the LLL-reduced basis for the :py:class:`~.SDM` matrix.
delta)r   lllr   )r   r  s     r   r  SDM.lllk  s(      $$5$188::r1   c                     U R                  5       R                  US9u  p#UR                  5       UR                  5       4$ )z:
Returns the LLL-reduced basis and transformation matrix.
r  )r   lll_transformr   )r   r  reduced	transforms       r   r  SDM.lll_transformq  s<     __.<<5<I~~!1!1!333r1   )r)   r*   r(   r'   rB   )Qrx   
__module____qualname____firstlineno____doc__fmtis_DFMis_DDMr&   r9   r?   rN   rg   rr   rz   classmethodrF   rY   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r
   r   r   rQ   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   r   r+  r0  r5  r:  rA  rD  rG  rJ  rP  rW  rZ  rg  rt  ry  r  r  r  r  r  r  r  r  r   r   r  r  __static_attributes____classcell__)r/   s   @r   r   r      sl   .` CFF97$*>$CL+G
 ' '8,& ,' ,'\ 9 960> ' 'B#J 0 0$7* ' ':K. ' '<$" ,3  gY/# 0#, gY/* 0*0 & &, ' ' . .0 ' '2$""(*T."...&.&.$%()&7.3$%(0"'.3$;$$ 4DU#n2#3J3B1BCCCF 1X ;  "!Qx 4 4r1   r   c                    [        U 5      [        U5      pe0 nXV-   H  nX   X   p0 n[        U	5      [        U
5      pX-   H  nU" X   X   5      nU(       d  M  XU'   M     X-
   H  nU" X   5      nU(       d  M  XU'   M     X-
   H  nU" X   5      nU(       d  M  XU'   M     U(       d  M  XU'   M     XV-
   HE  nX   n	0 nU	R                  5        H  u  nnU" U5      nU(       d  M  XU'   M     U(       d  MA  XU'   MG     Xe-
   HE  nX   n
0 nU
R                  5        H  u  nnU" U5      nU(       d  M  XU'   M     U(       d  MA  XU'   MG     U$ rB   )rW   rD   )r   r   fabfafbAnzBnzr  r7   r   BiCiAnziBnzir8   Cijro  Bijs                     r   r  r  y  sj   1vs1v
AYqtBWc"gdAbeRU#Cs1  ARU)Cs1  ARU)Cs1  2aD# & YThhjFAsS'Cs1 ! 2aD  YThhjFAsS'Cs1 ! 2aD  Hr1   c                     0 nU R                  5        HB  u  p40 nUR                  5        H  u  pgU" U5      nU(       d  M  XU'   M     U(       d  M>  XRU'   MD     U$ rB   r   )	r   fr   r7   r   r  r8   ro  r  s	            r   r  r    sZ    
AhhjFAC&Cs1 ! 2aD  Hr1   c                     0 nU R                  5        H&  u  p#UR                  5        H  u  pE XQU   U'   M     M(     U$ ! [         a	    X%0X'    M)  f = frB   )rD   r4   )r   r   r7   Mir8   Mijs         r   r   r     s\    	BhhjFA!1a !  I  !!s   ?AAc                 |   ^ ^ UR                  U U4S jT R                  5       TR                  5       -   5       5      $ )Nc              3   :   >#    U  H  nTU   TU   -  v   M     g 7frB   r   )r   r8   r   r   s     r   r   sdm_dotvec.<locals>.<genexpr>  s     :&91!&9s   )r.  rX   )r   r   r'  s   `` r   
sdm_dotvecr    s)    55:affh&9:::r1   c                 n    0 nU R                  5        H  u  pE[        XQU5      nU(       d  M  XcU'   M      U$ rB   )rD   r  )r   r   r'  r  r7   r   r  s          r   sdm_matvecmulr    s8    
Aq!2aD  Hr1   c                    UR                   (       a  [        XX#U5      $ 0 n[        U5      nU R                  5        H  u  px0 n	[        U5      n
X-   Ho  nX   nX   R                  5        HR  u  pU	R	                  US 5      nUb'  XU-  -   nU(       a  XU'   M.  U	R                  U5        MA  X-  nU(       d  MN  XU'   MT     Mq     U	(       d  M  XU'   M     U$ rB   )is_EXRAWsdm_matmul_exrawrW   rD   r<   pop)r   r   r'  r   r  r  B_knzr7   r   r  Ai_knzkAikr8   Bkjr  s                   r   r  r    s    " 	zzaA..
AFERA%C$**,ffQo?c	/C #1q	)Cs #1 '   2aD% & Hr1   c           
      x   UR                   n0 n[        U5      nU R                  5        GH*  u  p[        [        5      n
[        U	5      nX-   Hz  nX   nX]-  U:X  a2  X   R                  5        H  u  pX   R                  X-  5        M     MA  [        U5       H*  nX   R                  XU   R                  X5      -  5        M,     M|     X-
   H7  nXYU   -  nUU:w  d  M  [        U5       H  nX   R                  U5        M     M9     0 nU
R                  5        H%  u  nnUR                  U5      nU(       d  M   UUU'   M'     U(       d  GM&  UXh'   GM-     UR                  5        H  u  nnUR                  5        H  u  pX_-  U:w  d  M  [        U5       H  nU R                  U0 5      R                  X5      nX:X  d  M+  UR                  U0 5      nUR                  X5      X-  -   nUU:w  a  UUU'   UXh'   Md  UR                  US 5        U(       a  UXh'   M  UR                  US 5        M     M     M     U$ rB   )
r5   rW   rD   r   rT   rV   rC   r<   r.  r  )r   r   r'  r   r  r5   r  r  r7   r   Ci_listr  r  r  r8   r  zAikr  Cij_listr  r}  s                        r   r  r    s    66D
AFEd#R A%CzT!djjlFAJ%%ci0 + qAJ%%caDHHQ,=&=> "   AQ%<Dt|qAJ%%d+ "   "==?KAx%%/Cs1 + 2AD; @ 2hhjFAzT!qA%%2,**13C{UU1b\ ffQo	9$;$'BqE#%ADFF1dO!') !a " ! & Hr1   c                    [        S U R                  5        5       [        S9n0 n[        5       n[        5       n[	        [        5      nU(       Gax  UR                  5       nUR                  5        VVs0 s H  u  pxXs;  d  M  Xx_M     nnnU[        U5      -   H  nX'   n	Xg   n[        U5      n
[        U	5      nX-
   H  nU* X   -  Xl'   M     UR                  U5        U
R                  U5        X-   H-  nXl   XU   -  -
  nU(       a  XU'   M  UR                  U5        M/     M     U(       d  M  [        U5      nXg   nXbU'   [        U5      n
US-  nU H  nXo==   U-  ss'   M     UR                  US5       H  nX,   nUU   n[        U5      nU
U-
   H!  nU* Xo   -  UU'   X_   R                  U5        M#     UR                  U5        UR                  U5        U
U-   HI  nUU   UXo   -  -
  nU(       a  UUU'   M  UR                  U5        X:w  d  M6  X_   R                  U5        MK     [        U5      S:X  d  M  UR                  U5        UR                  U5        M     [        U5      S:X  a  UR                  U5        O4UR                  U5        U H  nX:w  d  M
  X_   R                  U5        M     U(       a  GMx  [        X4-  5      n[        U5       VVs0 s H	  u  nnUU_M     nnnUR                  5        VVVs0 s H  u  nnUU Vs1 s H  nUU   iM
     sn_M     nnnnU Vs/ s H  nUU   PM
     nn[        [        U5      5      nUUU4$ s  snnf s  snnf s  snf s  snnnf s  snf )a1  RREF and pivots of a sparse matrix *A*.

Compute the reduced row echelon form (RREF) of the matrix *A* and return a
list of the pivot columns. This routine does not work in place and leaves
the original matrix *A* unmodified.

The domain of the matrix must be a field.

Examples
========

This routine works with a dict of dicts sparse representation of a matrix:

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import sdm_irref
>>> A = {0: {0: QQ(1), 1: QQ(2)}, 1: {0: QQ(3), 1: QQ(4)}}
>>> Arref, pivots, _ = sdm_irref(A)
>>> Arref
{0: {0: 1}, 1: {1: 1}}
>>> pivots
[0, 1]

The analogous calculation with :py:class:`~.MutableDenseMatrix` would be

>>> from sympy import Matrix
>>> M = Matrix([[1, 2], [3, 4]])
>>> Mrref, pivots = M.rref()
>>> Mrref
Matrix([
[1, 0],
[0, 1]])
>>> pivots
(0, 1)

Notes
=====

The cost of this algorithm is determined purely by the nonzero elements of
the matrix. No part of the cost of any step in this algorithm depends on
the number of rows or columns in the matrix. No step depends even on the
number of nonzero rows apart from the primary loop over those rows. The
implementation is much faster than ddm_rref for sparse matrices. In fact
at the time of writing it is also (slightly) faster than the dense
implementation even if the input is a fully dense matrix so it seems to be
faster in all cases.

The elements of the matrix should support exact division with ``/``. For
example elements of any domain that is a field (e.g. ``QQ``) should be
fine. No attempt is made to handle inexact arithmetic.

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.rref
    The higher-level function that would normally be used to call this
    routine.
sympy.polys.matrices.dense.ddm_irref
    The dense equivalent of this routine.
sdm_rref_den
    Fraction-free version of this routine.
c              3   @   #    U  H  oR                  5       v   M     g 7frB   )rY   )r   r   s     r   r   sdm_irref.<locals>.<genexpr>  s     3
"GGII
s   keyr   r   r   )rj  r,   rR   rW   r   r  rD   remover   rG   rU   ry   )r   Arowspivot_row_mapreduced_pivotsnonreduced_pivotsnonzero_columnsr   r8   ro  AjAinzAjnzr  r  Aijinvlr*  AkjAknzAklr9  r$   p	pivot2rowr#   sr7   r(   r:  s                                r   r8  r8  8  s[   v 3
3=E M UN  "#&O
YY[ $&88:I:1Hfaf:I #SW,A!B%Cr7Dr7D[ !FF1IKKN[ecqEk)qEFF1I ! -$  Gea2w bAEVOE  !$$Q+A!BQ%Cr7DD[1"&&q) ! FF1IKKND[ecBEk)BqE FF1Iv'*11!4 ! 2w!|""1%!((+) ,, r7a<q!!!!$6#&**1- M %V N67F"+F"34"3$!QA"3I4@O@U@U@WX@W1q3A9Q<33@WOX&,-fM!fD-	$ D((W JN 53X-s0   4M!M!$M'M2M-(M27M9-M2c                 	   U (       d  0 UR                   / 4$ [        U 5      S:X  a6  U R                  5       u  n[        U5      nX#   nSUR	                  5       0XC/4$ UR
                  (       a  UR                  nOUR                  n[        [        U R                  5       5      6 u  pg0 n0 n	UR                  5       n
U	R                  5       n/ nSnSn[        U[        S9nU GH  nUR                  5        VVs0 s H  u  p4X:;  d  M  X4_M     nnn0 nXR                  5       -   Hz  nUR                  U5      nXU      nUR                  5        HK  u  nnUR                  U5      nUc
  UU-  UU'   M$  UUU-  -   nU(       a  UUU'   M:  UR                  U5        MM     M|     [        U5      n[        U5      nU=(       d    UR                   nUU-
   H  nUU   * UU'   M     UU-
   H  nUU   U-  UU'   M     UU-   H0  nUU   U-  UU   -
  nU(       a  UUU'   M  UR                  U5        M2     U(       d  GM[  [        U5      nUR                  U5      n[        U	R                  5       5       GH*  u  nnUU   nUU;  a2  UR                  5        H  u  nnUU-  nUb	  U" UU5      nUUU'   M     MD  UR                  U5      n[        U5      n[        U5      nUU-
   H#  nU* UU   -  UU'   Uc  M  U" UU   U5      UU'   M%     UU-
   H"  nUUU   -  UU'   Uc  M  U" UU   U5      UU'   M$     UU-   H?  nUUU   -  UUU   -  -
  nU(       a  Ub	  U" UU5      nUUU'   M.  UR                  U5        MA     U(       a  GM  U	R                  U5        UUU'   GM-     [        U5      nUR!                  U5        U(       a  UX'   OUX'   UR#                  U5      (       d
  Uc  UnOX-  nUb  U" X5      nUnGM     Uc  UR                   n0 UEU	En U R                  5        VVs0 s H	  u  nnUU_M     n!nn[%        U5       VVs/ s H  u  nnU!U   U4PM     n"nn[        [        U"5      6 u  n#n$[        U#5      n#[%        U$5       H  u  nnXU#U   '   M     ['        [%        U$5      5      n%U%UU#4$ s  snnf s  snnf s  snnf )a  
Return the reduced row echelon form (RREF) of A with denominator.

The RREF is computed using fraction-free Gauss-Jordan elimination.

Explanation
===========

The algorithm used is the fraction-free version of Gauss-Jordan elimination
described as FFGJ in [1]_. Here it is modified to handle zero or missing
pivots and to avoid redundant arithmetic. This implementation is also
optimized for sparse matrices.

The domain $K$ must support exact division (``K.exquo``) but does not need
to be a field. This method is suitable for most exact rings and fields like
:ref:`ZZ`, :ref:`QQ` and :ref:`QQ(a)`. In the case of :ref:`QQ` or
:ref:`K(x)` it might be more efficient to clear denominators and use
:ref:`ZZ` or :ref:`K[x]` instead.

For inexact domains like :ref:`RR` and :ref:`CC` use ``ddm_irref`` instead.

Examples
========

>>> from sympy.polys.matrices.sdm import sdm_rref_den
>>> from sympy.polys.domains import ZZ
>>> A = {0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}}
>>> A_rref, den, pivots = sdm_rref_den(A, ZZ)
>>> A_rref
{0: {0: -2}, 1: {1: -2}}
>>> den
-2
>>> pivots
[0, 1]

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.rref_den
    Higher-level interface to ``sdm_rref_den`` that would usually be used
    instead of calling this function directly.
sympy.polys.matrices.sdm.sdm_rref_den
    The ``SDM`` method that uses this function.
sdm_irref
    Computes RREF using field division.
ddm_irref_den
    The dense version of this algorithm.

References
==========

.. [1] Fraction-free algorithms for linear and polynomial equations.
    George C. Nakos , Peter R. Turner , Robert M. Williams.
    https://dl.acm.org/doi/10.1145/271130.271133
r   r   Nr  )r   rG   r,   rR   rY   is_Exactexquoquor   rj  rD   rX   r  r<   rW   rT   rV   is_onerU   ry   )&r   r'  r   r8   ro  r  r   rows_in_ordercol_to_row_reducedcol_to_row_unreducedr  	unreducedA_rref_rowsr?  divisorA_rows	Ai_cancelr  r  Ajk
Aik_cancelAi_nzAi_cancel_nzdr  pkr*  r  r  r  Ak_nzr7   
col_to_row
row_to_colA_rref_rows_colr9  r@  r>  s&                                         r   r=  r=    s   z AEE2	Q1hhjGeBGGIS)) 	zz F1779-.A %%'G$))+I KEG Ms+F $&88:B:1Afaf:B 	WWY&A &&)C!45B((*3&]]1-
%#&9IaL!+cCi!7J!'1	!!a( % '& B9~NQUU%Aq\MBqE & %AqEAIBqE & %AQ%!)il*C1q	 &  GffQi .4467EBQB{ !hhjFAs)C*#C1BqE	 )
 &&)CGEGEU]11&!"Q%1BqE # U]be1&!"Q%1BqE #
 U]BqEkC"Q%K/*#C1BqEFF1I # 2$((,)*"2&S 8V 2&' #$%! xx}}}%)E } @ } @&?*>?J#-#3#3#56#541a!Q$#5J68A+8NO8Nuq"
1r*8NOO&12NFF&\F 6"26!9 # i'(Juf$$[ CD 7Os   8R2R2&R8R>c                     [        [        [        U5      5      [        U5      -
  5      n/ nU H=  nXq0nUR                  US5       H  n	X	   U   * XU	   '   M     UR	                  U5        M?     Xe4$ )z%Get nullspace from A which is in RREFr   )rj  rW   rC   r<   rV   )
r   r   rd  r9  rn  rf  r'  r8   Kjr7   s
             r   rc  rc    ss    s5<(3v;67I
AW!!!R(AT!WHBayM )		  <r1   c                     0 n[        U5       H-  u  pEX   R                  US-
  S5      nUc  M!  X`U   U   -  X5'   M/     U$ )z1Get a particular solution from A which is in RREFr   N)rU   r<   )r   rd  r9  r_  r7   r8   Ains          r   rw  rw    sK    
A&!dhhuQw%?1a=AD " Hr1   c           
      ,   UR                   nUR                  nUS:X  a  SU0$ US:X  a3  SU0nU R                  S0 5      R                  SU5      =n(       a  U* US'   UR                   0 0 [        [        5      4u  pxpU R                  5        H]  u  pUR                  5        HD  u  pU(       a  U(       a  XUS-
     US-
  '   M"  U(       a	  XUS-
  '   M2  U(       a	  XUS-
  '   MB  UnMF     M_     U	n[        XU5      nXG* U* /n[        SUS-   5       H6  n[        XU5      nU(       d    O"[        XU5      nUR                  U* 5        M8     U(       a-  US   (       d#  UR                  5         U(       a  US   (       d  M#  [        XS-
  U5      nUSSS2   n0 n[        [        U5      [        [        U5      [        U5      -   US-   5      5       HB  n[	        [        UU[        U5      -
  S-   5      5      n[        UUU5      =n(       d  M=  UUU'   MD     U$ )a  
Berkowitz algorithm for computing the characteristic polynomial.

Explanation
===========

The Berkowitz algorithm is a division-free algorithm for computing the
characteristic polynomial of a matrix over any commutative ring using only
arithmetic in the coefficient ring. This implementation is for sparse
matrices represented in a dict-of-dicts format (like :class:`SDM`).

Examples
========

>>> from sympy import Matrix
>>> from sympy.polys.matrices.sdm import sdm_berk
>>> from sympy.polys.domains import ZZ
>>> M = {0: {0: ZZ(1), 1:ZZ(2)}, 1: {0:ZZ(3), 1:ZZ(4)}}
>>> sdm_berk(M, 2, ZZ)
{0: 1, 1: -5, 2: -2}
>>> Matrix([[1, 2], [3, 4]]).charpoly()
PurePoly(lambda**2 - 5*lambda - 2, lambda, domain='ZZ')

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.charpoly
    The high-level interface to this function.
sympy.polys.matrices.dense.ddm_berk
    The dense version of this function.

References
==========

.. [1] https://en.wikipedia.org/wiki/Samuelson%E2%80%93Berkowitz_algorithm
r   r   r  r   N)r5   r   r<   r   ry   rD   r  rC   r  rV   r  r  rR   rS   rG   rU   )r   r$   r'  r5   r   r  M00r   rT  r  r   r7   r  r8   r  AnCRCTvalsRAnCqTqTiTqis                          r   r  r  #  s   J 66D
%%CAv3x	
aC%%2,""1d++3+tE!H RT!22JA!hhjFAQ!!A#qs!A#!A# ! . C	A!	B"rcNE1ac]AA&!!$dU  b			 b		 	aCA" $B$KE	B3q63s1vc%j0!A#67)E1SZ<>23RA&&3&BqE 8
 Ir1   N)&r  operatorr   r   r   r   r   collectionsr   sympy.external.gmpyr	   sympy.utilities.decoratorr
   sympy.utilities.iterablesr   
exceptionsr   r   r   sympy.polys.domainsr   r   r   __doctest_skip__ry   r   r  r  r   r  r  r  r  r8  r=  rc  rw  r  r   r1   r   <module>r)     s    - , # , 8 D D D "  7$&9:]4$ ]4@++\
;)X=@})@P%frr1   