1 #include "cs_mex.h"
2 /* check MATLAB input argument */
cs_mex_check(CS_INT nel,CS_INT m,CS_INT n,int square,int sparse,int values,const mxArray * A)3 void cs_mex_check (CS_INT nel, CS_INT m, CS_INT n, int square, int sparse,
4 int values, const mxArray *A)
5 {
6 CS_INT nnel, mm = mxGetM (A), nn = mxGetN (A) ;
7 #ifdef NCOMPLEX
8 if (values)
9 {
10 if (mxIsComplex (A)) mexErrMsgTxt ("complex matrices not supported") ;
11 }
12 #endif
13 if (sparse && !mxIsSparse (A)) mexErrMsgTxt ("matrix must be sparse") ;
14 if (!sparse)
15 {
16 if (mxIsSparse (A)) mexErrMsgTxt ("matrix must be full") ;
17 if (values && !mxIsDouble (A)) mexErrMsgTxt ("matrix must be double") ;
18 }
19 if (nel)
20 {
21 /* check number of elements */
22 nnel = mxGetNumberOfElements (A) ;
23 if (m >= 0 && n >= 0 && m*n != nnel) mexErrMsgTxt ("wrong length") ;
24 }
25 else
26 {
27 /* check row and/or column dimensions */
28 if (m >= 0 && m != mm) mexErrMsgTxt ("wrong dimension") ;
29 if (n >= 0 && n != nn) mexErrMsgTxt ("wrong dimension") ;
30 }
31 if (square && mm != nn) mexErrMsgTxt ("matrix must be square") ;
32 }
33
34 /* get a real (or pattern) MATLAB sparse matrix and convert to cs_dl */
cs_dl_mex_get_sparse(cs_dl * A,int square,int values,const mxArray * Amatlab)35 cs_dl *cs_dl_mex_get_sparse (cs_dl *A, int square, int values,
36 const mxArray *Amatlab)
37 {
38 cs_mex_check (0, -1, -1, square, 1, values, Amatlab) ;
39 A->m = mxGetM (Amatlab) ;
40 A->n = mxGetN (Amatlab) ;
41 A->p = (CS_INT *) mxGetJc (Amatlab) ;
42 A->i = (CS_INT *) mxGetIr (Amatlab) ;
43 A->x = values ? mxGetPr (Amatlab) : NULL ;
44 A->nzmax = mxGetNzmax (Amatlab) ;
45 A->nz = -1 ; /* denotes a compressed-col matrix, instead of triplet */
46 return (A) ;
47 }
48
49
50 /* return a real sparse matrix to MATLAB */
cs_dl_mex_put_sparse(cs_dl ** Ahandle)51 mxArray *cs_dl_mex_put_sparse (cs_dl **Ahandle)
52 {
53 cs_dl *A ;
54 mxArray *Amatlab ;
55 if (!Ahandle || !CS_CSC ((*Ahandle))) mexErrMsgTxt ("invalid sparse matrix") ;
56 A = *Ahandle ;
57 Amatlab = mxCreateSparse (0, 0, 0, mxREAL) ;
58 mxSetM (Amatlab, A->m) ;
59 mxSetN (Amatlab, A->n) ;
60 mxSetNzmax (Amatlab, A->nzmax) ;
61 cs_free (mxGetJc (Amatlab)) ;
62 cs_free (mxGetIr (Amatlab)) ;
63 cs_free (mxGetPr (Amatlab)) ;
64 mxSetJc (Amatlab, (void *) (A->p)) ; /* assign A->p pointer to MATLAB A */
65 mxSetIr (Amatlab, (void *) (A->i)) ;
66 if (A->x == NULL)
67 {
68 /* A is a pattern only matrix; return all 1's to MATLAB */
69 CS_INT i, nz ;
70 nz = A->p [A->n] ;
71 A->x = cs_dl_malloc (CS_MAX (nz,1), sizeof (double)) ;
72 for (i = 0 ; i < nz ; i++)
73 {
74 A->x [i] = 1 ;
75 }
76 }
77 mxSetPr (Amatlab, A->x) ;
78 cs_free (A) ; /* frees A struct only, not A->p, etc */
79 *Ahandle = NULL ;
80 return (Amatlab) ;
81 }
82
83 /* get a real MATLAB dense column vector */
cs_dl_mex_get_double(CS_INT n,const mxArray * X)84 double *cs_dl_mex_get_double (CS_INT n, const mxArray *X)
85 {
86 cs_mex_check (0, n, 1, 0, 0, 1, X) ;
87 return (mxGetPr (X)) ;
88 }
89
90 /* return a double vector to MATLAB */
cs_dl_mex_put_double(CS_INT n,const double * b,mxArray ** X)91 double *cs_dl_mex_put_double (CS_INT n, const double *b, mxArray **X)
92 {
93 double *x ;
94 CS_INT k ;
95 *X = mxCreateDoubleMatrix (n, 1, mxREAL) ; /* create x */
96 x = mxGetPr (*X) ;
97 for (k = 0 ; k < n ; k++) x [k] = b [k] ; /* copy x = b */
98 return (x) ;
99 }
100
101 /* get a MATLAB flint array and convert to CS_INT */
cs_dl_mex_get_int(CS_INT n,const mxArray * Imatlab,CS_INT * imax,int lo)102 CS_INT *cs_dl_mex_get_int (CS_INT n, const mxArray *Imatlab, CS_INT *imax,
103 int lo)
104 {
105 double *p ;
106 CS_INT i, k, *C = cs_dl_malloc (n, sizeof (CS_INT)) ;
107 cs_mex_check (1, n, 1, 0, 0, 1, Imatlab) ;
108 if (mxIsComplex (Imatlab))
109 {
110 mexErrMsgTxt ("integer input cannot be complex") ;
111 }
112 p = mxGetPr (Imatlab) ;
113 *imax = 0 ;
114 for (k = 0 ; k < n ; k++)
115 {
116 i = p [k] ;
117 C [k] = i - 1 ;
118 if (i < lo) mexErrMsgTxt ("index out of bounds") ;
119 *imax = CS_MAX (*imax, i) ;
120 }
121 return (C) ;
122 }
123
124 /* return an CS_INT array to MATLAB as a flint row vector */
cs_dl_mex_put_int(CS_INT * p,CS_INT n,CS_INT offset,int do_free)125 mxArray *cs_dl_mex_put_int (CS_INT *p, CS_INT n, CS_INT offset, int do_free)
126 {
127 mxArray *X = mxCreateDoubleMatrix (1, n, mxREAL) ;
128 double *x = mxGetPr (X) ;
129 CS_INT k ;
130 for (k = 0 ; k < n ; k++) x [k] = (p ? p [k] : k) + offset ;
131 if (do_free) cs_free (p) ;
132 return (X) ;
133 }
134
135 #ifndef NCOMPLEX
136
137 /* copy a MATLAB real or complex vector into a cs_cl complex vector */
cs_cl_get_vector(CS_INT n,CS_INT size,const mxArray * Xmatlab)138 static cs_complex_t *cs_cl_get_vector (CS_INT n, CS_INT size,
139 const mxArray *Xmatlab)
140 {
141 CS_INT p ;
142 double *X, *Z ;
143 cs_complex_t *Y ;
144 X = mxGetPr (Xmatlab) ;
145 Z = (mxIsComplex (Xmatlab)) ? mxGetPi (Xmatlab) : NULL ;
146 Y = cs_dl_malloc (size, sizeof (cs_complex_t)) ;
147 for (p = 0 ; p < n ; p++)
148 {
149 Y [p] = X [p] + I * (Z ? Z [p] : 0) ;
150 }
151 return (Y) ;
152 }
153
154 /* get a real or complex MATLAB sparse matrix and convert to cs_cl */
cs_cl_mex_get_sparse(cs_cl * A,int square,const mxArray * Amatlab)155 cs_cl *cs_cl_mex_get_sparse (cs_cl *A, int square, const mxArray *Amatlab)
156 {
157 cs_mex_check (0, -1, -1, square, 1, 1, Amatlab) ;
158 A->m = mxGetM (Amatlab) ;
159 A->n = mxGetN (Amatlab) ;
160 A->p = (CS_INT *) mxGetJc (Amatlab) ;
161 A->i = (CS_INT *) mxGetIr (Amatlab) ;
162 A->nzmax = mxGetNzmax (Amatlab) ;
163 A->x = cs_cl_get_vector (A->p [A->n], A->nzmax, Amatlab) ;
164 A->nz = -1 ; /* denotes a compressed-col matrix, instead of triplet */
165 return (A) ;
166 }
167
168 /* return a complex sparse matrix to MATLAB */
cs_cl_mex_put_sparse(cs_cl ** Ahandle)169 mxArray *cs_cl_mex_put_sparse (cs_cl **Ahandle)
170 {
171 cs_cl *A ;
172 double *x, *z ;
173 mxArray *Amatlab ;
174 CS_INT k ;
175 if (!Ahandle || !CS_CSC ((*Ahandle))) mexErrMsgTxt ("invalid sparse matrix") ;
176 A = *Ahandle ;
177 if (A->x == NULL) mexErrMsgTxt ("invalid complex sparse matrix") ;
178 Amatlab = mxCreateSparse (0, 0, 0, mxCOMPLEX) ;
179 mxSetM (Amatlab, A->m) ;
180 mxSetN (Amatlab, A->n) ;
181 mxSetNzmax (Amatlab, A->nzmax) ;
182 cs_cl_free (mxGetJc (Amatlab)) ;
183 cs_cl_free (mxGetIr (Amatlab)) ;
184 cs_cl_free (mxGetPr (Amatlab)) ;
185 cs_cl_free (mxGetPi (Amatlab)) ;
186 mxSetJc (Amatlab, (void *) (A->p)) ; /* assign A->p pointer to MATLAB A */
187 mxSetIr (Amatlab, (void *) (A->i)) ;
188 x = cs_dl_malloc (A->nzmax, sizeof (double)) ;
189 z = cs_dl_malloc (A->nzmax, sizeof (double)) ;
190 for (k = 0 ; k < A->nzmax ; k++)
191 {
192 x [k] = creal (A->x [k]) ; /* copy and split numerical values */
193 z [k] = cimag (A->x [k]) ;
194 }
195 cs_cl_free (A->x) ; /* free copy of complex values */
196 mxSetPr (Amatlab, x) ; /* x and z will not be NULL, even if nz==0 */
197 mxSetPi (Amatlab, z) ;
198 cs_cl_free (A) ; /* frees A struct only, not A->p, etc */
199 *Ahandle = NULL ;
200 return (Amatlab) ;
201 }
202
203 /* get a real or complex MATLAB dense column vector, and copy to cs_complex_t */
cs_cl_mex_get_double(CS_INT n,const mxArray * X)204 cs_complex_t *cs_cl_mex_get_double (CS_INT n, const mxArray *X)
205 {
206 cs_mex_check (0, n, 1, 0, 0, 1, X) ;
207 return (cs_cl_get_vector (n, n, X)) ;
208 }
209
210 /* copy a complex vector back to MATLAB and free it */
cs_cl_mex_put_double(CS_INT n,cs_complex_t * b)211 mxArray *cs_cl_mex_put_double (CS_INT n, cs_complex_t *b)
212 {
213 double *x, *z ;
214 mxArray *X ;
215 CS_INT k ;
216 X = mxCreateDoubleMatrix (n, 1, mxCOMPLEX) ; /* create x */
217 x = mxGetPr (X) ;
218 z = mxGetPi (X) ;
219 for (k = 0 ; k < n ; k++)
220 {
221 x [k] = creal (b [k]) ; /* copy x = b */
222 z [k] = cimag (b [k]) ;
223 }
224 cs_cl_free (b) ;
225 return (X) ;
226 }
227 #endif
228