
    Цi\3                         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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      _/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/sympy/polys/matrices/normalforms.pysmith_normal_formr      s-    $ QD


D((AGG
4CJ    c                     [        [        U 5      5       H2  nX   U   nX8-  X@U   U   -  -   X   U'   XX-  X`U   U   -  -   X   U'   M4     g N)rangelen)	r   ijabcdkes	            r   add_columnsr"   (   sW     3q6]DG#A$q'	/Q#A$q'	/Q r   c                   ^ ^^^^ T R                   mTR                  (       d  Sn[        U5      eST R                  ;   a  gT R                  =u  mmn[	        T R                  5       R                  R                  5       5      m U4S jmUUU4S jnUU4S jn[        T5       Vs/ s H  nT U   S   S:w  d  M  UPM     nnU(       a!  US   S:w  a  T US      T S   sT S'   T US   '   OW[        T5       Vs/ s H  nT S   U   S:w  d  M  UPM     nnU(       a'  US   S:w  a  T  H  nXS      US   sUS'   XS   '   M     [        U 4S j[        ST5       5       5      (       d$  [        U 4S	 j[        ST5       5       5      (       a\  U" T 5      m U" T 5      m [        U 4S j[        ST5       5       5      (       a  M6  [        U 4S	 j[        ST5       5       5      (       a  M\  SU;   a  Sn	O6[        T SS
  V
s/ s H  oSS
 PM	     sn
TS-
  TS-
  4T5      n[        U5      n	T S   S   (       a  T S   S   /nUR                  U	5        [        [        U5      S-
  5       Ho  nX   (       ac  TR                  XS-      X   5      S   S:w  aC  TR                  XS-      X   5      nTR                  X   U5      S   XS-      -  XS-   '   XU'   Mo    O   OU	T S   S   4-   n[!        U5      $ s  snf s  snf s  sn
f )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

z8The matrix entries must be over a principal ideal domainr    c                    > [        T	5       H2  nX   U   nX8-  X@U   U   -  -   X   U'   XX-  X`U   U   -  -   X   U'   M4     g r   )r   )
r   r   r   r   r   r   r   r    r!   colss
            r   add_rows#invariant_factors.<locals>.add_rowsH   sT     tAQAcAd1gIoADGcAd1gIoADG r   c           
        > U S   S   S:X  a  U $ U S   S   n[        ST5       H  nX   S   S:X  a  M  TR                  X   S   U5      u  p4US:X  a  T
" U SUSSU* S5        M@  TR                  XU   S   5      u  pVnTR                  X   S   U5      S   nTR                  X5      S   n	T
" U SX%XhU	* 5        UnM     U $ Nr   r   )r   divgcdex)r   pivotr   r   rr   r   gd_0d_jr'   r   rowss             r   clear_column'invariant_factors.<locals>.clear_columnP   s    Q47a<H!Qq$AtAw!|::ad1gu-DAAvAq!QA. ,,ud1g6ajja!,Q/jj*1-AqQcT2   r   c           
        > U S   S   S:X  a  U $ U S   S   n[        ST
5       H  nU S   U   S:X  a  M  TR                  U S   U   U5      u  p4US:X  a  [        U SUSSU* S5        ME  TR                  XS   U   5      u  pVnTR                  U S   U   U5      S   nTR                  X5      S   n	[        U SX%XhU	* 5        UnM     U $ r*   )r   r+   r"   r,   )r   r-   r   r   r.   r   r   r/   r0   r1   r&   r   s             r   	clear_row$invariant_factors.<locals>.clear_rowc   s    Q47a<H!Qq$AtAw!|::ad1gu-DAAvAq!QA2q1 ,,ud1g6ajj1a!,Q/jj*1-Aq!5   r   c              3   :   >#    U  H  nTS    U   S :g  v   M     g7fr   Nr$   .0r   r   s     r   	<genexpr>$invariant_factors.<locals>.<genexpr>        3]qtAw!|]   r   c              3   :   >#    U  H  nTU   S    S :g  v   M     g7fr9   r$   r:   s     r   r<   r=      r>   r?   N)r   is_PID
ValueErrorr   listto_denserepto_ddmr   anyr   r   extendr   r+   gcdtuple)r   msgr   r3   r6   r   indr   rowr   r.   lower_rightresultr/   r'   r&   r   r2   s   `             @@@@r   r   r   1   s    XXF==HoAGG| JD$QZZ\$$&'A&&( Dk
2kQqT!W\1kC
2
s1v{CF)QqT!aAi+6+Q1aAq+63q6Q;&)a&k3q6#AF  3U1T]3333U1T]333OaL 3U1T]3333U1T]333 	Ez"1QR5#95aabE5#9DFDF;KVT -tAwA$q'ds6{1}%AyVZZsVY?BaGJJvc{FI6$jjA6q9&1+Esq	 & 1a
"=E 3 7 $:s   %K,9K,6K1
K19K6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,   )r   r   xyr/   s        r   _gcdexrT      s?     hhqnGA!Av!%1*a%BQ7Nr   c                    U R                   R                  (       d  [        S5      eU R                  u  pU R	                  5       R
                  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   rQ   r   N)r   is_ZZr   r   rD   rE   rF   copyr   rT   r"   r   from_repto_dfm_or_ddm)Ar   nr    r   r   uvr   r.   sr   qs                r   _hermite_normal_formra      s   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       R                  R                  5       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.)

rV   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_R0  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.rQ   r   )r   rW   r   r
   of_typer   dictr   r   rD   rE   rF   rX   r   rT   r"   r   )r[   Dre   Wr   r\   r    rd   r   r   r]   r^   r   r.   r_   r   iir`   s                     r   _hermite_normal_form_modulo_Drl      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)ri   
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.)

rV   r   )	r   rW   r   
convert_tor	   rankr   rl   ra   )r[   ri   rm   s      r   hermite_normal_formrq   V  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   rT   ra   rl   rq   r$   r   r   <module>rx      sH    2 # & 3 3 &."hV*J;ZU2p !% @'r   