a
    RG5d                     @   s   d Z ddlmZ ddlmZmZ ddlm	Z	 ddl
mZ ddlmZ dd	lmZmZmZmZmZmZ dd
lmZ ddlmZ ddlmZ ddlmZmZ dd ZG dd dZdS )a  

Module for the DomainMatrix class.

A DomainMatrix represents a matrix with elements that are in a particular
Domain. Each DomainMatrix internally wraps a DDM which is used for the
lower-level operations. The idea is that the DomainMatrix class provides the
convenience routines for converting between Expr and the poly domains as well
as unifying matrices with different domains.

    )reduce)UnionTuple_sympify   )Domainconstruct_domain   )DMNonSquareMatrixErrorDMShapeErrorDMDomainErrorDMFormatErrorDMBadInputErrorDMNotAField)DDM)SDM)DomainScalar)ZZEXRAWc                 C   s   t | |S )a  Convenient alias for DomainMatrix.from_list

    Examples
    =======

    >>> from sympy import ZZ
    >>> from sympy.polys.matrices import DM
    >>> DM([[1, 2], [3, 4]], ZZ)
    DomainMatrix([[1, 2], [3, 4]], (2, 2), ZZ)

    See also
    =======

    DomainMatrix.from_list
    )DomainMatrix	from_list)rowsdomain r   ]/var/www/html/django/DPS/env/lib/python3.9/site-packages/sympy/polys/matrices/domainmatrix.pyDM"   s    r   c                       s  e Zd ZU dZeeef ed< ee	e	f ed< e
ed< ddddZd	d
 Zdd Zdd Zdd Zdd Ze fddZedd Zedd Zedd ZedddZedd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zed,d- Zeddd.d/Zddd0d1Z d2d3 Z!d4d5 Z"d6d7 Z#d8d9 Z$d:d; Z%d<d= Z&d>d? Z'e(d@dA Z)e(dBdC Z*e(dDdE Z+e(dFdG Z,dHdI Z-dJdK Z.dLdM Z/ddNdOZ0dPdQ Z1dRdS Z2dTdU Z3dVdW Z4dXdY Z5dZd[ Z6d\d] Z7d^d_ Z8d`da Z9dbdc Z:ddde Z;dfdg Z<dhdi Z=djdk Z>dldm Z?dndo Z@dpdq ZAdrds ZBdtdu ZCdvdw ZDdxdy ZEdzd{ ZFd|d} ZGd~d ZHdd ZIdd ZJdd ZKdd ZLdd ZMdd ZNedd ZOedddZPeddddZQedd ZRdd ZSdd ZT  ZUS )r   a  
    Associate Matrix with :py:class:`~.Domain`

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

    DomainMatrix uses :py:class:`~.Domain` for its internal representation
    which makes it more faster for many common operations
    than current SymPy Matrix class, but this advantage makes it not
    entirely compatible with Matrix.
    DomainMatrix could be found analogous to numpy arrays with "dtype".
    In the DomainMatrix, each matrix has a domain such as :ref:`ZZ`
    or  :ref:`QQ(a)`.


    Examples
    ========

    Creating a DomainMatrix from the existing Matrix class:

    >>> from sympy import Matrix
    >>> from sympy.polys.matrices import DomainMatrix
    >>> Matrix1 = Matrix([
    ...    [1, 2],
    ...    [3, 4]])
    >>> A = DomainMatrix.from_Matrix(Matrix1)
    >>> A
    DomainMatrix({0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}, (2, 2), ZZ)

    Driectly forming a DomainMatrix:

    >>> from sympy import ZZ
    >>> from sympy.polys.matrices import DomainMatrix
    >>> A = DomainMatrix([
    ...    [ZZ(1), ZZ(2)],
    ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
    >>> A
    DomainMatrix([[1, 2], [3, 4]], (2, 2), ZZ)

    See Also
    ========

    DDM
    SDM
    Domain
    Poly

    repshaper   Nfmtc                C   s   t |ttfrtdn<t |tr0t|||}n$t |trHt|||}nd}t||dur|dkrn| }n|dkr| }ntd| 	|S )a  
        Creates a :py:class:`~.DomainMatrix`.

        Parameters
        ==========

        rows : Represents elements of DomainMatrix as list of lists
        shape : Represents dimension of DomainMatrix
        domain : Represents :py:class:`~.Domain` of DomainMatrix

        Raises
        ======

        TypeError
            If any of rows, shape and domain are not provided

        z'Use from_rep to initialise from SDM/DDMz.Input should be list-of-lists or dict-of-dictsNsparsedense!fmt should be 'sparse' or 'dense')

isinstancer   r   	TypeErrorlistdictZto_sdmto_ddm
ValueErrorfrom_rep)clsr   r   r   r!   r   msgr   r   r   __new__j   s    




zDomainMatrix.__new__c                 C   s@   | j }t|trt|}nt|tr.t|}nt|| j| jfS N)	r   r%   r   r'   r   r(   RuntimeErrorr   r   )selfr   argr   r   r   __getnewargs__   s    



zDomainMatrix.__getnewargs__c                 C   s   |\}}| j \}}t|ts<t|ts<t| j||| jS t|ts|| |  kr\|k sfn td|| }t||d }t|ts| |  kr|k sn td|| }t||d }| | j	||S )NzRow index out of ranger   zColumn index out of range)
r   r%   slicer   r   getitemr   
IndexErrorr+   Zextract_slice)r1   keyijmnr   r   r   __getitem__   s    


zDomainMatrix.__getitem__c                 C   s   | j | j||S r/   )r   to_sympyr   r5   )r1   r8   r9   r   r   r   getitem_sympy   s    zDomainMatrix.getitem_sympyc                 C   s   |  | j||S r/   )r+   r   extract)r1   ZrowslistZcolslistr   r   r   r?      s    zDomainMatrix.extractc                 C   sF   |\}}| j |stt|tr>t|tr>| j||| ntd S r/   )r   of_typer&   r%   intr   setitemNotImplementedError)r1   r7   valuer8   r9   r   r   r   __setitem__   s    zDomainMatrix.__setitem__c                    s<   t |ttfstdt | }||_|j|_|j|_|S )a  Create a new DomainMatrix efficiently from DDM/SDM.

        Examples
        ========

        Create a :py:class:`~.DomainMatrix` with an dense internal
        representation as :py:class:`~.DDM`:

        >>> from sympy.polys.domains import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy.polys.matrices.ddm import DDM
        >>> drep = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
        >>> dM = DomainMatrix.from_rep(drep)
        >>> dM
        DomainMatrix([[1, 2], [3, 4]], (2, 2), ZZ)

        Create a :py:class:`~.DomainMatrix` with a sparse internal
        representation as :py:class:`~.SDM`:

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy.polys.matrices.sdm import SDM
        >>> from sympy import ZZ
        >>> drep = SDM({0:{1:ZZ(1)},1:{0:ZZ(2)}}, (2, 2), ZZ)
        >>> dM = DomainMatrix.from_rep(drep)
        >>> dM
        DomainMatrix({0: {1: 1}, 1: {0: 2}}, (2, 2), ZZ)

        Parameters
        ==========

        rep: SDM or DDM
            The internal sparse or dense representation of the matrix.

        Returns
        =======

        DomainMatrix
            A :py:class:`~.DomainMatrix` wrapping *rep*.

        Notes
        =====

        This takes ownership of rep as its internal representation. If rep is
        being mutated elsewhere then a copy should be provided to
        ``from_rep``. Only minimal verification or checking is done on *rep*
        as this is supposed to be an efficient internal routine.

        z rep should be of type DDM or SDM)	r%   r   r   r&   superr.   r   r   r   )r,   r   r1   	__class__r   r   r+      s    2zDomainMatrix.from_repc                    sJ   t |}|sdn
t |d }fdd  fdd|D }t|||fS )aS  
        Convert a list of lists into a DomainMatrix

        Parameters
        ==========

        rows: list of lists
            Each element of the inner lists should be either the single arg,
            or tuple of args, that would be passed to the domain constructor
            in order to form an element of the domain. See examples.

        Returns
        =======

        DomainMatrix containing elements defined in rows

        Examples
        ========

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy import FF, QQ, ZZ
        >>> A = DomainMatrix.from_list([[1, 0, 1], [0, 0, 1]], ZZ)
        >>> A
        DomainMatrix([[1, 0, 1], [0, 0, 1]], (2, 3), ZZ)
        >>> B = DomainMatrix.from_list([[1, 0, 1], [0, 0, 1]], FF(7))
        >>> B
        DomainMatrix([[1 mod 7, 0 mod 7, 1 mod 7], [0 mod 7, 0 mod 7, 1 mod 7]], (2, 3), GF(7))
        >>> C = DomainMatrix.from_list([[(1, 2), (3, 1)], [(1, 4), (5, 1)]], QQ)
        >>> C
        DomainMatrix([[1/2, 3], [1/4, 5]], (2, 2), QQ)

        See Also
        ========

        from_list_sympy

        r   c                    s   t | tr |  S  | S r/   )r%   tuple)er   r   r   <lambda>       z(DomainMatrix.from_list.<locals>.<lambda>c                    s   g | ]} fd d|D qS )c                    s   g | ]} |qS r   r   ).0rJ   convr   r   
<listcomp>!  rM   z5DomainMatrix.from_list.<locals>.<listcomp>.<listcomp>r   rN   rowrO   r   r   rQ   !  rM   z*DomainMatrix.from_list.<locals>.<listcomp>)lenr   )r,   r   r   nrowsncolsdomain_rowsr   )rP   r   r   r      s
    'zDomainMatrix.from_listc                    sv   t ||ksJ tfdd|D s*J dd |D }| j|fi |\}  fddt|D }t||f|S )a  
        Convert a list of lists of Expr into a DomainMatrix using construct_domain

        Parameters
        ==========

        nrows: number of rows
        ncols: number of columns
        rows: list of lists

        Returns
        =======

        DomainMatrix containing elements of rows

        Examples
        ========

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy.abc import x, y, z
        >>> A = DomainMatrix.from_list_sympy(1, 3, [[x, y, z]])
        >>> A
        DomainMatrix([[x, y, z]], (1, 3), ZZ[x,y,z])

        See Also
        ========

        sympy.polys.constructor.construct_domain, from_dict_sympy

        c                 3   s   | ]}t | kV  qd S r/   )rT   rR   rV   r   r   	<genexpr>F  rM   z/DomainMatrix.from_list_sympy.<locals>.<genexpr>c                 S   s   g | ]}|D ]}t |qqS r   r   rN   rS   itemr   r   r   rQ   H  rM   z0DomainMatrix.from_list_sympy.<locals>.<listcomp>c                    s&   g | ]  fd dt D qS )c                    s   g | ]}  |  qS r   r   )rN   c)items_domainrV   rr   r   rQ   L  rM   z;DomainMatrix.from_list_sympy.<locals>.<listcomp>.<listcomp>)range)rN   r]   rV   )r^   r   rQ   L  rM   )rT   all
get_domainr_   r   )r,   rU   rV   r   kwargsitems_sympyr   rW   r   r`   r   from_list_sympy%  s     zDomainMatrix.from_list_sympyc                    s   t fdd|D stdt  fdd| D s@tddd | D }| j|fi |\}}d}i }	| D ]2\}
}i |	|
< |D ]}|| |	|
 |< |d	7 }qqxt|	 f|S )
a  

        Parameters
        ==========

        nrows: number of rows
        ncols: number of cols
        elemsdict: dict of dicts containing non-zero elements of the DomainMatrix

        Returns
        =======

        DomainMatrix containing elements of elemsdict

        Examples
        ========

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy.abc import x,y,z
        >>> elemsdict = {0: {0:x}, 1:{1: y}, 2: {2: z}}
        >>> A = DomainMatrix.from_dict_sympy(3, 3, elemsdict)
        >>> A
        DomainMatrix({0: {0: x}, 1: {1: y}, 2: {2: z}}, (3, 3), ZZ[x,y,z])

        See Also
        ========

        from_list_sympy

        c                 3   s&   | ]}d |  ko k n  V  qdS r   Nr   )rN   r^   )rU   r   r   rY   p  rM   z/DomainMatrix.from_dict_sympy.<locals>.<genexpr>zRow out of rangec                 3   s0   | ](}|D ]}d |  ko  k n  V  q
qdS rf   r   )rN   rS   r\   rX   r   r   rY   r  rM   zColumn out of rangec                 S   s"   g | ]}|  D ]}t|qqS r   )valuesr   rZ   r   r   r   rQ   u  rM   z0DomainMatrix.from_dict_sympy.<locals>.<listcomp>r   r   )ra   r   rg   rb   itemsr   )r,   rU   rV   Z	elemsdictrc   rd   r   r]   idxZ
items_dictr8   rS   r9   r   )rV   rU   r   from_dict_sympyP  s     zDomainMatrix.from_dict_sympyr"   c                 K   sH   |dkr(| j g |j| R i |S | jg |j| R i |S )a  
        Convert Matrix to DomainMatrix

        Parameters
        ==========

        M: Matrix

        Returns
        =======

        Returns DomainMatrix with identical elements as M

        Examples
        ========

        >>> from sympy import Matrix
        >>> from sympy.polys.matrices import DomainMatrix
        >>> M = Matrix([
        ...    [1.0, 3.4],
        ...    [2.4, 1]])
        >>> A = DomainMatrix.from_Matrix(M)
        >>> A
        DomainMatrix({0: {0: 1.0, 1: 3.4}, 1: {0: 2.4, 1: 1.0}}, (2, 2), RR)

        We can keep internal representation as ddm using fmt='dense'
        >>> from sympy import Matrix, QQ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix.from_Matrix(Matrix([[QQ(1, 2), QQ(3, 4)], [QQ(0, 1), QQ(0, 1)]]), fmt='dense')
        >>> A.rep
        [[1/2, 3/4], [0, 0]]

        See Also
        ========

        Matrix

        r#   )re   r   tolistrj   Ztodod)r,   Mr!   rc   r   r   r   from_Matrix  s    ( zDomainMatrix.from_Matrixc                 K   s   t |fi |\}}||fS r/   r	   )r,   rd   rc   KZitems_Kr   r   r   rb     s    zDomainMatrix.get_domainc                 C   s   |  | j S r/   )r+   r   copyr1   r   r   r   ro     s    zDomainMatrix.copyc                 C   s"   |du r|   S | | j|S )a  
        Change the domain of DomainMatrix to desired domain or field

        Parameters
        ==========

        K : Represents the desired domain or field.
            Alternatively, ``None`` may be passed, in which case this method
            just returns a copy of this DomainMatrix.

        Returns
        =======

        DomainMatrix
            DomainMatrix with the desired domain or field

        Examples
        ========

        >>> from sympy import ZZ, ZZ_I
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

        >>> A.convert_to(ZZ_I)
        DomainMatrix([[1, 2], [3, 4]], (2, 2), ZZ_I)

        N)ro   r+   r   
convert_tor1   rn   r   r   r   rq     s    zDomainMatrix.convert_toc                 C   s
   |  tS r/   )rq   r   rp   r   r   r   r=     s    zDomainMatrix.to_sympyc                 C   s   | j  }| |S )a  
        Returns a DomainMatrix with the appropriate field

        Returns
        =======

        DomainMatrix
            DomainMatrix with the appropriate field

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

        >>> A.to_field()
        DomainMatrix([[1, 2], [3, 4]], (2, 2), QQ)

        )r   	get_fieldrq   rr   r   r   r   to_field  s    
zDomainMatrix.to_fieldc                 C   s"   | j jdkr| S | t| j S )a{  
        Return a sparse DomainMatrix representation of *self*.

        Examples
        ========

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy import QQ
        >>> A = DomainMatrix([[1, 0],[0, 2]], (2, 2), QQ)
        >>> A.rep
        [[1, 0], [0, 2]]
        >>> B = A.to_sparse()
        >>> B.rep
        {0: {0: 1}, 1: {1: 2}}
        r"   )r   r!   r+   r   Zfrom_ddmrp   r   r   r   	to_sparse  s    zDomainMatrix.to_sparsec                 C   s"   | j jdkr| S | t| j S )a  
        Return a dense DomainMatrix representation of *self*.

        Examples
        ========

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy import QQ
        >>> A = DomainMatrix({0: {0: 1}, 1: {1: 2}}, (2, 2), QQ)
        >>> A.rep
        {0: {0: 1}, 1: {1: 2}}
        >>> B = A.to_dense()
        >>> B.rep
        [[1, 0], [0, 2]]

        r#   )r   r!   r+   r   r)   rp   r   r   r   to_dense  s    zDomainMatrix.to_densec                    sB   dd |D }t |dkr|S tdd | t fdd|D S )z#Convert matrices to a common domainc                 S   s   h | ]
}|j qS r   rK   rN   matrixr   r   r   	<setcomp>$  rM   z-DomainMatrix._unify_domain.<locals>.<setcomp>r   c                 S   s
   |  |S r/   )unify)xyr   r   r   rL   '  rM   z,DomainMatrix._unify_domain.<locals>.<lambda>c                 3   s   | ]}|  V  qd S r/   )rq   rw   rK   r   r   rY   (  rM   z-DomainMatrix._unify_domain.<locals>.<genexpr>)rT   r   rI   )r,   matricesdomainsr   rK   r   _unify_domain!  s
    zDomainMatrix._unify_domainc                G   s^   dd |D }t |dkr|S |dkr8tdd |D S |dkrRtdd |D S td	d
S )zConvert matrices to the same format.

        If all matrices have the same format, then return unmodified.
        Otherwise convert both to the preferred format given as *fmt* which
        should be 'dense' or 'sparse'.
        c                 S   s   h | ]}|j jqS r   )r   r!   rw   r   r   r   ry   2  rM   z*DomainMatrix._unify_fmt.<locals>.<setcomp>r   r"   c                 s   s   | ]}|  V  qd S r/   )ru   rw   r   r   r   rY   6  rM   z*DomainMatrix._unify_fmt.<locals>.<genexpr>r#   c                 s   s   | ]}|  V  qd S r/   )rv   rw   r   r   r   rY   8  rM   r$   N)rT   rI   r*   )r,   r!   r}   formatsr   r   r   
_unify_fmt*  s    zDomainMatrix._unify_fmtc                G   s0   | f| }t j| }|dur,t j|d|i}|S )aL  
        Unifies the domains and the format of self and other
        matrices.

        Parameters
        ==========

        others : DomainMatrix

        fmt: string 'dense', 'sparse' or `None` (default)
            The preferred format to convert to if self and other are not
            already in the same format. If `None` or not specified then no
            conversion if performed.

        Returns
        =======

        Tuple[DomainMatrix]
            Matrices with unified domain and format

        Examples
        ========

        Unify the domain of DomainMatrix that have different domains:

        >>> from sympy import ZZ, QQ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ)
        >>> B = DomainMatrix([[QQ(1, 2), QQ(2)]], (1, 2), QQ)
        >>> Aq, Bq = A.unify(B)
        >>> Aq
        DomainMatrix([[1, 2]], (1, 2), QQ)
        >>> Bq
        DomainMatrix([[1/2, 2]], (1, 2), QQ)

        Unify the format (dense or sparse):

        >>> A = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ)
        >>> B = DomainMatrix({0:{0: ZZ(1)}}, (2, 2), ZZ)
        >>> B.rep
        {0: {0: 1}}

        >>> A2, B2 = A.unify(B, fmt='dense')
        >>> B2.rep
        [[1, 0], [0, 0]]

        See Also
        ========

        convert_to, to_dense, to_sparse

        Nr!   )r   r   r   )r1   r!   othersr}   r   r   r   rz   <  s
    5

zDomainMatrix.unifyc                    s<   ddl m}  j } fdd|D }|g  j|R  S )a  
        Convert DomainMatrix to Matrix

        Returns
        =======

        Matrix
            MutableDenseMatrix for the DomainMatrix

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

        >>> A.to_Matrix()
        Matrix([
            [1, 2],
            [3, 4]])

        See Also
        ========

        from_Matrix

        r   )MutableDenseMatrixc                    s"   g | ]}|D ]} j |qqS r   )r   r=   )rN   rS   rJ   rp   r   r   rQ     rM   z*DomainMatrix.to_Matrix.<locals>.<listcomp>)sympy.matrices.denser   r   to_listr   )r1   r   ZelemlistZelements_sympyr   rp   r   	to_Matrixw  s    
zDomainMatrix.to_Matrixc                 C   s
   | j  S r/   )r   r   rp   r   r   r   r     s    zDomainMatrix.to_listc                 C   s
   | j  S r/   )r   to_list_flatrp   r   r   r   r     s    zDomainMatrix.to_list_flatc                 C   s
   | j  S r/   )r   to_dokrp   r   r   r   r     s    zDomainMatrix.to_dokc                 C   s   dt | j| j| jf S )NzDomainMatrix(%s, %r, %r))strr   r   r   rp   r   r   r   __repr__  s    zDomainMatrix.__repr__c                 C   s   |  | j S )zMatrix transpose of ``self``)r+   r   	transposerp   r   r   r   r     s    zDomainMatrix.transposec                    s"   j \}  fddt|D S )Nc                    s(   g | ] }t  D ]}||f jqqS r   )r_   element)rN   r8   r9   colsr1   r   r   rQ     rM   z%DomainMatrix.flat.<locals>.<listcomp>)r   r_   )r1   r   r   r   r   flat  s    
zDomainMatrix.flatc                 C   s
   | j  S r/   )r   is_zero_matrixrp   r   r   r   r     s    zDomainMatrix.is_zero_matrixc                 C   s
   | j  S )z~
        Says whether this matrix is upper-triangular. True can be returned
        even if the matrix is not square.
        )r   is_upperrp   r   r   r   r     s    zDomainMatrix.is_upperc                 C   s
   | j  S )z~
        Says whether this matrix is lower-triangular. True can be returned
        even if the matrix is not square.
        )r   is_lowerrp   r   r   r   r     s    zDomainMatrix.is_lowerc                 C   s   | j d | j d kS )Nr   r   )r   rp   r   r   r   	is_square  s    zDomainMatrix.is_squarec                 C   s   |   \}}t|S r/   )rrefrT   )r1   r   pivotsr   r   r   rank  s    zDomainMatrix.rankc                 G   s0   | j |ddi^} }t| jjdd |D  S )a\  Horizontally stack the given matrices.

        Parameters
        ==========

        B: DomainMatrix
            Matrices to stack horizontally.

        Returns
        =======

        DomainMatrix
            DomainMatrix by stacking horizontally.

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix

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

        >>> C = DomainMatrix([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
        >>> A.hstack(B, C)
        DomainMatrix([[1, 2, 5, 6, 9, 10], [3, 4, 7, 8, 11, 12]], (2, 6), ZZ)

        See Also
        ========

        unify
        r!   r#   c                 s   s   | ]}|j V  qd S r/   r   rN   ZBkr   r   r   rY     rM   z&DomainMatrix.hstack.<locals>.<genexpr>)rz   r   r+   r   hstackABr   r   r   r     s    #zDomainMatrix.hstackc                 G   s0   | j |ddi^} }t| jjdd |D  S )ab  Vertically stack the given matrices.

        Parameters
        ==========

        B: DomainMatrix
            Matrices to stack vertically.

        Returns
        =======

        DomainMatrix
            DomainMatrix by stacking vertically.

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix

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

        >>> C = DomainMatrix([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
        >>> A.vstack(B, C)
        DomainMatrix([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]], (6, 2), ZZ)

        See Also
        ========

        unify
        r!   r#   c                 s   s   | ]}|j V  qd S r/   r   r   r   r   r   rY     rM   z&DomainMatrix.vstack.<locals>.<genexpr>)rz   r   r+   r   vstackr   r   r   r   r     s    #zDomainMatrix.vstackc                 C   s"   |d u r| j }| | j||S r/   )r   r+   r   	applyfunc)r1   funcr   r   r   r   r     s    zDomainMatrix.applyfuncc                 C   s*   t |tstS | j|dd\} }| |S Nr#   r    )r%   r   NotImplementedrz   addr   r   r   r   __add__  s    
zDomainMatrix.__add__c                 C   s*   t |tstS | j|dd\} }| |S r   )r%   r   r   rz   subr   r   r   r   __sub__!  s    
zDomainMatrix.__sub__c                 C   s   |   S r/   )negr   r   r   r   __neg__'  s    zDomainMatrix.__neg__c                 C   sf   t |tr&| j|dd\} }| |S || jv r:| |S t |tr^| |\} }| |jS tS dS )zA * Br#   r    N)	r%   r   rz   matmulr   	scalarmulr   r   r   r   r   r   r   __mul__*  s    




zDomainMatrix.__mul__c                 C   s@   || j v r| |S t|tr8| |\} }| |jS tS d S r/   )r   
rscalarmulr%   r   rz   r   r   r   r   r   r   __rmul__7  s    


zDomainMatrix.__rmul__c                 C   s   t |tstS | |S )zA ** n)r%   rA   r   pow)r   r;   r   r   r   __pow__@  s    
zDomainMatrix.__pow__c                 C   sz   | j |j kr&d| j ||j f }t|||krHd| j||jf }t|| jj|jjkrvd| jj||jjf }t|d S )NzDomain mismatch: %s %s %szShape mismatch: %s %s %szFormat mismatch: %s %s %s)r   r   r   r   r   r!   r   )aopbashapeZbshaper-   r   r   r   _checkF  s    zDomainMatrix._checkc                 C   s(   |  d|| j|j | | j|jS )a  
        Adds two DomainMatrix matrices of the same Domain

        Parameters
        ==========

        A, B: DomainMatrix
            matrices to add

        Returns
        =======

        DomainMatrix
            DomainMatrix after Addition

        Raises
        ======

        DMShapeError
            If the dimensions of the two DomainMatrix are not equal

        ValueError
            If the domain of the two DomainMatrix are not same

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
        >>> B = DomainMatrix([
        ...    [ZZ(4), ZZ(3)],
        ...    [ZZ(2), ZZ(1)]], (2, 2), ZZ)

        >>> A.add(B)
        DomainMatrix([[5, 5], [5, 5]], (2, 2), ZZ)

        See Also
        ========

        sub, matmul

        +)r   r   r+   r   r   r   r   r   r   r   Q  s    .zDomainMatrix.addc                 C   s(   |  d|| j|j | | j|jS )a  
        Subtracts two DomainMatrix matrices of the same Domain

        Parameters
        ==========

        A, B: DomainMatrix
            matrices to substract

        Returns
        =======

        DomainMatrix
            DomainMatrix after Substraction

        Raises
        ======

        DMShapeError
            If the dimensions of the two DomainMatrix are not equal

        ValueError
            If the domain of the two DomainMatrix are not same

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
        >>> B = DomainMatrix([
        ...    [ZZ(4), ZZ(3)],
        ...    [ZZ(2), ZZ(1)]], (2, 2), ZZ)

        >>> A.sub(B)
        DomainMatrix([[-3, -1], [1, 3]], (2, 2), ZZ)

        See Also
        ========

        add, matmul

        -)r   r   r+   r   r   r   r   r   r   r     s    .zDomainMatrix.subc                 C   s   |  | j S )a  
        Returns the negative of DomainMatrix

        Parameters
        ==========

        A : Represents a DomainMatrix

        Returns
        =======

        DomainMatrix
            DomainMatrix after Negation

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

        >>> A.neg()
        DomainMatrix([[-1, -2], [-3, -4]], (2, 2), ZZ)

        )r+   r   r   r   r   r   r   r     s    zDomainMatrix.negc                 C   s   |  | j|S )aW  
        Performs term by term multiplication for the second DomainMatrix
        w.r.t first DomainMatrix. Returns a DomainMatrix whose rows are
        list of DomainMatrix matrices created after term by term multiplication.

        Parameters
        ==========

        A, B: DomainMatrix
            matrices to multiply term-wise

        Returns
        =======

        DomainMatrix
            DomainMatrix after term by term multiplication

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
        >>> B = DomainMatrix([
        ...    [ZZ(1), ZZ(1)],
        ...    [ZZ(0), ZZ(1)]], (2, 2), ZZ)

        >>> A.mul(B)
        DomainMatrix([[DomainMatrix([[1, 1], [0, 1]], (2, 2), ZZ),
        DomainMatrix([[2, 2], [0, 2]], (2, 2), ZZ)],
        [DomainMatrix([[3, 3], [0, 3]], (2, 2), ZZ),
        DomainMatrix([[4, 4], [0, 4]], (2, 2), ZZ)]], (2, 2), ZZ)

        See Also
        ========

        matmul

        )r+   r   mulr   r   r   r   r   r     s    *zDomainMatrix.mulc                 C   s   |  | j|S r/   )r+   r   rmulr   r   r   r   r     s    zDomainMatrix.rmulc                 C   s0   |  d|| jd |jd  | | j|jS )a  
        Performs matrix multiplication of two DomainMatrix matrices

        Parameters
        ==========

        A, B: DomainMatrix
            to multiply

        Returns
        =======

        DomainMatrix
            DomainMatrix after multiplication

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
        >>> B = DomainMatrix([
        ...    [ZZ(1), ZZ(1)],
        ...    [ZZ(0), ZZ(1)]], (2, 2), ZZ)

        >>> A.matmul(B)
        DomainMatrix([[1, 3], [3, 7]], (2, 2), ZZ)

        See Also
        ========

        mul, pow, add, sub

        *r   r   )r   r   r+   r   r   r   r   r   r   r     s    &zDomainMatrix.matmulc                 C   sL   || j jkrt| j| j S || j jkr0|  S |r>| |S | |S d S r/   )	r   zeror   zerosr   onero   r   r   )r   lamdareverser   r   r   
_scalarmul*  s    
zDomainMatrix._scalarmulc                 C   s   | j |ddS )NFr   r   r   r   r   r   r   r   4  s    zDomainMatrix.scalarmulc                 C   s   | j |ddS )NTr   r   r   r   r   r   r   7  s    zDomainMatrix.rscalarmulc                 C   s$   | j |j ksJ | | j|jS r/   )r   r+   r   mul_elementwiser   r   r   r   r   :  s    zDomainMatrix.mul_elementwisec                 C   sz   t |tst|r"tt|t}t |ts0tS |  |\} }|j|j	j
krTt|j|j	jkrj|  S | d|j S )z Method for Scalar Divisonr   )r%   rA   r   r@   r   r   rt   rz   r   r   r   ZeroDivisionErrorr   r   r   r   r   r   __truediv__>  s    
zDomainMatrix.__truediv__c                 C   s   | j \}}||krtd|dk r,tdnR|dkrB| || jS |dkrN| S |d dkrj| | |d   S | |d  }|| S dS )a  
        Computes A**n

        Parameters
        ==========

        A : DomainMatrix

        n : exponent for A

        Returns
        =======

        DomainMatrix
            DomainMatrix on computing A**n

        Raises
        ======

        NotImplementedError
            if n is negative.

        Examples
        ========

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

        >>> A.pow(2)
        DomainMatrix([[1, 2], [0, 1]], (2, 2), ZZ)

        See Also
        ========

        matmul

        zPower of a nonsquare matrixr   zNegative powersr   r   N)r   r   rC   eyer   )r   r;   rU   rV   ZsqrtAnr   r   r   r   N  s    )

zDomainMatrix.powc                 C   s    | j \}}||ksJ | j S )az  Compute the strongly connected components of a DomainMatrix

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

        A square matrix can be considered as the adjacency matrix for a
        directed graph where the row and column indices are the vertices. In
        this graph if there is an edge from vertex ``i`` to vertex ``j`` if
        ``M[i, j]`` is nonzero. This routine computes the strongly connected
        components of that graph which are subsets of the rows and columns that
        are connected by some nonzero element of the matrix. The strongly
        connected components are useful because many operations such as the
        determinant can be computed by working with the submatrices
        corresponding to each component.

        Examples
        ========

        Find the strongly connected components of a matrix:

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> M = DomainMatrix([[ZZ(1), ZZ(0), ZZ(2)],
        ...                   [ZZ(0), ZZ(3), ZZ(0)],
        ...                   [ZZ(4), ZZ(6), ZZ(5)]], (3, 3), ZZ)
        >>> M.scc()
        [[1], [0, 2]]

        Compute the determinant from the components:

        >>> MM = M.to_Matrix()
        >>> MM
        Matrix([
        [1, 0, 2],
        [0, 3, 0],
        [4, 6, 5]])
        >>> MM[[1], [1]]
        Matrix([[3]])
        >>> MM[[0, 2], [0, 2]]
        Matrix([
        [1, 2],
        [4, 5]])
        >>> MM.det()
        -9
        >>> MM[[1], [1]].det() * MM[[0, 2], [0, 2]].det()
        -9

        The components are given in reverse topological order and represent a
        permutation of the rows and columns that will bring the matrix into
        block lower-triangular form:

        >>> MM[[1, 0, 2], [1, 0, 2]]
        Matrix([
        [3, 0, 0],
        [0, 1, 2],
        [6, 4, 5]])

        Returns
        =======

        List of lists of integers
            Each list represents a strongly connected component.

        See also
        ========

        sympy.matrices.matrices.MatrixBase.strongly_connected_components
        sympy.utilities.iterables.strongly_connected_components

        )r   r   scc)r1   r   r   r   r   r   r     s    G
zDomainMatrix.sccc                 C   s0   | j jstd| j \}}| |t|fS )ae  
        Returns reduced-row echelon form and list of pivots for the DomainMatrix

        Returns
        =======

        (DomainMatrix, list)
            reduced-row echelon form and list of pivots for the DomainMatrix

        Raises
        ======

        ValueError
            If the domain of DomainMatrix not a Field

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...     [QQ(2), QQ(-1), QQ(0)],
        ...     [QQ(-1), QQ(2), QQ(-1)],
        ...     [QQ(0), QQ(0), QQ(2)]], (3, 3), QQ)

        >>> rref_matrix, rref_pivots = A.rref()
        >>> rref_matrix
        DomainMatrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]], (3, 3), QQ)
        >>> rref_pivots
        (0, 1, 2)

        See Also
        ========

        convert_to, lu

        Not a field)r   is_Fieldr   r   r   r+   rI   )r1   Zrref_ddmr   r   r   r   r     s    &zDomainMatrix.rrefc                 C   s6   | j jstd|  \}}| j\}}| t||S )a  
        Returns the columnspace for the DomainMatrix

        Returns
        =======

        DomainMatrix
            The columns of this matrix form a basis for the columnspace.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [QQ(1), QQ(-1)],
        ...    [QQ(2), QQ(-2)]], (2, 2), QQ)
        >>> A.columnspace()
        DomainMatrix([[1], [2]], (2, 1), QQ)

        r   )r   r   r   r   r   r?   r_   r1   r   r   r   r   r   r   r   columnspace  s
    
zDomainMatrix.columnspacec                 C   s>   | j jstd|  \}}| j\}}| tt|t|S )a  
        Returns the rowspace for the DomainMatrix

        Returns
        =======

        DomainMatrix
            The rows of this matrix form a basis for the rowspace.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [QQ(1), QQ(-1)],
        ...    [QQ(2), QQ(-2)]], (2, 2), QQ)
        >>> A.rowspace()
        DomainMatrix([[1, -1]], (1, 2), QQ)

        r   )r   r   r   r   r   r?   r_   rT   r   r   r   r   rowspace  s
    
zDomainMatrix.rowspacec                 C   s$   | j jstd| | j d S )a  
        Returns the nullspace for the DomainMatrix

        Returns
        =======

        DomainMatrix
            The rows of this matrix form a basis for the nullspace.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [QQ(1), QQ(-1)],
        ...    [QQ(2), QQ(-2)]], (2, 2), QQ)
        >>> A.nullspace()
        DomainMatrix([[1, 1]], (1, 2), QQ)

        r   r   )r   r   r   r+   r   	nullspacerp   r   r   r   r   4  s    zDomainMatrix.nullspacec                 C   s:   | j jstd| j\}}||kr&t| j }| |S )a#  
        Finds the inverse of the DomainMatrix if exists

        Returns
        =======

        DomainMatrix
            DomainMatrix after inverse

        Raises
        ======

        ValueError
            If the domain of DomainMatrix not a Field

        DMNonSquareMatrixError
            If the DomainMatrix is not a not Square DomainMatrix

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...     [QQ(2), QQ(-1), QQ(0)],
        ...     [QQ(-1), QQ(2), QQ(-1)],
        ...     [QQ(0), QQ(0), QQ(2)]], (3, 3), QQ)
        >>> A.inv()
        DomainMatrix([[2/3, 1/3, 1/6], [1/3, 2/3, 1/3], [0, 0, 1/2]], (3, 3), QQ)

        See Also
        ========

        neg

        r   )r   r   r   r   r   r   invr+   )r1   r:   r;   r   r   r   r   r   N  s    %

zDomainMatrix.invc                 C   s    | j \}}||krt| j S )a  
        Returns the determinant of a Square DomainMatrix

        Returns
        =======

        S.Complexes
            determinant of Square DomainMatrix

        Raises
        ======

        ValueError
            If the domain of DomainMatrix not a Field

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

        >>> A.det()
        -2

        )r   r   r   detr1   r:   r;   r   r   r   r   {  s    
zDomainMatrix.detc                 C   s6   | j jstd| j \}}}| || ||fS )a%  
        Returns Lower and Upper decomposition of the DomainMatrix

        Returns
        =======

        (L, U, exchange)
            L, U are Lower and Upper decomposition of the DomainMatrix,
            exchange is the list of indices of rows exchanged in the decomposition.

        Raises
        ======

        ValueError
            If the domain of DomainMatrix not a Field

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [QQ(1), QQ(-1)],
        ...    [QQ(2), QQ(-2)]], (2, 2), QQ)
        >>> A.lu()
        (DomainMatrix([[1, 0], [2, 1]], (2, 2), QQ), DomainMatrix([[1, -1], [0, 0]], (2, 2), QQ), [])

        See Also
        ========

        lu_solve

        r   )r   r   r   r   lur+   )r1   LUZswapsr   r   r   r     s    "zDomainMatrix.luc                 C   sD   | j d |j d krtd| jjs,td| j|j}| |S )am  
        Solver for DomainMatrix x in the A*x = B

        Parameters
        ==========

        rhs : DomainMatrix B

        Returns
        =======

        DomainMatrix
            x in A*x = B

        Raises
        ======

        DMShapeError
            If the DomainMatrix A and rhs have different number of rows

        ValueError
            If the domain of DomainMatrix A not a Field

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [QQ(1), QQ(2)],
        ...    [QQ(3), QQ(4)]], (2, 2), QQ)
        >>> B = DomainMatrix([
        ...    [QQ(1), QQ(1)],
        ...    [QQ(0), QQ(1)]], (2, 2), QQ)

        >>> A.lu_solve(B)
        DomainMatrix([[-2, -1], [3/2, 1]], (2, 2), QQ)

        See Also
        ========

        lu

        r   Shaper   )r   r   r   r   r   r   lu_solver+   )r1   rhssolr   r   r   r     s    -zDomainMatrix.lu_solvec           	      C   s   | j d |j d krtd| j|jks0| jjs8td| |}| \}}||j	 }|d d d df j
 \}}||}||fS )Nr   r   r   )r   r   r   r   r   r   r   r+   r   
particularr   )	r   r   ZAaugZArrefr   r   Znullspace_repZ	nonpivotsr   r   r   r   _solve  s    

zDomainMatrix._solvec                 C   s$   | j \}}||krtd| j S )a  
        Returns the coefficients of the characteristic polynomial
        of the DomainMatrix. These elements will be domain elements.
        The domain of the elements will be same as domain of the DomainMatrix.

        Returns
        =======

        list
            coefficients of the characteristic polynomial

        Raises
        ======

        DMNonSquareMatrixError
            If the DomainMatrix is not a not Square DomainMatrix

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

        >>> A.charpoly()
        [1, -5, -2]

        z
not square)r   r   r   charpolyr   r   r   r   r     s    
zDomainMatrix.charpolyc                 C   s$   t |tr||f}| t||S )a  
        Return identity matrix of size n

        Examples
        ========

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy import QQ
        >>> DomainMatrix.eye(3, QQ)
        DomainMatrix({0: {0: 1}, 1: {1: 1}, 2: {2: 1}}, (3, 3), QQ)

        )r%   rA   r+   r   r   r,   r   r   r   r   r   r   *  s    
zDomainMatrix.eyec                 C   s,   |du rt |}||f}| t|||S )a3  
        Return diagonal matrix with entries from ``diagonal``.

        Examples
        ========

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy import ZZ
        >>> DomainMatrix.diag([ZZ(5), ZZ(6)], ZZ)
        DomainMatrix({0: {0: 5}, 1: {1: 6}}, (2, 2), ZZ)

        N)rT   r+   r   diag)r,   diagonalr   r   Nr   r   r   r   <  s    zDomainMatrix.diagc                C   s   |  t||S )a%  Returns a zero DomainMatrix of size shape, belonging to the specified domain

        Examples
        ========

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy import QQ
        >>> DomainMatrix.zeros((2, 3), QQ)
        DomainMatrix({}, (2, 3), QQ)

        )r+   r   r   )r,   r   r   r!   r   r   r   r   O  s    zDomainMatrix.zerosc                 C   s   |  t||S )a9  Returns a DomainMatrix of 1s, of size shape, belonging to the specified domain

        Examples
        ========

        >>> from sympy.polys.matrices import DomainMatrix
        >>> from sympy import QQ
        >>> DomainMatrix.ones((2,3), QQ)
        DomainMatrix([[1, 1, 1], [1, 1, 1]], (2, 3), QQ)

        )r+   r   onesr   r   r   r   r   ^  s    zDomainMatrix.onesc                 C   s*   t | t|stS | j|jko(| j|jkS )a  
        Checks for two DomainMatrix matrices to be equal or not

        Parameters
        ==========

        A, B: DomainMatrix
            to check equality

        Returns
        =======

        Boolean
            True for equal, else False

        Raises
        ======

        NotImplementedError
            If B is not a DomainMatrix

        Examples
        ========

        >>> from sympy import ZZ
        >>> from sympy.polys.matrices import DomainMatrix
        >>> A = DomainMatrix([
        ...    [ZZ(1), ZZ(2)],
        ...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
        >>> B = DomainMatrix([
        ...    [ZZ(1), ZZ(1)],
        ...    [ZZ(0), ZZ(1)]], (2, 2), ZZ)
        >>> A.__eq__(A)
        True
        >>> A.__eq__(B)
        False

        )r%   typer   r   r   r   r   r   r   __eq__m  s    'zDomainMatrix.__eq__c                 C   s2   | j |j krdS | j|jkr*| |\} }| |kS )NF)r   r   rz   r   r   r   r   unify_eq  s
    zDomainMatrix.unify_eq)r"   )N)N)V__name__
__module____qualname____doc__tUnionr   r   __annotations__tTuplerA   r   r.   r3   r<   r>   r?   rE   classmethodr+   r   re   rj   rm   rb   ro   rq   r=   rt   ru   rv   r   r   rz   r   r   r   r   r   r   r   propertyr   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   __classcell__r   r   rG   r   r   5   s   
0&
	:
-
*
1,
"
;#



&&
	21,)
8K+-"'4$

+r   N) r   	functoolsr   typingr   r   r   r   sympy.core.sympifyr   r~   r   constructorr
   
exceptionsr   r   r   r   r   r   Zddmr   Zsdmr   Zdomainscalarr   sympy.polys.domainsr   r   r   r   r   r   r   r   <module>   s    