U
    @f                     @   s   d Z ddlZddlZddlmZmZmZmZmZm	Z	m
Z
mZmZ ddlmZmZ ddddgZd	d
 Zdd Zdd ZdddZG dd dZdd ZdS )z
  Matrix Market I/O in Python.
  See http://math.nist.gov/MatrixMarket/formats.html
  for information about the Matrix Market format.
    N)	asarrayrealimagconjzerosndarrayconcatenateonescan_cast)
coo_matrix
isspmatrixmminfommreadmmwriteMMFilec                 C   s   t | tr| dS t| S )Nlatin1)
isinstancebytesdecodestr)s r   2/tmp/pip-unpacked-wheel-w7avvj8p/scipy/io/_mmio.pyasstr   s    

r   c                 C   s
   t | S )a  
    Return size and storage parameters from Matrix Market file-like 'source'.

    Parameters
    ----------
    source : str or file-like
        Matrix Market filename (extension .mtx) or open file-like object

    Returns
    -------
    rows : int
        Number of matrix rows.
    cols : int
        Number of matrix columns.
    entries : int
        Number of non-zero entries of a sparse matrix
        or rows*cols for a dense matrix.
    format : str
        Either 'coordinate' or 'array'.
    field : str
        Either 'real', 'complex', 'pattern', or 'integer'.
    symmetry : str
        Either 'general', 'symmetric', 'skew-symmetric', or 'hermitian'.

    Examples
    --------
    >>> from io import StringIO
    >>> from scipy.io import mminfo

    >>> text = '''%%MatrixMarket matrix coordinate real general
    ...  5 5 7
    ...  2 3 1.0
    ...  3 4 2.0
    ...  3 5 3.0
    ...  4 1 4.0
    ...  4 2 5.0
    ...  4 3 6.0
    ...  4 4 7.0
    ... '''


    ``mminfo(source)`` returns the number of rows, number of columns,
    format, field type and symmetry attribute of the source file.

    >>> mminfo(StringIO(text))
    (5, 5, 7, 'coordinate', 'real', 'general')
    )r   infosourcer   r   r   r      s    0c                 C   s   t  | S )aG  
    Reads the contents of a Matrix Market file-like 'source' into a matrix.

    Parameters
    ----------
    source : str or file-like
        Matrix Market filename (extensions .mtx, .mtz.gz)
        or open file-like object.

    Returns
    -------
    a : ndarray or coo_matrix
        Dense or sparse matrix depending on the matrix format in the
        Matrix Market file.

    Examples
    --------
    >>> from io import StringIO
    >>> from scipy.io import mmread

    >>> text = '''%%MatrixMarket matrix coordinate real general
    ...  5 5 7
    ...  2 3 1.0
    ...  3 4 2.0
    ...  3 5 3.0
    ...  4 1 4.0
    ...  4 2 5.0
    ...  4 3 6.0
    ...  4 4 7.0
    ... '''

    ``mmread(source)`` returns the data as sparse matrix in COO format.

    >>> m = mmread(StringIO(text))
    >>> m
    <5x5 sparse matrix of type '<class 'numpy.float64'>'
    with 7 stored elements in COOrdinate format>
    >>> m.A
    array([[0., 0., 0., 0., 0.],
           [0., 0., 1., 0., 0.],
           [0., 0., 0., 2., 3.],
           [4., 5., 6., 7., 0.],
           [0., 0., 0., 0., 0.]])
    )r   readr   r   r   r   r   T   s    - c                 C   s   t  | ||||| dS )a  
    Writes the sparse or dense array `a` to Matrix Market file-like `target`.

    Parameters
    ----------
    target : str or file-like
        Matrix Market filename (extension .mtx) or open file-like object.
    a : array like
        Sparse or dense 2-D array.
    comment : str, optional
        Comments to be prepended to the Matrix Market file.
    field : None or str, optional
        Either 'real', 'complex', 'pattern', or 'integer'.
    precision : None or int, optional
        Number of digits to display for real or complex values.
    symmetry : None or str, optional
        Either 'general', 'symmetric', 'skew-symmetric', or 'hermitian'.
        If symmetry is None the symmetry type of 'a' is determined by its
        values.

    Returns
    -------
    None

    Examples
    --------
    >>> from io import BytesIO
    >>> import numpy as np
    >>> from scipy.sparse import coo_matrix
    >>> from scipy.io import mmwrite

    Write a small NumPy array to a matrix market file.  The file will be
    written in the ``'array'`` format.

    >>> a = np.array([[1.0, 0, 0, 0], [0, 2.5, 0, 6.25]])
    >>> target = BytesIO()
    >>> mmwrite(target, a)
    >>> print(target.getvalue().decode('latin1'))
    %%MatrixMarket matrix array real general
    %
    2 4
    1.0000000000000000e+00
    0.0000000000000000e+00
    0.0000000000000000e+00
    2.5000000000000000e+00
    0.0000000000000000e+00
    0.0000000000000000e+00
    0.0000000000000000e+00
    6.2500000000000000e+00

    Add a comment to the output file, and set the precision to 3.

    >>> target = BytesIO()
    >>> mmwrite(target, a, comment='\n Some test data.\n', precision=3)
    >>> print(target.getvalue().decode('latin1'))
    %%MatrixMarket matrix array real general
    %
    % Some test data.
    %
    2 4
    1.000e+00
    0.000e+00
    0.000e+00
    2.500e+00
    0.000e+00
    0.000e+00
    0.000e+00
    6.250e+00

    Convert to a sparse matrix before calling ``mmwrite``.  This will
    result in the output format being ``'coordinate'`` rather than
    ``'array'``.

    >>> target = BytesIO()
    >>> mmwrite(target, coo_matrix(a), precision=3)
    >>> print(target.getvalue().decode('latin1'))
    %%MatrixMarket matrix coordinate real general
    %
    2 4 3
    1 1 1.00e+00
    2 2 2.50e+00
    2 4 6.25e+00

    Write a complex Hermitian array to a matrix market file.  Note that
    only six values are actually written to the file; the other values
    are implied by the symmetry.

    >>> z = np.array([[3, 1+2j, 4-3j], [1-2j, 1, -5j], [4+3j, 5j, 2.5]])
    >>> z
    array([[ 3. +0.j,  1. +2.j,  4. -3.j],
           [ 1. -2.j,  1. +0.j, -0. -5.j],
           [ 4. +3.j,  0. +5.j,  2.5+0.j]])

    >>> target = BytesIO()
    >>> mmwrite(target, z, precision=2)
    >>> print(target.getvalue().decode('latin1'))
    %%MatrixMarket matrix array complex hermitian
    %
    3 3
    3.00e+00 0.00e+00
    1.00e+00 -2.00e+00
    4.00e+00 3.00e+00
    1.00e+00 0.00e+00
    0.00e+00 5.00e+00
    2.50e+00 0.00e+00

    N)r   write)targetacommentfield	precisionsymmetryr   r   r   r      s    lc                
   @   st  e Zd ZdZedd Zedd Zedd Zedd	 Zed
d Z	edd Z
edd ZdZdZeefZedd ZdZdZdZdZdZeeeeefZedd ZdZdZdZdZeeeefZedd  Zed!ed"ed#ed$ed#iZed%d& Z ed'd( Z!ed)d* Z"edBd,d-Z#ed.d/ Z$ed0d1 Z%d2d3 Z&d4d5 Z'dCd8d9Z(d:d; Z)d<d= Z*d>d? Z+dDd@dAZ,d7S )Er   )_rows_cols_entries_format_field	_symmetryc                 C   s   | j S N)r&   selfr   r   r   rows   s    zMMFile.rowsc                 C   s   | j S r,   )r'   r-   r   r   r   cols  s    zMMFile.colsc                 C   s   | j S r,   )r(   r-   r   r   r   entries  s    zMMFile.entriesc                 C   s   | j S r,   )r)   r-   r   r   r   format
  s    zMMFile.formatc                 C   s   | j S r,   )r*   r-   r   r   r   r#     s    zMMFile.fieldc                 C   s   | j S r,   )r+   r-   r   r   r   r%     s    zMMFile.symmetryc                 C   s   | j | j| j| jfkS r,   )r+   SYMMETRY_SYMMETRICSYMMETRY_SKEW_SYMMETRICSYMMETRY_HERMITIANr-   r   r   r   has_symmetry  s    zMMFile.has_symmetry
coordinatearrayc                 C   s    || j krtd|| j f d S )Nz)unknown format type %s, must be one of %s)FORMAT_VALUES
ValueError)r.   r2   r   r   r   _validate_format!  s    
zMMFile._validate_formatintegerunsigned-integerr   complexpatternc                 C   s    || j krtd|| j f d S )Nz(unknown field type %s, must be one of %s)FIELD_VALUESr:   )r.   r#   r   r   r   _validate_field0  s    
zMMFile._validate_fieldZgeneralZ	symmetriczskew-symmetricZ	hermitianc                 C   s    || j krtd|| j f d S )Nz+unknown symmetry type %s, must be one of %s)SYMMETRY_VALUESr:   )r.   r%   r   r   r   _validate_symmetry>  s    
zMMFile._validate_symmetryintpuint64dDc                   C   s   d S r,   r   r   r   r   r   readerK  s    zMMFile.readerc                   C   s   d S r,   r   r   r   r   r   writerP  s    zMMFile.writerc                 C   sZ  |  |\}}z4| }dd | D \}}}}}	|dsHtd| dks`td| | dkrt| j}n| dkr| j}|r|d	 d
kr| }q|	 s| }q| }
|| jkrt
|
dkstd|d tt|
\}}|| }n0t
|
dkstd|d tt|
\}}}||||| |	 fW S |rT|  X dS )a  
        Return size, storage parameters from Matrix Market file-like 'source'.

        Parameters
        ----------
        source : str or file-like
            Matrix Market filename (extension .mtx) or open file-like object

        Returns
        -------
        rows : int
            Number of matrix rows.
        cols : int
            Number of matrix columns.
        entries : int
            Number of non-zero entries of a sparse matrix
            or rows*cols for a dense matrix.
        format : str
            Either 'coordinate' or 'array'.
        field : str
            Either 'real', 'complex', 'pattern', or 'integer'.
        symmetry : str
            Either 'general', 'symmetric', 'skew-symmetric', or 'hermitian'.
        c                 S   s   g | ]}t | qS r   )r   strip).0partr   r   r   
<listcomp>w  s     zMMFile.info.<locals>.<listcomp>z%%MatrixMarketz%source is not in Matrix Market formatmatrixzProblem reading file header: r8   r7   r   %%      zHeader line not of length 2: ascii   zHeader line not of length 3: N)_openclosereadlinesplit
startswithr:   lowerFORMAT_ARRAYFORMAT_COORDINATErJ   lenr   mapint)r.   r   streamclose_itlineZmmidrN   r2   r#   r%   Z
split_liner/   r0   r1   r   r   r   r   U  sF    




zMMFile.inforbc                 C   s  zt | } W n tk
r*   | df Y S X |d dkrt j| st j| d r^| d } n2t j| d rx| d } nt j| d r| d } | drddl}|| |}n*| d	rddl}|	| d
}n
t| |}n"| dd dkr| d } t| |}|dfS )a   Return an open file stream for reading based on source.

        If source is a file name, open it (after trying to find it with mtx and
        gzipped mtx extensions). Otherwise, just return source.

        Parameters
        ----------
        filespec : str or file-like
            String giving file name or file-like object
        mode : str, optional
            Mode with which to open file, if `filespec` is a file name.

        Returns
        -------
        fobj : file-like
            Open file-like object.
        close_it : bool
            True if the calling function should close this file when done,
            false otherwise.
        Fr   rz.mtxz.mtx.gzz.mtx.bz2z.gzNz.bz2rc   T)
osfspath	TypeErrorpathisfileendswithgzipopenbz2BZ2File)Zfilespecmoderl   r`   rn   r   r   r   rU     s.    




zMMFile._openc              
      s<   j \}|krtjS d}d} jjdk}t r|     \}}||k  ||k krftjS  	   fdd}n fdd}| D ]\}}	}
|r|
r|dkrd}nN|r||	krd}t
jdd	 |r||	 krd}W 5 Q R X |r|t|	krd}|s|s|s qq|rtjS |r*tjS |r6tjS tjS )
NTFDc                  3   sP      D ]B\\} }}| |kr6 || f }||dfV  q| |kr||dfV  qd S )NFT)items)ijaijaji)r!   r   r   symm_iterator  s    z+MMFile._get_symmetry.<locals>.symm_iteratorc                  3   sL   t D ]>} t | D ].} | |   |  |  }}|||| kfV  qqd S r,   )range)rt   rs   ru   rv   r!   nr   r   rw      s    r   Fignore)Zover)shaper   SYMMETRY_GENERALdtypecharr   tocooZnonzerosumZtodoknpZerrstater   r3   r4   r5   )r!   mZissymmZisskewZishermrowcolrw   ru   rv   Zis_diagonalr   ry   r   _get_symmetry  sB    
zMMFile._get_symmetryc              
   C   s0   t jd| t jdt jdt jd||f i| d S )Nz%%.%ie
z%i
z%u
z%%.%ie %%.%ie
)r   
FIELD_REALFIELD_INTEGERFIELD_UNSIGNEDFIELD_COMPLEXget)r#   r$   r   r   r   _field_template!  s    
    zMMFile._field_templatec                 K   s   | j f | d S r,   )_init_attrs)r.   kwargsr   r   r   __init__+  s    zMMFile.__init__c                 C   s:   |  |\}}z| | | |W S |r4|  X dS )a  
        Reads the contents of a Matrix Market file-like 'source' into a matrix.

        Parameters
        ----------
        source : str or file-like
            Matrix Market filename (extensions .mtx, .mtz.gz)
            or open file object.

        Returns
        -------
        a : ndarray or coo_matrix
            Dense or sparse matrix depending on the matrix format in the
            Matrix Market file.
        N)rU   rV   _parse_header_parse_body)r.   r   r`   ra   r   r   r   r   /  s    
zMMFile.readr   Nc           	      C   sF   |  |d\}}z| |||||| W 5 |r8|  n|  X dS )a7  
        Writes sparse or dense array `a` to Matrix Market file-like `target`.

        Parameters
        ----------
        target : str or file-like
            Matrix Market filename (extension .mtx) or open file-like object.
        a : array like
            Sparse or dense 2-D array.
        comment : str, optional
            Comments to be prepended to the Matrix Market file.
        field : None or str, optional
            Either 'real', 'complex', 'pattern', or 'integer'.
        precision : None or int, optional
            Number of digits to display for real or complex values.
        symmetry : None or str, optional
            Either 'general', 'symmetric', 'skew-symmetric', or 'hermitian'.
            If symmetry is None the symmetry type of 'a' is determined by its
            values.
        wbN)rU   rV   flush_write)	r.   r    r!   r"   r#   r$   r%   r`   ra   r   r   r   r   J  s    
zMMFile.writec              	   K   sl   | j j}dd |D }t| t| }|rBtdt||f |D ] }t| |||dd d qFdS )zr
        Initialize each attributes with the corresponding keyword arg value
        or a default of None
        c                 S   s   g | ]}|d d qS )   Nr   )rK   attrr   r   r   rM   t  s     z&MMFile._init_attrs.<locals>.<listcomp>zVfound %s invalid keyword arguments, please only
                                use %sr   N)	__class__	__slots__setkeysr:   tuplesetattrr   )r.   r   attrsZpublic_attrsZinvalid_keysr   r   r   r   r   m  s    zMMFile._init_attrsc                 C   s2   | j |\}}}}}}| j||||||d d S )N)r/   r0   r1   r2   r#   r%   )r   r   r   )r.   r`   r/   r0   r1   r2   r#   r%   r   r   r   r     s    
 zMMFile._parse_headerc                  C   s  | j | j| j| j| j| jf\}}}}}}zddlm} W n tk
rP   d }Y nX | j	
|d }	| j}
|| jk}|| jk}|| jk}|| jk}|| jk}|| jk}|| jkrVt||f|	d}d}d\}}|rd|||f< ||d k r|d7 }|r| }|r|d dks| sq|r(t|}n2|r8t|}n"|rRttt|  }nt|}||||f< |
r||kr|r| |||f< n$|rt||||f< n||||f< ||d k r|d }q|d }|
sd}q|}|rd|||f< ||d k r|d7 }q|r2|d|fkr(||d ksRtdn |d|fkrJ||kstdn~|| jkr|d krt||f|	d}d}d}|r| }|r|d dks| sq| }tt|d d \}}|d |d  }}|rt|d }n>|rt|d }n*|r*ttt|dd   }nt|d }||||f< |
r||kr|rh| |||f< n$|rt||||f< n||||f< |d }q||kstd	 n&|| jkr|dkr|||f|	dS t|d
d}t|d
d}|r t|dd}nH|rt|dd}n4|r(t|dd}n |r<t|dd}nt|dd}d}|D ]}|rP|d dksP| svqP|d |krtd| }tt|d d \||< ||< |s|rt|d ||< nJ|rt|d ||< n2|r
ttt|dd   ||< nt|d ||< |d7 }qP||k r8td|d8 }|d8 }|
r||k}|| }|| }|| }t||f}t||f}|r|d9 }n|r|  }t||f}||||ff||f|	d}nt!||S )Nr   )r   )r~   r   )r   r   rO   z$Parse error, did not read all lines.rR   zDid not read all entriesZintcZint8rD   rE   r>   floatz5'entries' in header is smaller than number of entriesz4'entries' in header is larger than number of entries)r|   r~   )"r/   r0   r1   r2   r#   r%   scipy.sparser   ImportErrorDTYPES_BY_FIELDr   r6   r   r   r   r4   r5   FIELD_PATTERNr[   r   rW   rJ   r_   r>   r^   r   rX   r   r:   r\   r	   r   	conjugateNotImplementedError) r.   r`   r/   r0   r1   r2   r#   Zsymmr   r~   r6   
is_integerZis_unsigned_integerZ
is_complexZis_skewZis_hermZ
is_patternr!   rb   rs   rt   ru   klIJVZentry_numbermaskZod_IZod_JZod_Vr   r   r   r     s     















zMMFile._parse_bodyc                 C   s  t |ts(t |ts(t |ts(t|dr| j}t|}t|jdkrLt	d|j\}}	|d k	r|| j
krt|jds|td|d}q|| jkr|jjdkr|d}q|| jkr|jjdkr|d	}n&t|st	d
t| d}|j\}}	|jj}
|d kr|
dkrd}nd}|d kr|jj}|dkrPt|jdsJtdd}n<|dkr`d}n,|dkrpd}n|dkrd}ntd| |d kr| |}| j| | j| | j| d| d| d| d}||d |dD ]}d| }||d q| ||}|| jkr*d||	f }||d || j
| j| jfkrF|| j krt!|	D ]6}t!|D ]&}||||f  }||d qqtn|| j"krt!|	D ]<}t!|d |D ]&}||||f  }||d qԐqnBt!|	D ]8}t!||D ]&}||||f  }||d qq
n|| jkr|| j krt!|	D ]F}t!|D ]6}|||f }|t#|t$|f }||d qrqfnRt!|	D ]H}t!||D ]6}|||f }|t#|t$|f }||d qƐqn"|| j%krt	dntd | n|& }|| j krr|j'|j(k}t)|j*| |j'| |j(| ff|jd!}d"||	|j+f }||d | ||d }|| j%krt,|j'd |j(d D ]&\}}d||f }||d qn|| j
| j| jfkrRt,|j'd |j(d |j*D ]0\}}}d#||f ||  }||d qnn|| jkrt,|j'd |j(d |j*D ]8\}}}d#||f ||j#|j$f  }||d qxntd | d S )$NZ	__array__rR   zExpected 2 dimensional arrayrD   zBmmwrite does not support integer dtypes larger than native 'intp'.fdrF   rq   rG   zunknown matrix type: %sr7   ZfF      rs   r<   fr   cr>   ur=   zunexpected dtype kind z%%MatrixMarket matrix  
r   z%%%s
z%i %i
r   z*pattern type inconsisted with dense formatzUnknown field type %s)r|   z	%i %i %i
z%i %i )-r   listr   r   hasattrr[   r   r]   r|   r:   r   r
   r~   OverflowErrorZastyper   r   r   r   typekindrh   r   r   r;   rA   rC   r   encoderX   r   r   r}   rx   r4   r   r   r   r   r   r   r   dataZnnzzip)r.   r`   r!   r"   r#   r$   r%   repr/   r0   typecoder   r   rb   templatert   rs   ru   ZcooZlower_triangle_maskrd   r   rF   r   r   r   r   5  s    

















$$zMMFile._write)rc   )r   NNN)r   NNN)-__name__
__module____qualname__r   propertyr/   r0   r1   r2   r#   r%   r6   r\   r[   r9   classmethodr;   r   r   r   r   r   r@   rA   r}   r3   r4   r5   rB   rC   r   staticmethodrH   rI   r   rU   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s   








 
    


K>
@
	  
# /  c                 C   st   g }zddl }||j W n tk
r0   Y nX zddl}||j W n tk
r^   Y nX t|}t| | S )z
    Check whether `stream` is compatible with numpy.fromfile.

    Passing a gzipped file object to ``fromfile/fromstring`` doesn't work with
    Python 3.
    r   N)rl   appendGzipFiler   rn   ro   r   r   )r`   Zbad_clsrl   rn   r   r   r   _is_fromfile_compatible  s    r   )r   NNN)__doc__rf   Znumpyr   r   r   r   r   r   r   r   r	   r
   r   r   r   __all__r   r   r   r   r   r   r   r   r   r   <module>   s    ,52
p     ^