
    g\3                         d Z ddlmZ ddlmZ ddlmZmZ ddlm	Z	 ddl
mZmZ d Zd	 Zd
 Zd Zd Zd ZddddZdS )z,Functions returning normal forms of matrices    )defaultdict   )DomainMatrix)DMDomainErrorDMShapeError)symmetric_residue)QQZZc                 d    t          |           }t          j        || j        | j                  }|S )aJ  
    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-engine/env/lib/python3.11/site-packages/sympy/polys/matrices/normalforms.pysmith_normal_formr      s.    $ QD

D!(AG
4
4CJ    c                     t          t          |                     D ]P}| |         |         }||z  || |         |         z  z   | |         |<   ||z  || |         |         z  z   | |         |<   Qd S N)rangelen)	r   ijabcdkes	            r   add_columnsr"   (   sz     3q66]] " "aDGA#!A$q'	/!QA#!A$q'	/!Q" "r   c                 V     j         j        sd}t          |          d j        v rdS  j        x\  }t	                                           j                                                   fdfd}fd} fdt                    D             }|r0|d         dk    r$ |d                   d         c d<    |d         <   nQ fdt                    D             }|r4|d         dk    r( D ]%}||d                  |d         c|d<   ||d         <   &t           fd	t          d
          D                       s)t           fdt          d
          D                       rh |             |            t           fd	t          d
          D                       ?t           fdt          d
          D                       hd
|v rd}n:t          d  d
d         D             d
z
  d
z
  f          }t          |          } d         d         r݉ d         d         g}	|	                    |           t          t          |	          d
z
            D ]}
|	|
         r                    |	|
d
z            |	|
                   d
         dk    r_                    |	|
d
z            |	|
                   }                    |	|
         |          d         |	|
d
z            z  |	|
d
z   <   ||	|
<    n| d         d         fz   }	t!          |	          S )a3  
    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          	          D ]P}| |         |         }||z  || |         |         z  z   | |         |<   ||z  || |         |         z  z   | |         |<   Qd S r   )r   )
r   r   r   r   r   r   r   r    r!   colss
            r   add_rowsz#invariant_factors.<locals>.add_rowsH   su     t 	& 	&A!QAcAad1gIoAaDGcAad1gIoAaDGG	& 	&r   c           
         | d         d         dk    r| S | d         d         }t          d          D ]}| |         d         dk    r                    | |         d         |          \  }}|dk    r 
| d|dd| d           S                    || |         d                   \  }}}                    | |         d         |          d         }                    ||          d         }	 
| d|||||	            |}| S Nr   r   )r   divgcdex)r   pivotr   r   rr   r   gd_0d_jr'   r   rowss             r   clear_columnz'invariant_factors.<locals>.clear_columnP   s   Q47a<<H!Qq$ 	 	AtAw!||::ad1gu--DAqAvvAq!QA.... ,,uad1g661ajj1a!,,Q/jj**1-Aq!QcT222r   c           
          | d         d         dk    r| S | d         d         }t          d
          D ]}| d         |         dk    r                    | d         |         |          \  }}|dk    rt          | d|dd| d           W                    || d         |                   \  }}}                    | d         |         |          d         }                    ||          d         }	t          | d|||||	            |}| S r)   )r   r*   r"   r+   )r   r,   r   r   r-   r   r   r.   r/   r0   r&   r   s             r   	clear_rowz$invariant_factors.<locals>.clear_rowc   s   Q47a<<H!Qq$ 	 	AtAw!||::ad1gu--DAqAvvAq!QA2q1111 ,,uad1g661ajj1a!,,Q/jj**1-Aq!Q3555r   c                 8    g | ]}|         d          d k    |S r   r$   .0r   r   s     r   
<listcomp>z%invariant_factors.<locals>.<listcomp>w   s&    
2
2
2QqT!W\\1\\\r   c                 8    g | ]}d          |         d k    |S r6   r$   )r8   r   r   s     r   r9   z%invariant_factors.<locals>.<listcomp>{   s&    666Q1aAqr   c              3   <   K   | ]}d          |         d k    V  dS r   Nr$   r7   s     r   	<genexpr>z$invariant_factors.<locals>.<genexpr>   /      33qtAw!|333333r   r   c              3   <   K   | ]}|         d          d k    V  dS r<   r$   r7   s     r   r=   z$invariant_factors.<locals>.<genexpr>   r>   r   c                 "    g | ]}|d d         S )r   Nr$   )r8   r-   s     r   r9   z%invariant_factors.<locals>.<listcomp>   s     #9#9#9aAabbE#9#9#9r   N)r   is_PID
ValueErrorr   listto_denserepto_ddmr   anyr   r   extendr   r*   gcdtuple)r   msgr   r2   r4   indrowr   lower_rightresultr   r.   r'   r&   r   r1   s   `           @@@@r   r   r   1   s    XF= HooAG||r JD$QZZ\\$$&&''A& & & & &      &     ( 3
2
2
2eDkk
2
2
2C
 :s1v{{CF)QqT!aAii6666%++666 	:3q6Q;; : :&)#a&k3q6#ACF 3333U1T]]33333 3333U1T]]33333LOOIaLL 3333U1T]]33333 3333U1T]]33333
 	Ezz"#9#91QRR5#9#9#9DFDF;KVTT --tAw #A$q'ds6{{1}%% 	 	Aay VZZqsVAY??BaGGJJvac{F1I66$jjA66q9&1+Eqsq		1a
"==r   c                 t    t          j        | |          \  }}}| dk    r|| z  dk    rd}| dk     rdnd}|||fS )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      sO     hq!nnGAq!Avv!a%1**a%%BBQa7Nr   c                    | j         j        st          d          | j        \  }}|                                 j                                                                        } |}t          |dz
  dd          D ]}|dk    r n	|dz  }t          |dz
  dd          D ]x}| |         |         dk    rdt          | |         |         | |         |                   \  }}}| |         |         |z  | |         |         |z  }
}	t          | |||||
 |	           y| |         |         }|dk     rt          | ||dddd           | }|dk    r|dz  }t          |dz   |          D ])}| |         |         |z  }t          | ||d| dd           *t          j        |                                           dd|df         S )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 8> ><=== 7DAq	

!!&&((A 	
A1q5"b!! !2 !266 E	Q q1ub"%% 	2 	2AtAw!|| !1a!A$q'221atAw!|QqT!W\1Aq!QA2q111aDGq551aQA...A 66FAA
 1q5!__ 2 2aDGqLAq!QAq11112
  !2!233AAAqrrE::r   c                    | j         j        st          d          t          j        |          r|dk     rt          d          d }t          t                    }| j        \  }}||k     rt          d          | 	                                j
                                                                        } |}|}t          |dz
  dd          D ]a}|dz  }t          |dz
  dd          D ]u}	| |         |	         dk    rat          | |         |         | |         |	                   \  }
}}| |         |         |z  | |         |	         |z  }} || |||	|
|| |           v| |         |         }|dk    r|x| |         |<   }t          ||          \  }
}}t          |          D ]}|
| |         |         z  |z  ||         |<    ||         |         dk    r|||         |<   t          |dz   |          D ]5}	||         |	         ||         |         z  }t          ||	|d| dd           6||z  }ct!          |||ft                    	                                S )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                 $   t          t          |                     D ]r}| |         |         }	t          ||	z  || |         |         z  z   |z  |          | |         |<   t          ||	z  || |         |         z  z   |z  |          | |         |<   sd S r   )r   r   r   )
r   Rr   r   r   r   r   r   r    r!   s
             r   add_columns_mod_Rz8_hermite_normal_form_modulo_D.<locals>.add_columns_mod_R0  s     s1vv 	F 	FA!QA'QQqT!W)<(A1EEAaDG'QQqT!W)<(A1EEAaDGG	F 	F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_Drk      s   Z 8> ><===:a== PAEENOOOF F F 	DA7DAq1uuOPPP	

!!&&((A	A	A1q5"b!!  	Qq1ub"%% 	; 	;AtAw!|| 1a!A$q'221atAw!|QqT!W\1!!!Q1aQB:::aDG66OAaDGaA,,1a(( 	& 	&B2qzA~AbE!HHQ47a<<AaDGq1ua 	. 	.A!Q1Q47"A1aQB1----	aAq62&&//111r   NF)rh   
check_rankc                    | j         j        st          d          |M|r;|                     t                                                    | j        d         k    rt          | |          S t          |           S )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   Nr   )	r   rW   r   
convert_tor	   rankr   rk   ra   )r[   rh   rl   s      r   hermite_normal_formrp   V  so    v 8> ><===}j}ALL,<,<,A,A,C,Cqwqz,Q,Q,Q222#A&&&r   )__doc__collectionsr   domainmatrixr   
exceptionsr   r   sympy.ntheory.modularr   sympy.polys.domainsr	   r
   r   r"   r   rT   ra   rk   rp   r$   r   r   <module>rw      s   2 2 # # # # # # & & & & & & 3 3 3 3 3 3 3 3 3 3 3 3 3 3 & & & & & & & &  ." " "h h hV  *J; J; J;ZU2 U2 U2p !% @' @' @' @' @' @' @'r   