
    \hj~                         S 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
Jr  SSKJr  SSKJrJrJrJrJrJrJrJrJrJrJrJrJrJr  SS	KJrJr  \S
:w  a  SS/r  " S S\!5      r"SSK#J$r$  SSK%J&r&  g)a  

Module for the DDM class.

The DDM class is an internal representation used by DomainMatrix. The letters
DDM stand for Dense Domain Matrix. A DDM instance represents a matrix using
elements from a polynomial Domain (e.g. ZZ, QQ, ...) in a dense-matrix
representation.

Basic usage:

    >>> from sympy import ZZ, QQ
    >>> from sympy.polys.matrices.ddm import DDM
    >>> A = DDM([[ZZ(0), ZZ(1)], [ZZ(-1), ZZ(0)]], (2, 2), ZZ)
    >>> A.shape
    (2, 2)
    >>> A
    [[0, 1], [-1, 0]]
    >>> type(A)
    <class 'sympy.polys.matrices.ddm.DDM'>
    >>> A @ A
    [[-1, 0], [0, -1]]

The ddm_* functions are designed to operate on DDM as well as on an ordinary
list of lists:

    >>> from sympy.polys.matrices.dense import ddm_idet
    >>> ddm_idet(A, QQ)
    1
    >>> ddm_idet([[0, 1], [-1, 0]], QQ)
    1
    >>> A
    [[-1, 0], [0, -1]]

Note that ddm_idet modifies the input matrix in-place. It is recommended to
use the DDM.det method as a friendlier interface to this instead which takes
care of copying the matrix:

    >>> B = DDM([[ZZ(0), ZZ(1)], [ZZ(-1), ZZ(0)]], (2, 2), ZZ)
    >>> B.det()
    1

Normally DDM would not be used directly and is just part of the internal
representation of DomainMatrix which adds further functionality including e.g.
unifying domains.

The dense format used by DDM is a list of lists of elements e.g. the 2x2
identity matrix is like [[1, 0], [0, 1]]. The DDM class itself is a subclass
of list and its list items are plain lists. Elements are accessed as e.g.
ddm[i][j] where ddm[i] gives the ith row and ddm[i][j] gets the element in the
jth column of that row. Subclassing list makes e.g. iteration and indexing
very efficient. We do not override __getitem__ because it would lose that
benefit.

The core routines are implemented by the ddm_* functions defined in dense.py.
Those functions are intended to be able to operate on a raw list-of-lists
representation of matrices with most functions operating in-place. The DDM
class takes care of copying etc and also stores a Domain object associated
with its elements. This makes it possible to implement things like A + B with
domain checking and also shape checking so that the list of lists
representation is friendlier.

    )chain)GROUND_TYPES)doctest_depends_on   )DMBadInputErrorDMDomainErrorDMNonSquareMatrixErrorDMShapeError)QQ)ddm_transposeddm_iaddddm_isubddm_inegddm_imul	ddm_irmulddm_imatmul	ddm_irrefddm_irref_denddm_idetddm_iinvddm_ilu_splitddm_ilu_solveddm_berk)ddm_lllddm_lll_transformflintz
DDM.to_dfmzDDM.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 5       r\S 5       rS rS r\S 5       rS rS 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  r"S! r#S" r$U 4S# jr%S$ r&\S% 5       r'\S& 5       r(\S' 5       r)S( r*S) r+S* r,S+ r-S, r.S- r/S. r0S/ r1\S0 5       r2S1 r3S2 r4S3 r5S4 r6S5 r7S6 r8S7 r9S8 r:S9 r;S: r<S; r=S< r>\S= 5       r?S> r@S? rAS@ rBSUSA jrCSB rDSC rESD rFSE rGSF rHSG rISH rJSI rKSJ rLSK rMSL rNSM rOSN rPSO rQ\R" SPSQ5      4SR jrS\R" SPSQ5      4SS jrTSTrUU =rV$ )VDDMf   zDense matrix based on polys domain elements

This is a list subclass and is a wrapper for a list of lists that supports
basic matrix arithmetic +, -, *, **.
denseFTc                   >^ [        U[        5      (       a  [        S U 5       5      (       d  [        S5      eUu  nm[	        U5      U:w  d  [        U4S jU 5       5      (       a  [        S5      e[        TU ]  U Vs/ s H  oUR                  5       PM     sn5        UT4U l	        X@l
        TU l        X0l        g s  snf )Nc              3   D   #    U  H  n[        U5      [        L v   M     g 7fN)typelist.0rows     P/var/www/auris/envauris/lib/python3.13/site-packages/sympy/polys/matrices/ddm.py	<genexpr>DDM.__init__.<locals>.<genexpr>r   s     2YPX493DPXs    z rowslist must be a list of listsc              3   @   >#    U  H  n[        U5      T:g  v   M     g 7fr#   )len)r'   r(   ns     r)   r*   r+   u   s     $GhsSX]hs   zInconsistent row-list/shape)
isinstancer%   allr   r-   anysuper__init__copyshaperowscolsdomain)selfrowslistr5   r8   mir.   	__class__s         @r)   r3   DDM.__init__q   s    8T**s2YPX2Y/Y/Y!"DEE1x=A$Gh$G!G!G!"?@@H5Hq&&(H56V
			 6s    B=c                     X   U   $ r#    )r9   r<   js      r)   getitemDDM.getitem~   s    wqz    c                     X0U   U'   g r#   r@   )r9   r<   rA   values       r)   setitemDDM.setitem   s    Q
rD   c                     X    Vs/ s H  o3U   PM	     nn[        U5      nU(       a  [        US   5      O#[        [        U R                  S   5      U   5      n[        XEU4U R                  5      $ s  snf )Nr   r   )r-   ranger5   r   r8   )r9   slice1slice2r(   ddmr6   r7   s          r)   extract_sliceDDM.extract_slice   se    &*l3ls6{l33x!s3q6{s5A+?+G'H3tdkk22 4s   A3c                     / nU H+  nX   nUR                  U Vs/ s H  oeU   PM	     sn5        M-     [        U[        U5      [        U5      4U R                  5      $ s  snf r#   )appendr   r-   r8   )r9   r6   r7   rM   r<   rowirA   s          r)   extractDDM.extract   s\    A7DJJ.AQ./  3TCI.<< /s   A
c                     U " XU5      $ )aH  
Create a :class:`DDM` from a list of lists.

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.ddm import DDM
>>> A = DDM.from_list([[ZZ(0), ZZ(1)], [ZZ(-1), ZZ(0)]], (2, 2), ZZ)
>>> A
[[0, 1], [-1, 0]]
>>> A == DDM([[ZZ(0), ZZ(1)], [ZZ(-1), ZZ(0)]], (2, 2), ZZ)
True

See Also
========

from_list_flat
r@   )clsr:   r5   r8   s       r)   	from_listDDM.from_list   s    * 8F++rD   c                 "    UR                  5       $ r#   )r4   )rV   others     r)   from_ddmDDM.from_ddm   s    zz|rD   c                 6    U  Vs/ s H  oSS PM	     sn$ s  snf )a  
Convert to a list of lists.

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.ddm import DDM
>>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ)
>>> A.to_list()
[[1, 2], [3, 4]]

See Also
========

to_list_flat
sympy.polys.matrices.domainmatrix.DomainMatrix.to_list
Nr@   r9   r(   s     r)   to_listDDM.to_list   s    & #''$3A$'''s   c                 >    / nU  H  nUR                  U5        M     U$ )aa  
Convert to a flat list of elements.

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.ddm import DDM
>>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ)
>>> A.to_list_flat()
[1, 2, 3, 4]
>>> A == DDM.from_list_flat(A.to_list_flat(), A.shape, A.domain)
True

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.to_list_flat
extend)r9   flatr(   s      r)   to_list_flatDDM.to_list_flat   s$    ( CKK rD   c                     [        U5      [        L d   eUu  pE[        U5      XE-  :X  d  [        S5      e[	        U5       Vs/ s H  oaXe-  US-   U-   PM     nnU " XrU5      $ s  snf )a  
Create a :class:`DDM` from a flat list of elements.

Examples
========

>>> from sympy import QQ
>>> from sympy.polys.matrices.ddm import DDM
>>> A = DDM.from_list_flat([1, 2, 3, 4], (2, 2), QQ)
>>> A
[[1, 2], [3, 4]]
>>> A == DDM.from_list_flat(A.to_list_flat(), A.shape, A.domain)
True

See Also
========

to_list_flat
sympy.polys.matrices.domainmatrix.DomainMatrix.from_list_flat
zInconsistent flat-list shaper   )r$   r%   r-   r   rJ   )rV   rd   r5   r8   r6   r7   r<   lols           r)   from_list_flatDDM.from_list_flat   sp    , DzT!!!
D	TY&!"@AA05d<1AFAaC:&<3v&& =s   A#c                 .    [         R                  " U 5      $ r#   )r   from_iterabler9   s    r)   flatiterDDM.flatiter   s    ""4((rD   c                 >    / nU  H  nUR                  U5        M     U$ r#   rb   )r9   itemsr(   s      r)   rd   DDM.flat   s"    CLL rD   c                 >    U R                  5       R                  5       $ )a  
Convert 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 matrix using :meth:`from_flat_nz`. Zero elements are
included in the list but that may change in the future.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy import QQ
>>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ)
>>> elements, data = A.to_flat_nz()
>>> elements
[1, 2, 3, 4]
>>> A == DDM.from_flat_nz(elements, data, A.domain)
True

See Also
========

from_flat_nz
sympy.polys.matrices.sdm.SDM.to_flat_nz
sympy.polys.matrices.domainmatrix.DomainMatrix.to_flat_nz
)to_sdm
to_flat_nzrm   s    r)   ru   DDM.to_flat_nz   s    < {{}''))rD   c                 L    [         R                  " XU5      R                  5       $ )a  
Reconstruct a :class:`DDM` after calling :meth:`to_flat_nz`.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy import QQ
>>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ)
>>> elements, data = A.to_flat_nz()
>>> elements
[1, 2, 3, 4]
>>> A == DDM.from_flat_nz(elements, data, A.domain)
True

See Also
========

to_flat_nz
sympy.polys.matrices.sdm.SDM.from_flat_nz
sympy.polys.matrices.domainmatrix.DomainMatrix.from_flat_nz
)SDMfrom_flat_nzto_ddm)rV   elementsdatar8   s       r)   ry   DDM.from_flat_nz   s     0 7>>@@rD   c                     0 n[        U 5       H:  u  p#[        U5       VVs0 s H  u  pEU(       d  M  XE_M     nnnU(       d  M6  X1U'   M<     U$ s  snnf )ad  
Convert to a dictionary of dictionaries (dod) format.

Examples
========

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

See Also
========

from_dod
sympy.polys.matrices.sdm.SDM.to_dod
sympy.polys.matrices.domainmatrix.DomainMatrix.to_dod
	enumerate)r9   dodr<   r(   rA   es         r)   to_dod
DDM.to_dod:  sQ    ( oFA#,S>7>41Q313>C7sA & 
 8s
   AAc                     Uu  pE[        U5       Vs/ s H  ocR                  /U-  PM     nnUR                  5        H%  u  pU	R                  5        H  u  pXU   U
'   M     M'     [        XrU5      $ s  snf )a  
Create a :class:`DDM` from a dictionary of dictionaries (dod) format.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy import QQ
>>> dod = {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}
>>> A = DDM.from_dod(dod, (2, 2), QQ)
>>> A
[[1, 2], [3, 4]]

See Also
========

to_dod
sympy.polys.matrices.sdm.SDM.from_dod
sympy.polys.matrices.domainmatrix.DomainMatrix.from_dod
rJ   zerorq   r   )rV   r   r5   r8   r6   r7   _rh   r<   r(   rA   elements               r)   from_dodDDM.from_dodU  so    , 
-24[9[}t#[9iikFA!iik
#Aq	 * " 3v&&	 :s   A2c                 v    0 n[        U 5       H'  u  p#[        U5       H  u  pEU(       d  M  XQX$4'   M     M)     U$ )aq  
Convert :class:`DDM` to dictionary of keys (dok) format.

Examples
========

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

See Also
========

from_dok
sympy.polys.matrices.sdm.SDM.to_dok
sympy.polys.matrices.domainmatrix.DomainMatrix.to_dok
r   )r9   dokr<   r(   rA   r   s         r)   to_dok
DDM.to_dokr  s>    ( oFA'n
7 'I - & 
rD   c                     Uu  pE[        U5       Vs/ s H  ocR                  /U-  PM     nnUR                  5        H  u  u  pn
XU   U	'   M     [        XrU5      $ s  snf )a  
Create a :class:`DDM` from a dictionary of keys (dok) format.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy import QQ
>>> dok = {(0, 0): 1, (0, 1): 2, (1, 0): 3, (1, 1): 4}
>>> A = DDM.from_dok(dok, (2, 2), QQ)
>>> A
[[1, 2], [3, 4]]

See Also
========

to_dok
sympy.polys.matrices.sdm.SDM.from_dok
sympy.polys.matrices.domainmatrix.DomainMatrix.from_dok
r   )rV   r   r5   r8   r6   r7   r   rh   r<   rA   r   s              r)   from_dokDDM.from_dok  s_    , 
-24[9[}t#[9"yy{OFQGF1I  +3v&& :s   Ac              #   J   #    U  H  n[        SU5       Sh  vN   M     g N	7f)aP  
Iterate over the non-zero values of the matrix.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy import QQ
>>> A = DDM([[QQ(1), QQ(0)], [QQ(3), QQ(4)]], (2, 2), QQ)
>>> list(A.iter_values())
[1, 3, 4]

See Also
========

iter_items
to_list_flat
sympy.polys.matrices.domainmatrix.DomainMatrix.iter_values
N)filterr^   s     r)   iter_valuesDDM.iter_values  s$     ( CdC((( (s   #!
#c              #   |   #    [        U 5       H)  u  p[        U5       H  u  p4U(       d  M  X4U4v   M     M+     g7f)az  
Iterate over indices and values of nonzero elements of the matrix.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy import QQ
>>> A = DDM([[QQ(1), QQ(0)], [QQ(3), QQ(4)]], (2, 2), QQ)
>>> list(A.iter_items())
[((0, 0), 1), ((1, 0), 3), ((1, 1), 4)]

See Also
========

iter_values
to_dok
sympy.polys.matrices.domainmatrix.DomainMatrix.iter_items
Nr   )r9   r<   r(   rA   r   s        r)   
iter_itemsDDM.iter_items  s8     (  oFA'n
7&'/) - &s   &<<c                     U $ )a  
Convert to a :class:`DDM`.

This just returns ``self`` but exists to parallel the corresponding
method in other matrix types like :class:`~.SDM`.

See Also
========

to_sdm
to_dfm
to_dfm_or_ddm
sympy.polys.matrices.sdm.SDM.to_ddm
sympy.polys.matrices.domainmatrix.DomainMatrix.to_ddm
r@   rm   s    r)   rz   
DDM.to_ddm  s	      rD   c                 X    [         R                  " X R                  U R                  5      $ )aL  
Convert to a :class:`~.SDM`.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy import QQ
>>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ)
>>> A.to_sdm()
{0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}
>>> type(A.to_sdm())
<class 'sympy.polys.matrices.sdm.SDM'>

See Also
========

SDM
sympy.polys.matrices.sdm.SDM.to_ddm
)rx   rW   r5   r8   rm   s    r)   rt   
DDM.to_sdm  s    * }}T::t{{;;rD   r   )ground_typesc                 V    [        [        U 5      U R                  U R                  5      $ )aL  
Convert to :class:`~.DDM` to :class:`~.DFM`.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy import QQ
>>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ)
>>> A.to_dfm()
[[1, 2], [3, 4]]
>>> type(A.to_dfm())
<class 'sympy.polys.matrices._dfm.DFM'>

See Also
========

DFM
sympy.polys.matrices._dfm.DFM.to_ddm
)DFMr%   r5   r8   rm   s    r)   to_dfm
DDM.to_dfm  s    , 4:tzz4;;77rD   c                 p    [         R                  " U R                  5      (       a  U R                  5       $ U $ )a  
Convert to :class:`~.DFM` if possible or otherwise return self.

Examples
========

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy import QQ
>>> A = DDM([[1, 2], [3, 4]], (2, 2), QQ)
>>> A.to_dfm_or_ddm()
[[1, 2], [3, 4]]
>>> type(A.to_dfm_or_ddm())
<class 'sympy.polys.matrices._dfm.DFM'>

See Also
========

to_dfm
to_ddm
sympy.polys.matrices.domainmatrix.DomainMatrix.to_dfm_or_ddm
)r   _supports_domainr8   r   rm   s    r)   to_dfm_or_ddmDDM.to_dfm_or_ddm  s*    . ,,;;= rD   c                     U R                   nX:X  a  U R                  5       $ U  VVs/ s H#  o3 Vs/ s H  oAR                  XB5      PM     snPM%     nnn[        XPR                  U5      $ s  snf s  snnf r#   )r8   r4   convert_fromr   r5   )r9   KKoldr(   r   r6   s         r)   
convert_toDDM.convert_to5  s_    {{999;BFG$3#6#Q(#6$G4Q'' 7Gs   	A/A*
A/*A/c           
          U  Vs/ s H%  nSSR                  [        [        U5      5      -  PM'     nnSSR                  U5      -  $ s  snf )Nz[%s], )joinmapstr)r9   r(   rowsstrs      r)   __str__DDM.__str__<  sD    @DE6DIIc#sm44E		'*** Fs   ,Ac                     [        U 5      R                  n[        R                  U 5      nU< SU< SU R                  < SU R
                  < S3$ )N(r   ))r$   __name__r%   __repr__r5   r8   )r9   rV   r6   s      r)   r   DDM.__repr__@  s6    4j!!}}T"#&djj$++FFrD   c                    > [        U[        5      (       d  g[        TU ]  U5      =(       a    U R                  UR                  :H  $ )NF)r/   r   r2   __eq__r8   )r9   rZ   r=   s     r)   r   
DDM.__eq__E  s4    %%%u%E$++*EFrD   c                 .    U R                  U5      (       + $ r#   )r   )r9   rZ   s     r)   __ne__
DDM.__ne__J  s    ;;u%%%rD   c                     UR                   nUu  pE[        U5       Vs/ s H  oc/U-  PM
     nn[        XqU5      $ s  snf r#   )r   rJ   r   )rV   r5   r8   zr;   r.   r   r:   s           r)   zeros	DDM.zerosM  s@    KK%*1X.XC!GX.8F++ /   ;c                     UR                   nUu  pE[        U5       Vs/ s H  oc/U-  PM
     nn[        XqU5      $ s  snf r#   )onerJ   r   )rV   r5   r8   r   r;   r.   r   rowlists           r)   onesDDM.onesT  s@    jj&+Ah/h519h/76** 0r   c                     [        U[        5      (       a  Uu  p4O[        U[        5      (       a  U=p4UR                  nU R	                  WW4U5      n[        [        X45      5       H
  nXVU   U'   M     U$ r#   )r/   tupleintr   r   rJ   min)rV   sizer8   r;   r.   r   rM   r<   s           r)   eyeDDM.eye[  sl    dE""DAqc""LAjjiiA's1y!AF1I "
rD   c                 t    U  Vs/ s H  oS S  PM	     nn[        X R                  U R                  5      $ s  snf r#   )r   r5   r8   )r9   r(   copyrowss      r)   r4   DDM.copyg  s2    &*+dsFd+8ZZ55 ,s   5c                     U R                   u  pU(       a  [        U 5      nO/ /U-  n[        X2U4U R                  5      $ r#   )r5   r   r   r8   )r9   r6   r7   ddmTs       r)   	transposeDDM.transposek  s:    ZZ
 &D4$;D4t{{33rD   c                 Z    [        U[        5      (       d  [        $ U R                  U5      $ r#   )r/   r   NotImplementedaddabs     r)   __add__DDM.__add__s  "    !S!!!!uuQxrD   c                 Z    [        U[        5      (       d  [        $ U R                  U5      $ r#   )r/   r   r   subr   s     r)   __sub__DDM.__sub__x  r   rD   c                 "    U R                  5       $ r#   )negr   s    r)   __neg__DDM.__neg__}  s    uuwrD   c                 N    XR                   ;   a  U R                  U5      $ [        $ r#   r8   mulr   r   s     r)   __mul__DDM.__mul__      =558O!!rD   c                 N    XR                   ;   a  U R                  U5      $ [        $ r#   r   r   s     r)   __rmul__DDM.__rmul__  r   rD   c                 Z    [        U[        5      (       a  U R                  U5      $ [        $ r#   )r/   r   matmulr   r   s     r)   
__matmul__DDM.__matmul__  s#    a88A;!!rD   c                     UR                   UR                   :w  a-  SUR                   < SU< SUR                   < 3n[        U5      eXE:w  a-  SUR                  < SU< SUR                  < 3n[        U5      eg )NzDomain mismatch:  zShape mismatch: )r8   r   r5   r
   )rV   r   opr   ashapebshapemsgs          r)   _check
DDM._check  s[    88qxx122qxxHC$$01QWWECs## rD   c                     U R                  U SXR                  UR                  5        U R                  5       n[        X!5        U$ )za + b+)r   r5   r4   r   r   r   cs      r)   r   DDM.add  3    	CGGQWW-FFHrD   c                     U R                  U SXR                  UR                  5        U R                  5       n[        X!5        U$ )za - b-)r   r5   r4   r   r  s      r)   r   DDM.sub  r  rD   c                 <    U R                  5       n[        U5        U$ )z-a)r4   r   r   s     r)   r   DDM.neg  s    FFHrD   c                 <    U R                  5       n[        X!5        U$ r#   )r4   r   r  s      r)   r   DDM.mul  s    FFHrD   c                 <    U R                  5       n[        X!5        U$ r#   )r4   r   r  s      r)   rmulDDM.rmul  s    FFH!rD   c                     U R                   u  p#UR                   u  pEU R                  U SXU5        U R                  X%4U R                  5      n[	        X`U5        U$ )za @ b (matrix product)*)r5   r   r   r8   r   )r   r   r;   oo2r.   r  s          r)   r   
DDM.matmul  sO    ww	Cr"GGQFAHH%A!rD   c                 T   U R                   UR                   :X  d   eU R                  UR                  :X  d   e[        X5       VVVVs/ s H'  u  p#[        X#5       VVs/ s H	  u  pEXE-  PM     snnPM)     nnnnn[        X`R                   U R                  5      $ s  snnf s  snnnnf r#   )r5   r8   zipr   )r   r   aibiaijbijr  s          r)   mul_elementwiseDDM.mul_elementwise  s|    ww!''!!!xx188###CFq9M9B4HCci49M1ggqxx(( 5Ms   	B"
B/B"
B"
c                 N   [        U R                  5       5      nU R                  u  p4U R                  nU HU  nUR                  u  pxXs:X  d   eUR                  U:X  d   eXH-  n[	        U5       H  u  pX)   R                  U
5        M     MW     [        X#U4U R                  5      $ )a  Horizontally stacks :py:class:`~.DDM` matrices.

Examples
========

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

>>> A = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DDM([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ)
>>> A.hstack(B)
[[1, 2, 5, 6], [3, 4, 7, 8]]

>>> C = DDM([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
>>> A.hstack(B, C)
[[1, 2, 5, 6, 9, 10], [3, 4, 7, 8, 11, 12]]
)r%   r4   r5   r8   r   rc   r   )ABAnewr6   r7   r8   BkBkrowsBkcolsr<   Bkis              r)   hstack
DDM.hstack  s    $ AFFH~WW
BXXNF>!>99&&&ND#B-s# (  4qxx00rD   c                 >   [        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X7-  nUR	                  UR                  5       5        MO     [        X#U4U R                  5      $ )a  Vertically stacks :py:class:`~.DDM` matrices.

Examples
========

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

>>> A = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DDM([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ)
>>> A.vstack(B)
[[1, 2], [3, 4], [5, 6], [7, 8]]

>>> C = DDM([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
>>> A.vstack(B, C)
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]
)r%   r4   r5   r8   rc   r   )	r  r  r   r6   r7   r8   r!  r"  r#  s	            r)   vstack
DDM.vstack  s    $ AFFH~WW
BXXNF>!>99&&&NDKK	"  4qxx00rD   c           	          U  Vs/ s H  n[        [        X5      5      PM     nn[        X@R                  U5      $ s  snf r#   )r%   r   r   r5   )r9   funcr8   r(   r{   s        r)   	applyfuncDDM.applyfunc  s5    489DSDT(D98ZZ00 :s   ;c                 &    [        S U  5       5      $ )zNumber of non-zero entries in :py:class:`~.DDM` matrix.

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.nnz
c              3   T   #    U  H  n[        [        [        U5      5      v   M      g 7fr#   )sumr   boolr&   s     r)   r*   DDM.nnz.<locals>.<genexpr>  s     4!33s4~&&!s   &()r0  r   s    r)   nnzDDM.nnz  s     4!444rD   c                 >    U R                  5       R                  5       $ )a)  Strongly connected components of a square matrix *a*.

Examples
========

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

See also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.scc

)rt   sccr   s    r)   r6  DDM.scc  s    $ xxz~~rD   c                 J    [         R                  " X5      R                  5       $ )a,  Returns a square diagonal matrix with *values* on the diagonal.

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import DDM
>>> DDM.diag([ZZ(1), ZZ(2), ZZ(3)], ZZ)
[[1, 0, 0], [0, 2, 0], [0, 0, 3]]

See also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.diag
)rx   diagrz   )rV   valuesr8   s      r)   r9  DDM.diag-  s    " xx'..00rD   c                     U R                  5       nU R                  nUR                  =(       d    UR                  n[	        XS9nX4$ )zReduced-row echelon form of a and list of pivots.

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.rref
    Higher level interface to this function.
sympy.polys.matrices.dense.ddm_irref
    The underlying algorithm.
)_partial_pivot)r4   r8   is_RealFieldis_ComplexFieldr   )r   r   r   partial_pivotpivotss        r)   rrefDDM.rref@  s>     FFHHH;!*;*;1;yrD   c                 \    U R                  5       nU R                  n[        X5      u  p4XU4$ )a  Reduced-row echelon form of a with denominator and list of pivots

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.rref_den
    Higher level interface to this function.
sympy.polys.matrices.dense.ddm_irref_den
    The underlying algorithm.
)r4   r8   r   )r   r   r   denomrA  s        r)   rref_denDDM.rref_denQ  s/     FFHHH%a+rD   c                 H    U R                  5       u  pUR                  U5      $ )zReturns a basis for the nullspace of a.

The domain of the matrix must be a field.

See Also
========

rref
sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace
)rB  nullspace_from_rref)r   rB  rA  s      r)   	nullspaceDDM.nullspacea  s"     vvx''//rD   c                    U R                   u  p#U R                  nUcO  / nSn[        U5       H<  nX   n[        US-   U5       H"  nXx   (       d  M  UnUR                  U5          M:     M>     U(       d%  U R	                  X45      [        [        U5      5      4$ U S   US      n	/ n
/ n[        U5       H}  nXa;   a  M
  UR                  U5        [        U5       Vs/ s H  oU:X  a  U	OUR                  PM     nn[        U5       H  u  pX==   X   U   -  ss'   M     U
R                  U5        M     [        U
[        U
5      U4U5      nX4$ s  snf )a  Compute the nullspace of a matrix from its rref.

The domain of the matrix can be any domain.

Returns a tuple (basis, nonpivots).

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.nullspace
    The higher level interface to this function.
r   r   )
r5   r8   rJ   rQ   r   r%   r   r   r   r-   )r   rA  r;   r.   r   
last_pivotr<   r  rA   	pivot_valbasis	nonpivotsveciijj	basis_ddms                   r)   rI  DDM.nullspace_from_rrefo  sH    wwHH>FJ1XTz!|Q/Auu%&
a(	 0  EE!KeAh00 aDO		qA{Q<A!HEHqQ9AFF2HCE#F+158# ,LL  E
A2	%% Fs   Ec                 Z    U R                  5       R                  5       R                  5       $ r#   )rt   
particularrz   r   s    r)   rX  DDM.particular  s     xxz$$&--//rD   c                     U R                   u  pX:w  a  [        S5      eU R                  5       nUR                  n[	        X45      nU$ )zDeterminant of a Determinant of non-square matrix)r5   r	   r4   r8   r   )r   r;   r.   r   r   detas         r)   detDDM.det  s@    ww6()KLLFFHHH~rD   c                     U R                   u  pX:w  a  [        S5      eU R                  5       nU R                  n[	        X0U5        U$ )zInverse of ar[  )r5   r	   r4   r8   r   )r   r;   r.   ainvr   s        r)   invDDM.inv  sA    ww6()KLLvvxHH!rD   c                     U R                   u  pU R                  nU R                  5       nU R                  X5      n[	        XTU5      nXTU4$ )zL, U decomposition of a)r5   r8   r4   r   r   )r   r;   r.   r   ULswapss          r)   luDDM.lu  sD    wwHHFFHEE!KaA&U{rD   c                   ^^^ U R                   u  pU R                  mU R                  5       m[        [	        U5      5      nSn[	        [        X5      5       GH  m[        UUU4S j[	        U5       5       5      (       a  M+  Sn[	        XA5       H  nTU   T   TR                  :w  d  M  Un  O   US:X  a  Ma  XT:w  a  TU   TU   sTU'   TU'   X5   X4   sX4'   X5'   TU   T   n[	        US-   U5       Hv  nTU   T   nUS:  a  TUS-
     US-
     OTR                  n	[	        TS-   U5       H0  n
TR                  UTU   U
   -  TU   U
   U-  -
  U	5      TU   U
'   M2     UTU   T'   Mx     US-  nGM     TU4$ )z
Private method for Phase 1 of fraction-free LU decomposition.
Performs row operations and elimination to compute U and permutation indices.

Returns:
    LU : decomposition as a single matrix.
    perm (list): Permutation indices for row swaps.
r   c              3   N   >#    U  H  nTU   T   TR                   :H  v   M     g 7fr#   )r   )r'   r<   r   LUrA   s     r)   r*   DDM._fflu.<locals>.<genexpr>  s"     ;{!2a58qvv%{   "%rM  r   )
r5   r8   r4   r%   rJ   r   r0   r   r   exquo)r9   r6   r7   permrank	pivot_rowr<   pivot
multiplierdenominatorkr   rk  rA   s              @@@r)   _fflu	DDM._fflu  s    ZZ
KKYY[E$K s4'A;uT{;;; I4&a58qvv% !I ' B  *,Y-D'4"Y-.2otz+
DO tHQKE4!8T*U1X
8<qbl4!84aeeq1ud+A wwur!uQx'7"T(1+
:R'RT_`BqE!H , &1a + AID? (B 4xrD   c                    U R                   u  pU R                  nU R                  5       u  pEU R                  X4U5      n[	        U5       H  u  pxUR
                  Xg   U'   M     U R                  X4U5      n	S=pzXq:  ao  X:  aj  XG   U
   UR                  :w  aD  XG   U
   X   U'   [        US-   U5       H   nXK   U
   X   U'   UR                  XK   U
'   M"     US-  nU
S-  n
Xq:  a  X:  a  Mj  [        Xq5       H  nUR
                  X   U'   M     U R                  X4U5      nUS:  a  U	S   S   US   S'   UR
                  n[        SU5       H  nXS-
     US-
     X   U   -  nXU   U'   M!     XiX4$ )z
Fraction-free LU decomposition of DDM.

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.fflu
    The higher-level interface to this function.
r   r   )r5   r8   rv  r   r   r   r   rJ   )r9   r6   r7   r   rd  ro  Pr<   pire  rA   lDdis                 r)   ffluDDM.fflu  s    ZZ
KK **, JJ|Q't_EAuuADH % JJ|Q'	h18tAw!&&  $q'Qq1ud+Ad1gADGffADG	 ,
 QFA h18 qAeeADG   JJ|Q'19d1gAaDGUUq$Aq5!a%147*BaDG  
 QzrD   c           	        ^	^
^ U R                   u  mnU R                  m	U R                  5       m
U R                  [	        TU5      U4T	5      nT	R
                  (       d  [        S5      eU	U
U4S jn[        U5       H  n[        [	        UT5      5       H]  nU" XU5      nUT	R                  :w  d  M  U" XT5      U-  X%   U'   [        T5       H!  nT
U   U==   X%   U   T
U   U   -  -  ss'   M#     M_     UT:  d  M  U" XD5      nUT	R                  :w  d  M  T	R                  X$   U'   M     T
R                  [        T5      [        [	        TU5      5      5      m
T
U4$ )z
QR decomposition for DDM.

Returns:
    - Q: Orthogonal matrix as a DDM.
    - R: Upper triangular matrix as a DDM.

See Also
========

sympy.polys.matrices.domainmatrix.DomainMatrix.qr
    The higher-level interface to this function.
z,QR decomposition requires a field (e.g. QQ).c                 T   >^ ^ TR                  UU U4S j[        T5       5       5      $ )Nc              3   F   >#    U  H  nTU   T   TU   T   -  v   M     g 7fr#   r@   )r'   ru  Qr<   rA   s     r)   r*   +DDM.qr.<locals>.<lambda>.<locals>.<genexpr>A  s&     %MAad1g!Q&7s   !)r0  rJ   )r<   rA   r   r  r6   s   ``r)   <lambda>DDM.qr.<locals>.<lambda>A  s    %Mt%M MrD   )r5   r8   r4   r   r   is_Fieldr   rJ   r   r   rS   )r9   r7   Rdot_colsrA   r<   dot_iiru  dot_jjr   r  r6   s            @@@r)   qrDDM.qr*  s1    ZZ
dKKIIKJJD$.2 zz NOOMtA3q$<(!!QVV#&qnv5ADG"4[!Q147QqT!W#44 )	 ) 4x!!QVV#eeADG  IIeDk5T4#9:!trD   c                 ,   U R                   u  p#UR                   u  pEU R                  U SXU5        U R                  R                  (       d  [	        S5      eU R                  5       u  pgnU R                  X54U R                  5      n	[        XXxU5        U	$ )zx where a*x = blu_solvezlu_solve requires a field)r5   r   r8   r  r   rg  r   r   )
r   r   r;   r.   m2r  re  rd  rf  xs
             r)   r  DDM.lu_solveT  sy    ww	Jb)xx   ;<<ddfeGGQFAHH%aAa(rD   c                     U R                   nU R                  u  p#X#:w  a  [        S5      e[        X5      n[	        US-   5       Vs/ s H
  oTU   S   PM     nnU$ s  snf )z.Coefficients of characteristic polynomial of azCharpoly of non-square matrixr   r   )r8   r5   r	   r   rJ   )r   r   r;   r.   rR  r<   coeffss          r)   charpolyDDM.charpolya  s\    HHww6()HIIqn%*1Q3Z0Za&)Z0 1s   Ac                 v   ^ U R                   R                  m[        U4S jU R                  5        5       5      $ )z0
Says whether this matrix has all zero entries.
c              3   ,   >#    U  H	  oT:H  v   M     g 7fr#   r@   )r'   Mijr   s     r)   r*   %DDM.is_zero_matrix.<locals>.<genexpr>p  s     :/3$;/s   )r8   r   r0   rn   r9   r   s    @r)   is_zero_matrixDDM.is_zero_matrixk  s+     {{:$--/:::rD   c                 l   ^ U R                   R                  m[        U4S j[        U 5       5       5      $ )zf
Says whether this matrix is upper-triangular. True can be returned
even if the matrix is not square.
c              3   J   >#    U  H  u  pUS U   H	  o3T:H  v   M     M     g 7fr#   r@   r'   r<   Mir  r   s       r)   r*   DDM.is_upper.<locals>.<genexpr>x  s#     NO51r"1v$;v;Os    #r8   r   r0   r   r  s    @r)   is_upperDDM.is_upperr  s)    
 {{NIdONNNrD   c                 l   ^ U R                   R                  m[        U4S j[        U 5       5       5      $ )zf
Says whether this matrix is lower-triangular. True can be returned
even if the matrix is not square.
c              3   N   >#    U  H  u  pX!S -   S   H	  o3T:H  v   M     M     g7f)r   Nr@   r  s       r)   r*   DDM.is_lower.<locals>.<genexpr>  s%     PO51rA#$x$;x;Orm  r  r  s    @r)   is_lowerDDM.is_lowerz  s)    
 {{PIdOPPPrD   c                 P    U R                  5       =(       a    U R                  5       $ )z^
Says whether this matrix is diagonal. True can be returned even if
the matrix is not square.
)r  r  rm   s    r)   is_diagonalDDM.is_diagonal  s    
 }}24==?2rD   c                 |    U R                   u  p[        [        X5      5       Vs/ s H
  o0U   U   PM     sn$ s  snf )zA
Returns a list of the elements from the diagonal of the matrix.
)r5   rJ   r   )r9   r;   r.   r<   s       r)   diagonalDDM.diagonal  s8     zz$)#a)$45$4qQ
$4555s   9      c                     [        XS9$ N)delta)r   r  r  s     r)   lllDDM.lll  s    q&&rD   c                     [        XS9$ r  )r   r  s     r)   lll_transformDDM.lll_transform  s     00rD   )r7   r8   r6   r5   r#   )Wr   
__module____qualname____firstlineno____doc__fmtis_DFMis_DDMr3   rB   rG   rN   rS   classmethodrW   r[   r_   re   ri   rn   rd   ru   ry   r   r   r   r   r   r   rz   rt   r   r   r   r   r   r   r   r   r   r   r   r4   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r  r%  r(  r,  r3  r6  r9  rB  rF  rJ  rI  rX  r]  ra  rg  rv  r~  r  r  r  r  r  r  r  r  r   r  r  __static_attributes____classcell__)r=   s   @r)   r   r   f   s    CFF3= , ,,  (*2 ' '8)*@ A A26 ' '86 ' '6).*2$<. gY/8 08. gY/ 04(+G
G
& , , + + 	 	64

""" $ $

) 1D1B15 ( 1 1$"  0.&`0	1f4l(T;OQ36 1X '  "!Qx 1 1rD   r   )rx   )r   N)'r  	itertoolsr   sympy.external.gmpyr   sympy.utilities.decoratorr   
exceptionsr   r   r	   r
   sympy.polys.domainsr   r    r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   __doctest_skip__r%   r   sdmrx   dfmr   r@   rD   r)   <module>r     sk   >~  , 8  #
 
 
 
" , 7$&9:n1$ n1b!  rD   