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