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