1 /* ========================================================================== */
2 /* === CHOLMOD/MATLAB/mread mexFunction ===================================== */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/MATLAB Module.  Copyright (C) 2005-2006, Timothy A. Davis
7  * http://www.suitesparse.com
8  * MATLAB(tm) is a Trademark of The MathWorks, Inc.
9  * -------------------------------------------------------------------------- */
10 
11 /* [A Z] = mread (filename, prefer_binary)
12  *
13  * Read a sparse or dense matrix from a file in Matrix Market format.
14  *
15  * All MatrixMarket formats are supported.
16  * The Matrix Market "integer" format is converted into real, but the values
17  * are preserved.  The "pattern" format is converted into real.  If a pattern
18  * matrix is unsymmetric, all of its values are equal to one.  If a pattern is
19  * symmetric, the kth diagonal entry is set to one plus the number of
20  * off-diagonal nonzeros in row/column k, and off-diagonal entries are set to
21  * -1.
22  *
23  * Explicit zero entries are returned as the binary pattern of the matrix Z.
24  */
25 
26 #include "cholmod_matlab.h"
27 
28 /* maximum file length */
29 #define MAXLEN 1030
30 
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])31 void mexFunction
32 (
33     int	nargout,
34     mxArray *pargout [ ],
35     int	nargin,
36     const mxArray *pargin [ ]
37 )
38 {
39     void *G ;
40     cholmod_dense *X = NULL ;
41     cholmod_sparse *A = NULL, *Z = NULL ;
42     cholmod_common Common, *cm ;
43     Long *Ap = NULL, *Ai ;
44     double *Ax, *Az = NULL ;
45     char filename [MAXLEN] ;
46     Long nz, k, is_complex = FALSE, nrow = 0, ncol = 0, allzero ;
47     int mtype ;
48 
49     /* ---------------------------------------------------------------------- */
50     /* start CHOLMOD and set parameters */
51     /* ---------------------------------------------------------------------- */
52 
53     cm = &Common ;
54     cholmod_l_start (cm) ;
55     sputil_config (SPUMONI, cm) ;
56 
57     /* ---------------------------------------------------------------------- */
58     /* get inputs */
59     /* ---------------------------------------------------------------------- */
60 
61     if (nargin < 1 || nargin > 2 || nargout > 2)
62     {
63 	mexErrMsgTxt ("usage: [A Z] = mread (filename, prefer_binary)") ;
64     }
65     if (!mxIsChar (pargin [0]))
66     {
67 	mexErrMsgTxt ("mread requires a filename") ;
68     }
69     mxGetString (pargin [0], filename, MAXLEN) ;
70     sputil_file = fopen (filename, "r") ;
71     if (sputil_file == NULL)
72     {
73 	mexErrMsgTxt ("cannot open file") ;
74     }
75     if (nargin > 1)
76     {
77 	cm->prefer_binary = (mxGetScalar (pargin [1]) != 0) ;
78     }
79 
80     /* ---------------------------------------------------------------------- */
81     /* read the matrix, as either a dense or sparse matrix */
82     /* ---------------------------------------------------------------------- */
83 
84     G = cholmod_l_read_matrix (sputil_file, 1, &mtype, cm) ;
85     fclose (sputil_file) ;
86     sputil_file = NULL ;
87     if (G == NULL)
88     {
89 	mexErrMsgTxt ("could not read file") ;
90     }
91 
92     /* get the specific matrix (A or X), and change to ZOMPLEX if needed */
93     if (mtype == CHOLMOD_SPARSE)
94     {
95 	A = (cholmod_sparse *) G ;
96 	nrow = A->nrow ;
97 	ncol = A->ncol ;
98 	is_complex = (A->xtype == CHOLMOD_COMPLEX) ;
99 	Ap = A->p ;
100 	Ai = A->i ;
101 	if (is_complex)
102 	{
103 	    /* if complex, ensure A is ZOMPLEX */
104 	    cholmod_l_sparse_xtype (CHOLMOD_ZOMPLEX, A, cm) ;
105 	}
106 	Ax = A->x ;
107 	Az = A->z ;
108     }
109     else if (mtype == CHOLMOD_DENSE)
110     {
111 	X = (cholmod_dense *) G ;
112 	nrow = X->nrow ;
113 	ncol = X->ncol ;
114 	is_complex = (X->xtype == CHOLMOD_COMPLEX) ;
115 	if (is_complex)
116 	{
117 	    /* if complex, ensure X is ZOMPLEX */
118 	    cholmod_l_dense_xtype (CHOLMOD_ZOMPLEX, X, cm) ;
119 	}
120 	Ax = X->x ;
121 	Az = X->z ;
122     }
123     else
124     {
125 	mexErrMsgTxt ("invalid file") ;
126     }
127 
128     /* ---------------------------------------------------------------------- */
129     /* if requested, extract the zero entries and place them in Z */
130     /* ---------------------------------------------------------------------- */
131 
132     if (nargout > 1)
133     {
134 	if (mtype == CHOLMOD_SPARSE)
135 	{
136 	    /* A is a sparse real/zomplex double matrix */
137 	    Z = sputil_extract_zeros (A, cm) ;
138 	}
139 	else
140 	{
141 	    /* input is full; just return an empty Z matrix */
142 	    Z = cholmod_l_spzeros (nrow, ncol, 0, CHOLMOD_REAL, cm) ;
143 	}
144     }
145 
146     /* ---------------------------------------------------------------------- */
147     /* prune the zero entries from A and set nzmax(A) to nnz(A) */
148     /* ---------------------------------------------------------------------- */
149 
150     if (mtype == CHOLMOD_SPARSE)
151     {
152 	sputil_drop_zeros (A) ;
153 	cholmod_l_reallocate_sparse (cholmod_l_nnz (A, cm), A, cm) ;
154     }
155 
156     /* ---------------------------------------------------------------------- */
157     /* change a complex matrix to real if its imaginary part is all zero */
158     /* ---------------------------------------------------------------------- */
159 
160     if (is_complex)
161     {
162 	if (mtype == CHOLMOD_SPARSE)
163 	{
164 	    nz = Ap [ncol] ;
165 	}
166 	else
167 	{
168 	    nz = nrow * ncol ;
169 	}
170 	allzero = TRUE ;
171 	for (k = 0 ; k < nz ; k++)
172 	{
173 	    if (Az [k] != 0)
174 	    {
175 		allzero = FALSE ;
176 		break ;
177 	    }
178 	}
179 	if (allzero)
180 	{
181 	    /* discard the all-zero imaginary part */
182 	    if (mtype == CHOLMOD_SPARSE)
183 	    {
184 		cholmod_l_sparse_xtype (CHOLMOD_REAL, A, cm) ;
185 	    }
186 	    else
187 	    {
188 		cholmod_l_dense_xtype (CHOLMOD_REAL, X, cm) ;
189 	    }
190 	}
191     }
192 
193     /* ---------------------------------------------------------------------- */
194     /* return results to MATLAB */
195     /* ---------------------------------------------------------------------- */
196 
197     if (mtype == CHOLMOD_SPARSE)
198     {
199 	pargout [0] = sputil_put_sparse (&A, cm) ;
200     }
201     else
202     {
203 	pargout [0] = sputil_put_dense (&X, cm) ;
204     }
205     if (nargout > 1)
206     {
207 	pargout [1] = sputil_put_sparse (&Z, cm) ;
208     }
209 
210     /* ---------------------------------------------------------------------- */
211     /* free workspace */
212     /* ---------------------------------------------------------------------- */
213 
214     cholmod_l_finish (cm) ;
215     cholmod_l_print_common (" ", cm) ;
216 }
217