
    \hB                         S r SSKJr  SSKJr  SSKJrJr  SSKJ	r	  SSK
JrJr  S rS	 rS
 rS rS rS rS rS rS rSSS.S jrg)z,Functions returning normal forms of matrices    )defaultdict   )DomainMatrix)DMDomainErrorDMShapeError)symmetric_residue)QQZZc                 r    [        U 5      n[        R                  " XR                  U R                  5      nU$ )a  
Return the Smith Normal Form of a matrix `m` over the ring `domain`.
This will only work if the ring is a principal ideal domain.

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.polys.matrices.normalforms import smith_normal_form
>>> m = DomainMatrix([[ZZ(12), ZZ(6), ZZ(4)],
...                   [ZZ(3), ZZ(9), ZZ(6)],
...                   [ZZ(2), ZZ(16), ZZ(14)]], (3, 3), ZZ)
>>> print(smith_normal_form(m).to_Matrix())
Matrix([[1, 0, 0], [0, 10, 0], [0, 0, 30]])

)invariant_factorsr   diagdomainshape)minvssmfs      X/var/www/auris/envauris/lib/python3.13/site-packages/sympy/polys/matrices/normalforms.pysmith_normal_formr      s-    $ QD


D((AGG
4CJ    c                    U R                   nU R                  nUR                  nU R                  5       n [	        US   5       H-  n[	        US   5       H  nXE:X  a  M
  X   U   U:X  a  M      g   M/     [        US   US   5      n[	        SU5       HO  nXS-
     US-
     U:X  a  X   U   U:w  a    gM#  UR                  X   U   XS-
     US-
     5      S   nXs:w  d  MO    g   g)z0
Checks that the matrix is in Smith Normal Form
r   r   FT)r   r   zeroto_listrangemindiv)r   r   r   r   ijupperrs           r   is_smith_normal_formr    (   s     XXFGGE;;D			A58_uQxAv47d?	 !  a%(#E1e_qS6!A#;$tAw$  

147AcF1Q3K03Ay  r   c                     [        [        U 5      5       H2  nX   U   nX8-  X@U   U   -  -   X   U'   XX-  X`U   U   -  -   X   U'   M4     g Nr   len	r   r   r   abcdkes	            r   add_columnsr,   E   sW     3q6]DG#A$q'	/Q#A$q'	/Q r   c                 h    U R                   nU R                  nU R                  5       n [        XUSS9$ )a  
Return the tuple of abelian invariants for a matrix `m`
(as in the Smith-Normal form)

References
==========

[1] https://en.wikipedia.org/wiki/Smith_normal_form#Algorithm
[2] https://web.archive.org/web/20200331143852/https://sierra.nmsu.edu/morandi/notes/SmithNormalForm.pdf

Fr   full)r   r   r   _smith_normal_decomp)r   r   r   s      r   r   r   N   s0     XXFGGE			AUCCr   c                     U R                   nU R                  =u  p#nU R                  5       n [        XUSS9u  pVn[        R
                  " XQU5      R                  5       n[	        XaX"4S9n[	        XqX34S9nXU4$ )a  
Return the Smith-Normal form decomposition of matrix `m`.

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.polys.matrices.normalforms import smith_normal_decomp
>>> m = DomainMatrix([[ZZ(12), ZZ(6), ZZ(4)],
...                   [ZZ(3), ZZ(9), ZZ(6)],
...                   [ZZ(2), ZZ(16), ZZ(14)]], (3, 3), ZZ)
>>> a, s, t = smith_normal_decomp(m)
>>> assert a == s * m * t
Tr.   )r   r   )r   r   r   r0   r   r   to_dense)	r   r   rowscolsr   r   str   s	            r   smith_normal_decompr7   `   s{      XXF JD			A%au4HJDQ


D%
0
9
9
;CQd\:AQd\:A19r   c           
      
  ^ ^^^^ ^!^"^#^$^% TR                   (       d  ST 3n[        U5      eUu  m"m TR                  m%TR                  m!U!U%4S jnSU;   a  T(       a  SU" T"5      U" T 5      4$ gT(       a  U" T"5      m#U" T 5      m$S mUUUU U"U#U%4S jnU UUU U$U%4S jn[	        T"5       Vs/ s H  nT U   S   T%:w  d  M  UPM     n	nU	(       a?  U	S   T%:w  a6  T U	S      T S   sT S'   T U	S   '   T(       a  T#U	S      T#S   sT#S'   T#U	S   '   O|[	        T 5       V
s/ s H  n
T S   U
   T%:w  d  M  U
PM     n	n
U	(       aL  U	S   T%:w  aC  T  H  nXS      US   sUS'   XS   '   M     T(       a  T$ H  nXS      US   sUS'   XS   '   M     [        U U%4S j[	        S	T 5       5       5      (       d%  [        U U%4S
 j[	        S	T"5       5       5      (       a\  U" 5         U" 5         [        U U%4S j[	        S	T 5       5       5      (       a  M5  [        U U%4S
 j[	        S	T"5       5       5      (       a  M\  U4S jnT S   S   S:w  au  TR                  T S   S   5      nTR                  (       a  S	T S   S   -  nUTR                  :w  a2  T S   S==   U-  ss'   T(       a  T#S    Vs/ s H  oU-  PM	     snT#S'   S	U;   a  SnOT S	S  Vs/ s H  nUS	S PM
     nn[        UTT"S	-
  T S	-
  4TS9nT(       a  Uu  nnnS	/S/T"S	-
  -  -   /U Vs/ s H	  nS/U-   PM     sn-   nS	/S/T S	-
  -  -   /U Vs/ s H	  nS/U-   PM     sn-   n[        [        UT#UT$U/5      5      u  m#nm$nUT#-  m#T$U-  m$T#R                  5       m#T$R                  5       m$OUnT S   S   (       Ga1  T S   S   /nUR                  U5        [	        [        U5      S	-
  5       H  nUU   UUS	-      nnU(       a  TR                  UU5      S	   T%:w  a  T(       a  TR                  UU5      u  nnnOTR!                  UU5      nTR                  UU5      S   nT(       am  TR                  UU5      S   nT" T#XS	-   S	SWS	5        [#        T$XS	-   S	WSS	5        T" T#XS	-   S	U* SS	5        [#        T$XS	-   S	SU* S	5        T" T#XS	-   SS	SS5        UU-  UUS	-   '   UUU'   M    OJ   OGT(       a4  T"S	:  a  T#S	S T#S   /-   m#T S	:  a  T$ Vs/ s H  oS	S US   /-   PM     snm$UT S   S   4-   nT(       a  [%        U5      T#T$4$ [%        U5      $ s  snf s  sn
f s  snf s  snf s  snf s  snf s  snf )z
Return the tuple of abelian invariants for a matrix `m`
(as in the Smith-Normal form). If `full=True` then invertible matrices
``s, t`` such that the product ``s, m, t`` is the Smith Normal Form
are also returned.
zBThe matrix entries must be over a principal ideal domain, but got c           	         > [        U 5       VVs/ s H&  n[        U 5       Vs/ s H  o"U:X  a  TOTPM     snPM(     snn$ s  snf s  snnf r"   )r   )nr   r   oner   s      r   eye!_smith_normal_decomp.<locals>.eye   s>    EJ1XNX%(;(QQD((;XNN;Ns   AAAAr    c                     [        [        U S   5      5       H2  nX   U   nX8-  X@U   U   -  -   X   U'   XX-  X`U   U   -  -   X   U'   M4     g )Nr   r#   r%   s	            r   add_rows&_smith_normal_decomp.<locals>.add_rows   s\     s1Q4y!AQAcAd1gIoADGcAd1gIoADG "r   c            
        > TS   S   n [        ST5       H  nTU   S   T:X  a  M  T
R                  TU   S   U 5      u  p#UT:X  a)  T	" TSUSSU* S5        T(       a  T	" TSUSSU* S5        MX  MZ  T
R                  U TU   S   5      u  pEnT
R                  TU   S   U5      nT
R                  X5      nT	" TSXXWU* 5        T(       a  T	" TSXXWU* 5        Un M     g Nr   r   )r   r   gcdexexquo)pivotr   r)   r   r&   r'   gd_0d_jr@   r   r/   r   r3   r5   r   s            r   clear_column*_smith_normal_decomp.<locals>.clear_column   s    !Qq$AtAw$::ad1gu-DADyAq!QA.Q1aQB2  !,,uad1g6all1Q47A.ll5,AqQcT2Q1#6  r   c            
        > TS   S   n [        ST	5       H  nTS   U   T:X  a  M  T
R                  TS   U   U 5      u  p#UT:X  a/  [        TSUSSU* S5        T(       a  [        TSUSSU* S5        M^  M`  T
R                  U TS   U   5      u  pEnT
R	                  TS   U   U5      nT
R	                  X5      n[        TSXXWU* 5        T(       a  [        TSXXWU* 5        Un M     g rC   )r   r   r,   rD   rE   )rF   r   r)   r   r&   r'   rG   rH   rI   r4   r   r/   r   r6   r   s            r   	clear_row'_smith_normal_decomp.<locals>.clear_row   s    !Qq$AtAw$::ad1gu-DADyAq!QA2q11aAr15  !,,uad1g6all1Q47A.ll5,Aq!51aASD9  r   c              3   :   >#    U  H  nTS    U   T:g  v   M     g7fr   Nr>   .0r   r   r   s     r   	<genexpr>'_smith_normal_decomp.<locals>.<genexpr>        61qtAw$   r   c              3   :   >#    U  H  nTU   S    T:g  v   M     g7frP   r>   rQ   s     r   rS   rT      rU   rV   c                 H   > [        U [        U 5      [        U S   5      4TS9$ )Nr   )r   r   )r   r$   )r   r   s    r   to_domain_matrix._smith_normal_decomp.<locals>.to_domain_matrix   s#    Ac!fc!A$i%8HHr   Nr.   )is_PID
ValueErrorr   r;   r   anycanonical_unitis_Fieldr0   listmapr   extendr$   r   rD   gcdr,   tuple)&r   r   r   r/   msgr<   rJ   rM   r   indr   rowrY   r(   elemr   r   lower_rightrets_smallt_smalls2t2resultr&   r'   xyr)   alphabetar@   r4   r;   r3   r5   r6   r   s&   `` `                           @@@@@@@r   r0   r0   |   s    ==RSYRZ[oJD$;;D
**CO 	Ezs4y#d)++II& ( * Dk
5kQqT!W_1kC
5
s1v~CF)QqT!aAiAi1OAaD!CF)+9+Q1aDq+93q6T>&)a&k3q6#AF C*-!f+s1v'CFCAK  6a6666a666 6a6666a666I 	tAw!|!!!A$q'*??AaDGA

?aDGqLG-.qT2TTqT2!Ez&'e,eque,";ax*7%("D'7#T!V$%g(Fgs!sg(FFB#T!V$%g(Fgs!sg(FFB$4q"an EFLAr1bQABA		A		ADtAwwA$q'ds6{1}%A!9fQqSkqAVZZ1%a(D0$ll1a0GAq!

1a(A

1a(+!::a+A.DQq5!Q151!eQ1a8Qq5!eVQ:1!eQD5!<Qq5!QA6%iqsq	) &, axabEQqTFNax3451CWAx'151a
"V}a""V}m 6 :0 3
 -
 )G(FN 6s6   -T7T7T<0T<$UUU1U3Uc                 p    [         R                  " X5      u  p#nU S:w  a  X-  S:X  a  SnU S:  a  SOSnX#U4$ )a  
This supports the functions that compute Hermite Normal Form.

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

Let x, y be the coefficients returned by the extended Euclidean
Algorithm, so that x*a + y*b = g. In the algorithms for computing HNF,
it is critical that x, y not only satisfy the condition of being small
in magnitude -- namely that |x| <= |b|/g, |y| <- |a|/g -- but also that
y == 0 when a | b.

r   r[   r   )r
   rD   )r&   r'   rq   rr   rG   s        r   _gcdexrv   "  s?     hhqnGA!Av!%1*a%BQ7Nr   c                    U R                   R                  (       d  [        S5      eU R                  u  pU R	                  5       R                  5       n Un[        US-
  SS5       H  nUS:X  a    OUS-  n[        US-
  SS5       HK  nX   U   S:w  d  M  [        X   U   X   U   5      u  pgnX   U   U-  X   U   U-  p[        XXVXz* U	5        MM     X   U   nUS:  a  [        XUSSSS5        U* nUS:X  a  US-  nM  [        US-   U5       H  nX   U   U-  n[        XUSU* SS5        M      M     [        R                  " U R                  5       5      SS2US24   $ )a  
Compute the Hermite Normal Form of DomainMatrix *A* over :ref:`ZZ`.

Parameters
==========

A : :py:class:`~.DomainMatrix` over domain :ref:`ZZ`.

Returns
=======

:py:class:`~.DomainMatrix`
    The HNF of matrix *A*.

Raises
======

DMDomainError
    If the domain of the matrix is not :ref:`ZZ`.

References
==========

.. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*
   (See Algorithm 2.4.5.)

Matrix must be over domain ZZ.r   r[   r   N)r   is_ZZr   r   to_ddmcopyr   rv   r,   r   from_repto_dfm_or_ddm)Ar   r:   r*   r   r   uvr)   r   r5   r'   qs                r   _hermite_normal_formr   7  sz   8 88>><== 77DA	
A 	
A1q5"b!6 	Q q1ub"%AtAw!| !a!$q'2atAw!|QT!W\1A!2q1 & DGq5aQA.A 6FA
 1q5!_DGqLA!QAq1 %? "H   !23AqrE::r   c                    U R                   R                  (       d  [        S5      e[        R                  " U5      (       a  US:  a  [        S5      eS n[        [        5      nU R                  u  pEXT:  a  [        S5      eU R                  5       n UnUn[        US-
  SS5       H  nUS-  n[        US-
  SS5       HI  n	X   U	   S:w  d  M  [        X   U   X   U	   5      u  pnX   U   U-  X   U	   U-  pU" XXiXU* U5        MK     X   U   nUS:X  a	  U=X   U'   n[        X5      u  pn[        U5       H  nXU   U   -  U-  UU   U'   M     X8   U   S:X  a  XsU   U'   [        US-   U5       H#  n	X8   U	   X8   U   -  n[        X9USU* SS5        M%     X|-  nM     [        X4U4[        5      R                  5       $ )a  
Perform the mod *D* Hermite Normal Form reduction algorithm on
:py:class:`~.DomainMatrix` *A*.

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

If *A* is an $m \times n$ matrix of rank $m$, having Hermite Normal Form
$W$, and if *D* is any positive integer known in advance to be a multiple
of $\det(W)$, then the HNF of *A* can be computed by an algorithm that
works mod *D* in order to prevent coefficient explosion.

Parameters
==========

A : :py:class:`~.DomainMatrix` over :ref:`ZZ`
    $m \times n$ matrix, having rank $m$.
D : :ref:`ZZ`
    Positive integer, known to be a multiple of the determinant of the
    HNF of *A*.

Returns
=======

:py:class:`~.DomainMatrix`
    The HNF of matrix *A*.

Raises
======

DMDomainError
    If the domain of the matrix is not :ref:`ZZ`, or
    if *D* is given but is not in :ref:`ZZ`.

DMShapeError
    If the matrix has more rows than columns.

References
==========

.. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*
   (See Algorithm 2.4.8.)

rx   r   z0Modulus D must be positive element of domain ZZ.c                     [        [        U 5      5       HL  nX   U   n	[        XI-  XPU   U   -  -   U-  U5      X   U'   [        Xi-  XpU   U   -  -   U-  U5      X   U'   MN     g r"   )r   r$   r   )
r   Rr   r   r&   r'   r(   r)   r*   r+   s
             r   add_columns_mod_R8_hermite_normal_form_modulo_D.<locals>.add_columns_mod_R  sq     s1vAQA'qT!W)<(A1EADG'qT!W)<(A1EADG r   z2Matrix must have at least as many columns as rows.r[   r   )r   ry   r   r
   of_typer   dictr   r   r   r   rv   r,   r   r2   )r~   Dr   Wr   r:   r*   r   r   r   r   r   r)   r   r5   r'   iir   s                     r   _hermite_normal_form_modulo_Dr     s   Z 88>><==::a==AENOOF 	DA77DAuOPP			A	A	A1q5"b!	Qq1ub"%AtAw!| a!$q'2atAw!|QT!W\1!!aQB:	 &
 DG6OADGa,a(B2qzA~AbE!H 47a<aDGq1uaAQ147"AaQB1- ! 	
% "& q62&//11r   NF)r   
check_rankc                    U R                   R                  (       d  [        S5      eUbF  U(       a4  U R                  [        5      R                  5       U R                  S   :X  a  [        X5      $ [        U 5      $ )a}  
Compute the Hermite Normal Form of :py:class:`~.DomainMatrix` *A* over
:ref:`ZZ`.

Examples
========

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.polys.matrices.normalforms import hermite_normal_form
>>> m = DomainMatrix([[ZZ(12), ZZ(6), ZZ(4)],
...                   [ZZ(3), ZZ(9), ZZ(6)],
...                   [ZZ(2), ZZ(16), ZZ(14)]], (3, 3), ZZ)
>>> print(hermite_normal_form(m).to_Matrix())
Matrix([[10, 0, 2], [0, 15, 3], [0, 0, 2]])

Parameters
==========

A : $m \times n$ ``DomainMatrix`` over :ref:`ZZ`.

D : :ref:`ZZ`, optional
    Let $W$ be the HNF of *A*. If known in advance, a positive integer *D*
    being any multiple of $\det(W)$ may be provided. In this case, if *A*
    also has rank $m$, then we may use an alternative algorithm that works
    mod *D* in order to prevent coefficient explosion.

check_rank : boolean, optional (default=False)
    The basic assumption is that, if you pass a value for *D*, then
    you already believe that *A* has rank $m$, so we do not waste time
    checking it for you. If you do want this to be checked (and the
    ordinary, non-modulo *D* algorithm to be used if the check fails), then
    set *check_rank* to ``True``.

Returns
=======

:py:class:`~.DomainMatrix`
    The HNF of matrix *A*.

Raises
======

DMDomainError
    If the domain of the matrix is not :ref:`ZZ`, or
    if *D* is given but is not in :ref:`ZZ`.

DMShapeError
    If the mod *D* algorithm is used but the matrix has more rows than
    columns.

References
==========

.. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*
   (See Algorithms 2.4.5 and 2.4.8.)

rx   r   )	r   ry   r   
convert_tor	   rankr   r   r   )r~   r   r   s      r   hermite_normal_formr     sZ    v 88>><==}jALL,<,A,A,Cqwwqz,Q,Q22#A&&r   )__doc__collectionsr   domainmatrixr   
exceptionsr   r   sympy.ntheory.modularr   sympy.polys.domainsr	   r
   r   r    r,   r   r7   r0   rv   r   r   r   r>   r   r   <module>r      sX    2 # & 3 3 &.:"D$8cL*J;ZU2p !% @'r   