
    sgly                         d dl mZ d dlmZ d dlmZ d dlmZmZ ddl	m
Z
mZmZmZmZmZmZ edk7  rdgZ ed      Zd	gZ edg
       G d d	             Zd dlmZ d dlmZ y)    )GROUND_TYPES)import_module)doctest_depends_onZZQQ   )DMBadInputErrorDMDomainErrorDMNonSquareMatrixErrorDMNonInvertibleMatrixErrorDMRankErrorDMShapeErrorDMValueErrorflint*DFMground_typesc                      e Zd ZdZdZdZdZd Zed        Z	d Z
ed        Zed	        Zed
        Zed        Zd Zd Zd Zed        Zd Zd Zd Zd Zd Zd Zed        Zed        Zd Zd Zed        Zd Zed        Z d Z!ed        Z"d Z#d  Z$d! Z%d" Z&d# Z'd$ Z(d% Z)d& Z*d' Z+d( Z,d) Z-d* Z.d+ Z/d, Z0d- Z1d. Z2ed/        Z3ed0        Z4ed1        Z5ed2        Z6d3 Z7d4 Z8d5 Z9d6 Z:d7 Z;d8 Z<d9 Z=d: Z>d; Z?d< Z@d= ZA eBd>?      d@        ZC eBd>?      dA        ZD eBd>?      dB        ZEdC ZF eBd>?      dD        ZGdE ZHdLdGZIdH ZJdMdIZK eBd>?      dNdJ       ZL eBd>?      dNdK       ZMyF)Or   a&  
    Dense FLINT matrix. This class is a wrapper for matrices from python-flint.

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.matrices.dfm import DFM
    >>> dfm = DFM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
    >>> dfm
    [[1, 2], [3, 4]]
    >>> dfm.rep
    [1, 2]
    [3, 4]
    >>> type(dfm.rep)  # doctest: +SKIP
    <class 'flint._flint.fmpz_mat'>

    Usually, the DFM class is not instantiated directly, but is created as the
    internal representation of :class:`~.DomainMatrix`. When
    `SYMPY_GROUND_TYPES` is set to `flint` and `python-flint` is installed, the
    :class:`DFM` class is used automatically as the internal representation of
    :class:`~.DomainMatrix` in dense format if the domain is supported by
    python-flint.

    >>> from sympy.polys.matrices.domainmatrix import DM
    >>> dM = DM([[1, 2], [3, 4]], ZZ)
    >>> dM.rep
    [[1, 2], [3, 4]]

    A :class:`~.DomainMatrix` can be converted to :class:`DFM` by calling the
    :meth:`to_dfm` method:

    >>> dM.to_dfm()
    [[1, 2], [3, 4]]

    denseTFc                     | j                  |      }d|vr
	  ||      }n || }| j	                  |||      S # t        t        f$ r t        d|       w xY w)Construct from a nested list.r   z"Input should be a list of list of )_get_flint_func
ValueError	TypeErrorr
   _new)clsrowslistshapedomain	flint_matreps         L/var/www/html/venv/lib/python3.12/site-packages/sympy/polys/matrices/_dfm.py__new__zDFM.__new__m   ss    ''/	E>U) U#CxxUF++ 	* U%(J6(&STTUs	   8 Ac                     | j                  |||       t        j                  |       }||_        |x|_        \  |_        |_        ||_        |S )z)Internal constructor from a flint matrix.)_checkobjectr%   r#   r    rowscolsr!   )r   r#   r    r!   objs        r$   r   zDFM._new{   sJ     	

3v&nnS!)..	&CHch

    c                 P    | j                  || j                  | j                        S )z>Create a new DFM with the same shape and domain but a new rep.)r   r    r!   )selfr#   s     r$   _new_repzDFM._new_rep   s    yydjj$++66r,   c                 N   |j                         |j                         f}||k7  rt        d      |t        k(  r%t	        |t
        j                        st        d      |t        k(  r%t	        |t
        j                        st        d      |t        t        fvrt        d      y )Nz(Shape of rep does not match shape of DFMzRep is not a flint.fmpz_matzRep is not a flint.fmpq_mat#Only ZZ and QQ are supported by DFM)nrowsncolsr
   r   
isinstancer   fmpz_matRuntimeErrorr   fmpq_matNotImplementedError)r   r#   r    r!   repshapes        r$   r'   z
DFM._check   s    IIK-u!"LMMR<
3 ?<==r\*S%.."A<==B8#%&KLL $r,   c                     |t         t        fv S )z4Return True if the given domain is supported by DFM.r   r   r!   s     r$   _supports_domainzDFM._supports_domain   s     "b!!r,   c                 |    |t         k(  rt        j                  S |t        k(  rt        j                  S t        d      )z3Return the flint matrix class for the given domain.r1   )r   r   r5   r   r7   r8   r;   s     r$   r   zDFM._get_flint_func   s2     R<>>!r\>>!%&KLLr,   c                 8    | j                  | j                        S )z5Callable to create a flint matrix of the same domain.)r   r!   r.   s    r$   _funcz	DFM._func   s     ##DKK00r,   c                 4    t        | j                               S )zReturn ``str(self)``.)strto_ddmr?   s    r$   __str__zDFM.__str__   s    4;;=!!r,   c                 @    dt        | j                               dd  S )zReturn ``repr(self)``.r      N)reprrC   r?   s    r$   __repr__zDFM.__repr__   s"    T$++-(,-..r,   c                     t        |t              st        S | j                  |j                  k(  xr | j                  |j                  k(  S )zReturn ``self == other``.)r4   r   NotImplementedr!   r#   r.   others     r$   __eq__z
DFM.__eq__   s9    %%!! {{ell*Dtxx599/DDr,   c                      | |||      S )r    )r   r   r    r!   s       r$   	from_listzDFM.from_list   s     8UF++r,   c                 6    | j                   j                         S )zConvert to a nested list.)r#   tolistr?   s    r$   to_listzDFM.to_list   s    xx  r,   c                 V    | j                  | j                  | j                              S )zReturn a copy of self.)r/   r@   r#   r?   s    r$   copyzDFM.copy   s    }}TZZ122r,   c                 t    t        j                  | j                         | j                  | j                        S )zConvert to a DDM.)DDMrP   rS   r    r!   r?   s    r$   rC   z
DFM.to_ddm   #    }}T\\^TZZEEr,   c                 t    t        j                  | j                         | j                  | j                        S )zConvert to a SDM.)SDMrP   rS   r    r!   r?   s    r$   to_sdmz
DFM.to_sdm   rX   r,   c                     | S )zReturn self.rO   r?   s    r$   to_dfmz
DFM.to_dfm   s    r,   c                     | S )aL  
        Convert to a :class:`DFM`.

        This :class:`DFM` method exists to parallel the :class:`~.DDM` and
        :class:`~.SDM` methods. For :class:`DFM` it will always return self.

        See Also
        ========

        to_ddm
        to_sdm
        sympy.polys.matrices.domainmatrix.DomainMatrix.to_dfm_or_ddm
        rO   r?   s    r$   to_dfm_or_ddmzDFM.to_dfm_or_ddm   s	     r,   c                 l    | j                  |j                         |j                  |j                        S )zConvert from a DDM.)rP   rS   r    r!   )r   ddms     r$   from_ddmzDFM.from_ddm   s%     }}S[[]CIIszzBBr,   c                     | j                  |      }	  |g || } | |||      S # t        $ r t        d|       t        $ r t        d|       w xY w)z Inverse of :meth:`to_list_flat`.z'Incorrect number of elements for shape zInput should be a list of )r   r   r
   r   )r   elementsr    r!   funcr#   s         r$   from_list_flatzDFM.from_list_flat   s     ""6*	I((x(C
 3v&&	  	U!$KE7"STT 	I!$>vh"GHH	Is	   
' .Ac                 6    | j                   j                         S )zConvert to a flat list.)r#   entriesr?   s    r$   to_list_flatzDFM.to_list_flat   s    xx!!r,   c                 >    | j                         j                         S )z$Convert to a flat list of non-zeros.)rC   
to_flat_nzr?   s    r$   rk   zDFM.to_flat_nz   s    {{}''))r,   c                 L    t        j                  |||      j                         S )zInverse of :meth:`to_flat_nz`.)rW   from_flat_nzr]   )r   rd   datar!   s       r$   rm   zDFM.from_flat_nz   s"     $7>>@@r,   c                 >    | j                         j                         S )zConvert to a DOD.)rC   to_dodr?   s    r$   rp   z
DFM.to_dod      {{}##%%r,   c                 L    t        j                  |||      j                         S )zInverse of :meth:`to_dod`.)rW   from_dodr]   )r   dodr    r!   s       r$   rs   zDFM.from_dod        ||C/6688r,   c                 >    | j                         j                         S )zConvert to a DOK.)rC   to_dokr?   s    r$   rw   z
DFM.to_dok
  rq   r,   c                 L    t        j                  |||      j                         S )zInverse of :math:`to_dod`.)rW   from_dokr]   )r   dokr    r!   s       r$   ry   zDFM.from_dok  ru   r,   c              #      K   | j                   \  }}| j                  }t        |      D ]%  }t        |      D ]  }|||f   }|s|||f     ' yw)z0Iterater over the non-zero values of the matrix.Nr    r#   ranger.   mnr#   ijrepijs          r$   iter_valueszDFM.iter_values  s_     zz1hhq 	$A1X $AqD	ad)O$	$s   AAAc              #      K   | j                   \  }}| j                  }t        |      D ]$  }t        |      D ]  }|||f   }|s||f|f  & yw)zBIterate over indices and values of nonzero elements of the matrix.Nr|   r~   s          r$   
iter_itemszDFM.iter_items  s`     zz1hhq 	*A1X *AqD	q65/)*	*s   AAAc                    || j                   k(  r| j                         S |t        k(  rM| j                   t        k(  r:| j	                  t
        j                  | j                        | j                  |      S |t        k(  r@| j                   t        k(  r-| j                         j                  |      j                         S t        d      )zConvert to a new domain.r1   )r!   rU   r   r   r   r   r7   r#   r    rC   
convert_tor]   r8   )r.   r!   s     r$   r   zDFM.convert_to'  s    T[[ 99;r\dkkR/99U^^DHH5tzz6JJr\dkkR/;;=++F3::<< &&KLLr,   c           	          | j                   \  }}|dk  r||z  }|dk  r||z  }	 | j                  ||f   S # t        $ r t        d| d| d| j                          w xY w)zGet the ``(i, j)``-th entry.r   Invalid indices (, ) for Matrix of shape r    r#   r   
IndexError)r.   r   r   r   r   s        r$   getitemzDFM.getitem5  s~     zz1q5FAq5FA	]88AqD>! 	]02aS8Ntzzl[\\	]s	   6 (Ac           	          | j                   \  }}|dk  r||z  }|dk  r||z  }	 || j                  ||f<   y# t        $ r t        d| d| d| j                          w xY w)zSet the ``(i, j)``-th entry.r   r   r   r   Nr   )r.   r   r   valuer   r   s         r$   setitemzDFM.setitemC  s}     zz1q5FAq5FA	]"DHHQTN 	]02aS8Ntzzl[\\	]s	   7 (Ac           
          | j                   }|D cg c]  }|D cg c]	  }|||f    c} }}}t        |      t        |      f}| j                  ||| j                        S c c}w c c}}w )z%Extract a submatrix with no checking.)r#   lenrP   r!   )r.   	i_indices	j_indicesMr   r   lolr    s           r$   _extractzDFM._extractQ  sd     HH5>?+A!Q$+??YY0~~c5$++66 ,?s   	A)A$A)$A)c                    | j                   \  }}g }g }|D ]H  }|dk  r||z   }n|}d|cxk  r|k  sn t        d| d| j                          |j                  |       J |D ]H  }	|	dk  r|	|z   }
n|	}
d|
cxk  r|k  sn t        d|	 d| j                          |j                  |
       J | j                  ||      S )zExtract a submatrix.r   zInvalid row index z for Matrix of shape zInvalid column index )r    r   appendr   )r.   r   colslistr   r   new_rowsnew_colsr   i_posr   j_poss              r$   extractzDFM.extractY  s    
 zz1 	#A1uA>> #5aS8Mdjj\!Z[[OOE"	#  	#A1uA>> #8;PQUQ[Q[P\!]^^OOE"	# }}Xx00r,   c                 |    | j                   \  }}t        |      |   }t        |      |   }| j                  ||      S )zSlice a DFM.)r    r}   r   )r.   rowslicecolslicer   r   r   r   s          r$   extract_slicezDFM.extract_slicew  s>     zz1!HX&	!HX&	}}Y	22r,   c                 :    | j                  | j                         S zNegate a DFM matrix.r/   r#   r?   s    r$   negzDFM.neg  s    }}dhhY''r,   c                 R    | j                  | j                  |j                  z         S )zAdd two DFM matrices.r   rK   s     r$   addzDFM.add      }}TXX		122r,   c                 R    | j                  | j                  |j                  z
        S )zSubtract two DFM matrices.r   rK   s     r$   subzDFM.sub  r   r,   c                 >    | j                  | j                  |z        S )z1Multiply a DFM matrix from the right by a scalar.r   rK   s     r$   mulzDFM.mul  s    }}TXX-..r,   c                 >    | j                  || j                  z        S )z0Multiply a DFM matrix from the left by a scalar.r   rK   s     r$   rmulzDFM.rmul  s    }}UTXX-..r,   c                 x    | j                         j                  |j                               j                         S )z/Elementwise multiplication of two DFM matrices.)rC   mul_elementwiser]   rK   s     r$   r   zDFM.mul_elementwise  s*     {{},,U\\^<CCEEr,   c                     | j                   |j                  f}| j                  | j                  |j                  z  || j                        S )zMultiply two DFM matrices.)r)   r*   r   r#   r!   )r.   rL   r    s      r$   matmulz
DFM.matmul  s8    EJJ'yyEII-udkkBBr,   c                 "    | j                         S r   )r   r?   s    r$   __neg__zDFM.__neg__  s    xxzr,   c                 P    | j                  |      }| j                   || ||      S )zReturn a zero DFM matrix.)r   r   )r   r    r!   re   s       r$   zerosz	DFM.zeros  s+     ""6*xxeeV44r,   c                 J    t        j                  ||      j                         S )zReturn a one DFM matrix.)rW   onesr]   )r   r    r!   s      r$   r   zDFM.ones  s     xxv&--//r,   c                 J    t        j                  ||      j                         S )z%Return the identity matrix of size n.)rW   eyer]   )r   r   r!   s      r$   r   zDFM.eye  s     wwq&!((**r,   c                 J    t        j                  ||      j                         S )zReturn a diagonal matrix.)rW   diagr]   )r   rd   r!   s      r$   r   zDFM.diag  s     xx&)0022r,   c                 ^    | j                         j                  ||      j                         S )z/Apply a function to each entry of a DFM matrix.)rC   	applyfuncr]   )r.   re   r!   s      r$   r   zDFM.applyfunc  s$    {{}&&tV4;;==r,   c                     | j                  | j                  j                         | j                  | j                  f| j
                        S )zTranspose a DFM matrix.)r   r#   	transposer*   r)   r!   r?   s    r$   r   zDFM.transpose  s3    yy++-		499/Et{{SSr,   c                      | j                         j                  |D cg c]  }|j                          c} j                         S c c}w )zHorizontally stack matrices.)rC   hstackr]   r.   othersos      r$   r   z
DFM.hstack  8    #t{{}##&%AQahhj%ABIIKK%A   Ac                      | j                         j                  |D cg c]  }|j                          c} j                         S c c}w )zVertically stack matrices.)rC   vstackr]   r   s      r$   r   z
DFM.vstack  r   r   c                     | j                   }| j                  \  }}t        t        ||            D cg c]	  }|||f    c}S c c}w )z$Return the diagonal of a DFM matrix.)r#   r    r}   min)r.   r   r   r   r   s        r$   diagonalzDFM.diagonal  s?    HHzz1!&s1ay!12A!Q$222s   Ac                     | j                   }t        | j                        D ]  }t        |      D ]  }|||f   s  y  y)z2Return ``True`` if the matrix is upper triangular.FT)r#   r}   r)   r.   r   r   r   s       r$   is_upperzDFM.is_upper  sI    HHtyy! 	!A1X !QT7 !	! r,   c                     | j                   }t        | j                        D ]*  }t        |dz   | j                        D ]  }|||f   s  y , y)z2Return ``True`` if the matrix is lower triangular.r	   FTr#   r}   r)   r*   r   s       r$   is_lowerzDFM.is_lower  sT    HHtyy! 	!A1q5$)), !QT7 !	! r,   c                 F    | j                         xr | j                         S )z*Return ``True`` if the matrix is diagonal.)r   r   r?   s    r$   is_diagonalzDFM.is_diagonal  s    }}24==?2r,   c                     | j                   }t        | j                        D ]&  }t        | j                        D ]  }|||f   s  y ( y)z1Return ``True`` if the matrix is the zero matrix.FTr   r   s       r$   is_zero_matrixzDFM.is_zero_matrix  sN    HHtyy! 	!A499% !QT7 !	! r,   c                 >    | j                         j                         S )z5Return the number of non-zero elements in the matrix.)rC   nnzr?   s    r$   r   zDFM.nnz      {{}  ""r,   c                 >    | j                         j                         S )z7Return the strongly connected components of the matrix.)rC   sccr?   s    r$   r   zDFM.scc  r   r,   r   r   c                 6    | j                   j                         S )a  
        Compute the determinant of the matrix using FLINT.

        Examples
        ========

        >>> from sympy import Matrix
        >>> M = Matrix([[1, 2], [3, 4]])
        >>> dfm = M.to_DM().to_dfm()
        >>> dfm
        [[1, 2], [3, 4]]
        >>> dfm.det()
        -2

        Notes
        =====

        Calls the ``.det()`` method of the underlying FLINT matrix.

        For :ref:`ZZ` or :ref:`QQ` this calls ``fmpz_mat_det`` or
        ``fmpq_mat_det`` respectively.

        At the time of writing the implementation of ``fmpz_mat_det`` uses one
        of several algorithms depending on the size of the matrix and bit size
        of the entries. The algorithms used are:

        - Cofactor for very small (up to 4x4) matrices.
        - Bareiss for small (up to 25x25) matrices.
        - Modular algorithms for larger matrices (up to 60x60) or for larger
          matrices with large bit sizes.
        - Modular "accelerated" for larger matrices (60x60 upwards) if the bit
          size is smaller than the dimensions of the matrix.

        The implementation of ``fmpq_mat_det`` clears denominators from each
        row (not the whole matrix) and then calls ``fmpz_mat_det`` and divides
        by the product of the denominators.

        See Also
        ========

        sympy.polys.matrices.domainmatrix.DomainMatrix.det
            Higher level interface to compute the determinant of a matrix.
        )r#   detr?   s    r$   r   zDFM.det  s    b xx||~r,   c                 ^    | j                   j                         j                         ddd   S )a#  
        Compute the characteristic polynomial of the matrix using FLINT.

        Examples
        ========

        >>> from sympy import Matrix
        >>> M = Matrix([[1, 2], [3, 4]])
        >>> dfm = M.to_DM().to_dfm()  # need ground types = 'flint'
        >>> dfm
        [[1, 2], [3, 4]]
        >>> dfm.charpoly()
        [1, -5, -2]

        Notes
        =====

        Calls the ``.charpoly()`` method of the underlying FLINT matrix.

        For :ref:`ZZ` or :ref:`QQ` this calls ``fmpz_mat_charpoly`` or
        ``fmpq_mat_charpoly`` respectively.

        At the time of writing the implementation of ``fmpq_mat_charpoly``
        clears a denominator from the whole matrix and then calls
        ``fmpz_mat_charpoly``. The coefficients of the characteristic
        polynomial are then multiplied by powers of the denominator.

        The ``fmpz_mat_charpoly`` method uses a modular algorithm with CRT
        reconstruction. The modular algorithm uses ``nmod_mat_charpoly`` which
        uses Berkowitz for small matrices and non-prime moduli or otherwise
        the Danilevsky method.

        See Also
        ========

        sympy.polys.matrices.domainmatrix.DomainMatrix.charpoly
            Higher level interface to compute the characteristic polynomial of
            a matrix.
        N)r#   charpolycoeffsr?   s    r$   r   zDFM.charpoly0  s*    T xx  "))+DbD11r,   c                 8   | j                   }| j                  \  }}||k7  rt        d      |t        k(  rt	        d|z        |t
        k(  r*	 | j                  | j                  j                               S t        d|z        # t        $ r t        d      w xY w)a  
        Compute the inverse of a matrix using FLINT.

        Examples
        ========

        >>> from sympy import Matrix, QQ
        >>> M = Matrix([[1, 2], [3, 4]])
        >>> dfm = M.to_DM().to_dfm().convert_to(QQ)
        >>> dfm
        [[1, 2], [3, 4]]
        >>> dfm.inv()
        [[-2, 1], [3/2, -1/2]]
        >>> dfm.matmul(dfm.inv())
        [[1, 0], [0, 1]]

        Notes
        =====

        Calls the ``.inv()`` method of the underlying FLINT matrix.

        For now this will raise an error if the domain is :ref:`ZZ` but will
        use the FLINT method for :ref:`QQ`.

        The FLINT methods for :ref:`ZZ` and :ref:`QQ` are ``fmpz_mat_inv`` and
        ``fmpq_mat_inv`` respectively. The ``fmpz_mat_inv`` method computes an
        inverse with denominator. This is implemented by calling
        ``fmpz_mat_solve`` (see notes in :meth:`lu_solve` about the algorithm).

        The ``fmpq_mat_inv`` method clears denominators from each row and then
        multiplies those into the rhs identity matrix before calling
        ``fmpz_mat_solve``.

        See Also
        ========

        sympy.polys.matrices.domainmatrix.DomainMatrix.inv
            Higher level method for computing the inverse of a matrix.
        z!cannot invert a non-square matrixzfield expected, got %szmatrix is not invertiblez#DFM.inv() is not implemented for %s)r!   r    r   r   r   r   r/   r#   invZeroDivisionErrorr   r8   )r.   Kr   r   s       r$   r   zDFM.inv\  s    n KKzz16()LMM7 81 <=="WM}}TXX\\^44 &&Ka&OPP % M01KLLMs   (B Bc                     | j                         j                         \  }}}|j                         |j                         |fS )z*Return the LU decomposition of the matrix.)rC   lur]   )r.   LUswapss       r$   r   zDFM.lu  s5    kkm&&(1exxz188:u,,r,   c           
         | j                   |j                   k(  s%t        d| j                   d|j                         | j                   j                  st        d| j                   z        | j                  \  }}|j                  \  }}||k7  rt	        d|d|d|d|      ||f}||k7  r;| j                         j                  |j                               j                         S 	 | j                  j                  |j                        }| j                  ||| j                         S # t        $ r t        d      w xY w)a  
        Solve a matrix equation using FLINT.

        Examples
        ========

        >>> from sympy import Matrix, QQ
        >>> M = Matrix([[1, 2], [3, 4]])
        >>> dfm = M.to_DM().to_dfm().convert_to(QQ)
        >>> dfm
        [[1, 2], [3, 4]]
        >>> rhs = Matrix([1, 2]).to_DM().to_dfm().convert_to(QQ)
        >>> dfm.lu_solve(rhs)
        [[0], [1/2]]

        Notes
        =====

        Calls the ``.solve()`` method of the underlying FLINT matrix.

        For now this will raise an error if the domain is :ref:`ZZ` but will
        use the FLINT method for :ref:`QQ`.

        The FLINT methods for :ref:`ZZ` and :ref:`QQ` are ``fmpz_mat_solve``
        and ``fmpq_mat_solve`` respectively. The ``fmpq_mat_solve`` method
        uses one of two algorithms:

        - For small matrices (<25 rows) it clears denominators between the
          matrix and rhs and uses ``fmpz_mat_solve``.
        - For larger matrices it uses ``fmpq_mat_solve_dixon`` which is a
          modular approach with CRT reconstruction over :ref:`QQ`.

        The ``fmpz_mat_solve`` method uses one of four algorithms:

        - For very small (<= 3x3) matrices it uses a Cramer's rule.
        - For small (<= 15x15) matrices it uses a fraction-free LU solve.
        - Otherwise it uses either Dixon or another multimodular approach.

        See Also
        ========

        sympy.polys.matrices.domainmatrix.DomainMatrix.lu_solve
            Higher level interface to solve a matrix equation.
        zDomains must match: z != zField expected, got %szMatrix size mismatch: z * z vs z Matrix det == 0; not invertible.)r!   r   is_Fieldr    r   rC   lu_solver]   r#   solver   r   r   )r.   rhsr   r   r   k	sol_shapesols           r$   r   zDFM.lu_solve  s   \ {{cjj($++szz Z[[
 {{## 84;; FGGzz1yy16QPQSTVWXYYF	 6;;=))#**,7>>@@	Q((..)C yyi55 ! 	Q,-OPP	Qs   ,%D. .Ec                 h    | j                         j                         \  }}|j                         |fS )/Return a basis for the nullspace of the matrix.)rC   	nullspacer]   )r.   ra   	nonpivotss      r$   r   zDFM.nullspace   s-    & 002Yzz|Y&&r,   Nc                 l    | j                         j                  |      \  }}|j                         |fS )r   )pivots)r[   nullspace_from_rrefr]   )r.   r   sdmr   s       r$   r   zDFM.nullspace_from_rref  s2     ::&:IYzz|Y&&r,   c                 Z    | j                         j                         j                         S )z+Return a particular solution to the system.)rC   
particularr]   r?   s    r$   r   zDFM.particular  s     {{}'')0022r,   c                    d } ||      } ||      }d|cxk  rdk  st        d       t        d      | j                  \  }}| j                  j                         |k7  rt	        d      | j                  j                  |||||      S )zACall the fmpz_mat.lll() method but check rank to avoid segfaults.c                     t        j                  |       r+t        | j                        t        | j                        z  S t        |       S N)r   of_typefloat	numeratordenominator)xs    r$   to_floatzDFM._lll.<locals>.to_float*  s3    zz!}Q[[)E!--,@@@Qxr,   g      ?r	   z delta must be between 0.25 and 1z-Matrix must have full row rank for Flint LLL.)	transformdeltaetar#   gram)r   r    r#   rankr   lll)	r.   r
  r  r  r#   r  r	  r   r   s	            r$   _lllzDFM._lll   s    	  smeaABB  ABB zz188==?aMNN xx||iu#3UY|ZZr,   c                     | j                   t        k7  rt        d| j                   z        | j                  | j                  kD  rt        d      | j                  |      }| j                  |      S )a  Compute LLL-reduced basis using FLINT.

        See :meth:`lll_transform` for more information.

        Examples
        ========

        >>> from sympy import Matrix
        >>> M = Matrix([[1, 2, 3], [4, 5, 6]])
        >>> M.to_DM().to_dfm().lll()
        [[2, 1, 0], [-1, 1, 3]]

        See Also
        ========

        sympy.polys.matrices.domainmatrix.DomainMatrix.lll
            Higher level interface to compute LLL-reduced basis.
        lll_transform
            Compute LLL-reduced basis and transform matrix.
        ZZ expected, got %s,Matrix must not have more rows than columns.)r  )r!   r   r   r)   r*   r   r  r/   )r.   r  r#   s      r$   r  zDFM.lll>  s`    , ;;" 5 CDDYY"MNNiiei$}}S!!r,   c                 \   | j                   t        k7  rt        d| j                   z        | j                  | j                  kD  rt        d      | j                  d|      \  }}| j                  |      }| j                  || j                  | j                  f| j                         }||fS )ad  Compute LLL-reduced basis and transform using FLINT.

        Examples
        ========

        >>> from sympy import Matrix
        >>> M = Matrix([[1, 2, 3], [4, 5, 6]]).to_DM().to_dfm()
        >>> M_lll, T = M.lll_transform()
        >>> M_lll
        [[2, 1, 0], [-1, 1, 3]]
        >>> T
        [[-2, 1], [3, -1]]
        >>> T.matmul(M) == M_lll
        True

        See Also
        ========

        sympy.polys.matrices.domainmatrix.DomainMatrix.lll
            Higher level interface to compute LLL-reduced basis.
        lll
            Compute LLL-reduced basis without transform matrix.
        r  r  T)r
  r  )	r!   r   r   r)   r*   r   r  r/   r   )r.   r  r#   TbasisT_dfms         r$   lll_transformzDFM.lll_transform\  s    2 ;;" 5 CDDYY"MNNT7Qc"		!dii3T[[Ae|r,   r  )FgGz?gRQ?zbasisapprox)g      ?)N__name__
__module____qualname____doc__fmtis_DFMis_DDMr%   classmethodr   r/   r'   r<   r   propertyr@   rD   rH   rM   rP   rS   rU   rC   r[   r]   r_   rb   rf   ri   rk   rm   rp   rs   rw   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  rO   r,   r$   r   r   E   s    D CFF,  7 	M 	M " " M M 1 1"/E , ,!3FF  C C 	' 	'"* A A& 9 9& 9 9$*M]]71<3(33//F
C 5 5 0 0
 + +
 3 3>TLL33## W-0 .0d W-)2 .)2V W-FQ .FQP-  W-H6 .H6T','3[< W-" .": W-  . r,   )rW   )rZ   N)sympy.external.gmpyr   sympy.external.importtoolsr   sympy.utilities.decoratorr   sympy.polys.domainsr   r   
exceptionsr
   r   r   r   r   r   r   __doctest_skip__r   __all__r   sympy.polys.matrices.ddmrW   rZ   rO   r,   r$   <module>r,     sv   T - 4 8 &   7u 	g ' '+w w ,wv ) (r,   